Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rocin.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: Rocin.C,v 1.76 2009/04/08 18:01:57 mtcampbe Exp $
24 
28 /* Author John Norris
29  * Initial date: March 19, 2004
30  */
31 /* Modified by Phillip Alexander
32  * April 8, 2004
33  * -updated to Roccom3 compliance
34  * -added support for use as a Roccom module
35  *
36  * Modified by Eric Shaffer
37  * Feb. 20, 2006
38  * - fixes to read Boeing CGNS files
39  */
40 
41 #include <algorithm>
42 #include <set>
43 #include <cmath>
44 #include <cstdlib>
45 #include <fstream>
46 #include <iomanip>
47 #include <iostream>
48 #include <sstream>
49 #include <string>
50 #include <cstring>
51 #include <strings.h>
52 #include <errno.h>
53 #include <iomanip>
54 #include <vector>
55 #include <list>
56 
57 #ifndef _NO_GLOB_
58 #include <glob.h>
59 #endif
60 //#include "Matcher.h"
61 //#include "Pattern.h"
62 #include <fnmatch.h>
63 #include <unistd.h>
64 #include <sys/types.h>
65 #include <dirent.h>
66 #include "Directory.H"
67 //#endif
68 
69 #include "Rocin.h"
70 
71 #ifndef DOXYGEN_SHOULD_SKIP_THIS
72 USE_COM_NAME_SPACE
73 #endif
74 
75 // #define DEBUG_DUMP_PREFIX "."
76 // #define DEBUG_MSG(x) std::cout << "ROCIN DEBUG: " << __LINE__ << ": " << x << std::endl
77 #define DEBUG_MSG(x)
78 
79 #ifdef DEBUG_DUMP_PREFIX
80 static void DebugDump(std::ofstream& fout, int n, int dType, void* data)
81 {
82  int i;
83  switch (dType) {
84  case COM_CHAR:
85  case COM_CHARACTER: {
86  char* p = (char*)data;
87  for (i=0; i<n; ++i)
88  fout << i << ": " << (int)p[i] << '\n';
89  break; }
90  case COM_INT:
91  case COM_INTEGER: {
92  int* p = (int*)data;
93  for (i=0; i<n; ++i)
94  fout << i << ": " << p[i] << '\n';
95  break; }
96  case COM_FLOAT:
97  case COM_REAL: {
98  float* p = (float*)data;
99  for (i=0; i<n; ++i)
100  fout << i << ": " << p[i] << '\n';
101  break; }
102  case COM_DOUBLE:
103  case COM_DOUBLE_PRECISION: {
104  double* p = (double*)data;
105  for (i=0; i<n; ++i)
106  fout << i << ": " << p[i] << '\n';
107  break; }
108  default:
109  fout << "Unhandled COM datatype " << dType << std::endl;
110  break;
111  }
112 }
113 #endif // DEBUG_DUMP_PREFIX
114 
118 #ifndef _NO_GLOB_
119 static int glob_error(const char* epath, int gerrno)
120 {
121  if ( !COMMPI_Initialized())
122  std::cerr << "Rocstar: Error (glob): error in pattern `" << epath << "': "
123  << strerror(gerrno) << std::endl;
124  return 0;
125 }
126 
127 
129 template < class T>
130 inline T cast_err_func( int (*glob)(const char *, int, T, glob_t*),
131  int (*errfunc)(const char*, int))
132 { return reinterpret_cast<T>(errfunc); }
133 #endif
134 
144 #define HDF4_CHECK_RET(routine, args, retval) \
145  { \
146  if((routine args) == FAIL) { \
147  sleep(1); \
148  if((routine args) == FAIL) { \
149  sleep(1); \
150  if((routine args) == FAIL) { \
151  sleep(1); \
152  if((routine args) == FAIL) { \
153  std::cerr << "Rocstar: Error: " #routine " (line " \
154  << __LINE__ << " in " << __FILE__ << ") failed: " \
155  << HDF4::error_msg() << std::endl; \
156  retval; \
157  } } } } \
158  }
159 /*
160 #define HDF4_CHECK_RET(routine, args, retval) \
161 { \
162  if ((routine args) == FAIL) { \
163  std::cerr << "Rocstar: Error: " #routine " (line " \
164  << __LINE__ << " in " << __FILE__ << ") failed: " \
165  << HDF4::error_msg() << std::endl; \
166  retval; \
167  } \
168 }
169 */
170 #define HDF4_CHECK(routine, args) HDF4_CHECK_RET(routine, args, )
171 
178 template <typename T1, typename T2 = T1>
180 {
181  public:
182  inline AutoCloser(T1 id, T2 (*f)(T1)) : m_id(id), m_close(f) {}
183  inline ~AutoCloser() { m_close(m_id); }
184  private:
185  T1 m_id;
186  T2 (*m_close)(T1);
187 };
188 
189 #ifdef USE_CGNS
190 
200 # define CG_CHECK_RET(routine, args, retval) \
201 { \
202  int ier = routine args; \
203  if (ier != 0) { \
204  std::cerr << "Rocstar: Error: " #routine " (line " \
205  << __LINE__ << " in " << __FILE__ << ") failed: " \
206  << cg_get_error() << std::endl; \
207  retval; \
208  } \
209 }
210 # define CG_CHECK(routine, args) CG_CHECK_RET(routine, args, )
211 
217 class AutoCDer
218 {
219  public:
220  inline AutoCDer()
221  : m_cwd(getcwd(NULL, 0)) {}
222  inline ~AutoCDer() { chdir(m_cwd); free(m_cwd); }
223 
224  private:
225  char* m_cwd;
226 };
227 
231 bool elementType_to_string(ElementType_t etype, std::string & roccom_elem)
232 {
233 
234 switch (etype) /* type of CGNS element */
235  {
236 
237  case BAR_2: roccom_elem = ":b2:";
238  break;
239  case BAR_3: roccom_elem = ":b3:" ;
240  break;
241  case TRI_3: roccom_elem = ":t3:";
242  break;
243  case TRI_6: roccom_elem = ":t6:" ;
244  break;
245  case QUAD_4: roccom_elem = ":q4:" ;
246  break;
247  case QUAD_8: roccom_elem = ":q8:" ;
248  break;
249  case QUAD_9: roccom_elem = ":q9:" ;
250  break;
251  case TETRA_4: roccom_elem = ":T4:" ;
252  break;
253  case TETRA_10: roccom_elem = ":T10:";
254  break;
255  case PYRA_5: roccom_elem = ":P5:";
256  break;
257  case PYRA_14: roccom_elem = ":P14:" ;
258  break;
259  case PENTA_6: roccom_elem = ":P6:" ;
260  break;
261  case PENTA_15: roccom_elem = ":P15:" ;
262  break;
263  case PENTA_18: roccom_elem = ":P18:" ;
264  break;
265  case HEXA_8: roccom_elem = ":B8:" ;
266  break;
267  case HEXA_20: roccom_elem = ":B20:";
268  break;
269  //case 19: roccom_elem = ":B27:";
270  //break;
271  default: std::cerr << "Rocstar: Error: CGNS element type of " << etype << "has no Roccom equivalent\n";
272  return false;
273  }
274  return true;
275 }
276 #endif //ifdef CGNS
277 
278 
285 static int32 FindFirstGeometryDataset(int32 sd_id, const std::string& geomFile,
286  const std::string& matName,
287  const std::string& label, int32 hIndex,
288  int32* index)
289 {
290  int32 geom_id;
291  if (geomFile.empty()) {
292  // We're not using a separate geometry file, so just return the dataset
293  // immediately after the block header.
294  geom_id = sd_id;
295  *index = hIndex + 1;
296  return geom_id;
297  }
298 
299  // Open the geometry file.
300  HDF4_CHECK_RET(geom_id = HDF4::SDstart, (geomFile.c_str(), DFACC_READ),
301  return FAIL);
302 
303  // Get the number of datasets.
304  int32 dsCount = MAX_NC_VARS, nAttrs, status;
305  HDF4_CHECK(HDF4::SDfileinfo, (geom_id, &dsCount, &nAttrs));
306 
307  int32 sds_id, rank, size[5], dType;
308  char name[MAX_NC_NAME];
309  // We're looking for the dataset for this material and section.
310  std::string target = matName + '|' + label;
311 
312  // Scan through the datasets of the geometry file.
313  for (*index=0; *index<dsCount; ++(*index)) {
314  HDF4_CHECK_RET(sds_id = HDF4::Select,
315  (geom_id, *index, name, &rank, size, &dType, &nAttrs, dsCount),
316  HDF4::SDend(geom_id); return FAIL);
317 
319  (sds_id, NULL, NULL, NULL, name, MAX_NC_NAME),
320  HDF4::SDendaccess(sds_id); continue);
321  HDF4::SDendaccess(sds_id);
322 
323  // Check if this is the right dataset.
324  if (strcasecmp(target.c_str(), name) == 0) { // We've found it!
325  return geom_id;
326  }
327  }
328 
329  // No luck.
330  HDF4::SDend(geom_id);
331  return FAIL;
332 }
333 
340 static void scan_files_HDF4( int pathc, char* pathv[],
341  BlockMM_HDF4& blocks, std::string& time,
342  std::map<int32, COM_Type>& HDF2COM)
343 {
344  int32 sd_id, geom_id, sds_id, nDataSets, nAttrs, index, index3;
345  int32 rank, dType, start[1];
346  int32 size[5] = { 0, 0, 0, 0, 0 };
347  int32 geomIdx[3];
348  char name[MAX_NC_NAME], label[MAX_NC_NAME];
349  char timeLevel[MAX_NC_NAME], units[MAX_NC_NAME];
350  char matName[MAX_NC_NAME], varName[MAX_NC_NAME], varType[MAX_NC_NAME];
351  int xyz;
352  int numPoints=0, ghostPoints, gc, gridType=0;
353  std::vector<int> ghostCells;
354  char grid[32], ghost[32], location;
355  std::string geomFile;
356  char buffer[1024];
357  Block_HDF4* block;
358  int i;
359 
360  blocks.clear();
361 
362  // Iterate through each file.
363  for (i=0; i<pathc; ++i) {
364  // Make sure this is an HDF file.
365  if (strcmp(&pathv[i][strlen(pathv[i])-4], ".hdf") != 0
366  && strcmp(&pathv[i][strlen(pathv[i])-5], ".hdf4") != 0)
367  continue;
368 
369  HDF4_CHECK_RET(sd_id = HDF4::SDstart, (pathv[i], DFACC_READ), continue);
370  AutoCloser<int32, intn> auto0(sd_id, HDF4::SDend);
371 
372  // Determine the number of datasets.
373  HDF4_CHECK_RET(HDF4::SDfileinfo, (sd_id, &nDataSets, &nAttrs),
374  continue);
375 
376  // Iterate through the datasets.
377  for (index=0; index<nDataSets; ++index) {
378  // Select each non-"fakeDim" dataset in the file.
379  HDF4_CHECK_RET(sds_id = HDF4::Select,
380  (sd_id, index, name, &rank, size, &dType, &nAttrs, nDataSets),
381  continue);
382 
383  {
385 
386  // Get the paneId ('label'), time level ('timeLevel'),
387  // dataset type ('varName'), and window name ('matName').
389  (sds_id, label, timeLevel, varName, matName, MAX_NC_NAME),
390  continue);
391 
392  // If this isn't a block header, then it isn't interesting.
393  if (strncasecmp(varName, "block header", 12) != 0) {
394  continue;
395  } else {
396  // Otherwise, set the time level if not yet set, and skip
397  // the blocks that have different time levels.
398  if (time.empty())
399  time = timeLevel;
400  else if (time != timeLevel)
401  continue;
402  }
403 
404  // Block header datasets should have only one dimension.
405  if (rank != 1) {
406  std::cerr << "Rocstar: Warning: Dataset " << index << " in file " << pathv[i]
407  << " is marked as a block header, but its rank is not 1 "
408  << "(rank == " << rank << ')' << std::endl;
409  continue;
410  }
411 
412  ghostCells.clear();
413  geomFile.erase();
414  if (dType == DFNT_CHAR8) {
415  // This data file is written for version 1.1. Good!
416  start[0] = 0;
417  std::vector<char8> data(size[0]);
419  (sds_id, start, NULL, size, (VOIDP)&data[0]),
420  continue);
421 
422  // Parse the data into grid type, ghost info, and external
423  // geometry file.
424  std::istringstream sin(&data[0]);
425  sin.getline(grid, sizeof(grid), '|');
426  sin.getline(ghost, sizeof(ghost), '|');
427  buffer[0] = '\0';
428  sin >> buffer;
429 
430  // The first token is the grid type.
431  if (strcasecmp(grid, "structured") == 0 || strcmp(grid, "2") == 0) {
432  gridType = 2;
433  } else if (strcasecmp(grid, "unstructured") == 0
434  || strcmp(grid, "3") == 0) {
435  gridType = 3;
436  } else if (strcasecmp(grid, "discontinuous") == 0
437  || strcmp(grid, "4") == 0) {
438  gridType = 4;
439  } else if (strcasecmp(grid, "polydata") == 0
440  || strcmp(grid, "5") == 0) {
441  gridType = 5;
442  } else {
443  std::cerr << "Rocstar: Warning: The block header (dataset " << index
444  << " in file " << pathv[i] << ") does not have a "
445  << "valid grid type (grid = " << grid << ')'
446  << std::endl;
447  }
448 
449  // The second token is the number of ghost points and cells. If
450  // there is a single number, then this is (probably) the number of
451  // layers of ghost cells on a structured grid. Otherwise, it's the
452  // number of ghost points followed by the number of ghost cells of
453  // each connectivity table of an unstructured grid.
454  // WARNING: When using external grid files, the ghost data will
455  // probably not be accurate!
456 
457  ghostPoints = 0;
484  gc = atoi(ghost);
485  char* c = strchr(ghost, ',');
486  if (c != NULL) {
487  ++c;
488  ghostPoints = gc;
489  gc = atoi(c);
490  c = strchr(c, ',');
491  }
492  if (gc < 0) std::cerr << "Rocstar: Warning: Bad num ghosts " << gc << " from string: " << ghost << std::endl;
493  ghostCells.push_back(gc);
494  // Check if there are more data.
495  while (c != NULL) {
496  ++c;
497  gc = atoi(c);
498  c = strchr(c, ',');
499  if (gc < 0) std::cerr << "Rocstar: Warning: Bad ghosts " << gc << std::endl;
500  ghostCells.push_back(gc);
501  }
502 
503  // The third token (if present) is an external geometry file.
504  if (buffer[0] != '\0') {
505  if (buffer[0] == '/') {
506  geomFile = buffer;
507  } else {
508  // Normalize the filename.
509  geomFile = pathv[i];
510  std::string::size_type pos = geomFile.find_last_of('/');
511  if (pos != std::string::npos) {
512  geomFile.erase(pos + 1);
513  geomFile += buffer;
514 
515  // If normalized filename does not exist, then
516  // try to find the mesh file with the given name.
517  struct stat sb;
518  if (stat(geomFile.c_str(), &sb) != 0)
519  geomFile = buffer;
520  }
521  else
522  geomFile = buffer;
523  }
524 
525  // Make sure the file exists.
526  struct stat sb;
527  if (stat(geomFile.c_str(), &sb) != 0) {
528  std::cerr << "Rocstar: Warning: The block header (dataset " << index
529  << " in file " << pathv[i] << ") has an invalid "
530  << "filename for the external geometry data. The "
531  << "file does not exist: " << geomFile << std::endl;
532  continue;
533  }
534  }
535  } else {
536  std::cerr << "Rocstar: Warning: Dataset " << index << " in file " << pathv[i]
537  << " is marked as a block header, but its datatype is "
538  << "not char8." << std::endl;
539  continue;
540  }
541  }
542 
543  geom_id = FindFirstGeometryDataset(sd_id, geomFile, matName, label,
544  index, &index3);
545  if (geom_id == FAIL) {
546  std::cerr << "Rocstar: Warning: Could not open geometry dataset for section "
547  << label << " of material " << matName << std::endl;
548  continue;
549  }
550 
551  // Collect data on the nodal coordinate datasets.
552  for (xyz=0; xyz<6; xyz+=2,++index3) {
553  HDF4_CHECK_RET(sds_id = HDF4::Select,
554  (geom_id, index3, name, &rank, size, &dType, &nAttrs),
555  continue);
557 
558  geomIdx[xyz/2] = index3;
559 
560  if (xyz == 0) {
561  units[0] = '\0';
562  if ((gridType == 2 && rank != 3) || (gridType != 2 && rank != 1)) {
563  numPoints = size[0] = size[1] = size[2] = 0;
564  geomIdx[0] = geomIdx[1] = geomIdx[2] = FAIL;
565  break;
566  }
567 
569  (sds_id, name, units, NULL, varType, MAX_NC_NAME));
570 
571  if (gridType == 2) {
572  numPoints = size[0] * size[1] * size[2];
573  } else {
574  char* pos = strchr(name, '|');
575 
576  if (pos && *(pos+2)=='0')
577  numPoints = ghostPoints = 0; // Empty pane.
578  else {
579  numPoints = size[0];
580  // Get a trustworthy count of the number of ghost nodes.
581  std::istringstream in(pos+3);
582  in >> ghostPoints;
583  }
584  }
585  }
586  }
587 
588  // Determine the pane id. Skip any non-numeric prefix such as "block".
589  std::string lbl(label);
590  std::string::size_type pos = lbl.find_first_of("0123456789");
591  if (pos != std::string::npos)
592  lbl.erase(0, pos);
593 
594  std::istringstream sin(lbl);
595  int paneId;
596  sin >> paneId;
597 
598  // Create and initialize a Block object.
599  block = new Block_HDF4(pathv[i], geomFile, geomIdx, paneId, timeLevel,
600  units, numPoints, ghostPoints);
601 
602  // Add grid info.
603  if (gridType == 2) {
604  // Structured grids only have dimensions.
605  block->m_gridInfo.push_back(GridInfo_HDF4(size, ghostCells[0]));
606  } else {
607  // Get info for each connectivity table. If we were given ghost
608  // cell info, then we know how many connectivity tables we have.
609  // Otherwise we have to keep going until we find a dataset that is
610  // obviously not a connectivity table.
611  std::vector<int>::iterator p;
612  for (p=ghostCells.begin();
613  ghostCells.empty() || p!=ghostCells.end();
614  ++p,++index3) {
615  sds_id = HDF4::Select(geom_id, index3, name, &rank, size,
616  &dType, &nAttrs);
617  if (sds_id == FAIL) {
618  if (!ghostCells.empty())
619  std::cerr << "Rocstar: Warning: Select() failed on connectivity dataset "
620  << index3 << " in file "
621  << (geomFile.empty() ? pathv[i] : geomFile.c_str())
622  << std::endl;
623  break;
624  }
626 
627  // If the rank isn't 2, then it's not a connectivity table.
628  if (rank != 2) {
629  break;
630  }
631 
632  // Get metadata on the connectivity table.
634  (sds_id, label, units, varName, varType, MAX_NC_NAME),
635  continue);
636 
637  int ghostCount = 0;
638  if (!ghostCells.empty())
639  ghostCount = *p;
640 
641  // A connectivity table must start with ':'
642  if (varName[0] != ':') { /* Old, pre-roccom3 dataset */
643  /* HIDEOUS HACK: should figure out real element type */
644  if (gridType == 3 || gridType == 4) {
645  if (size[0] == 4)
646  strcpy(varName,":T4:");
647  else if (size[0] == 5)
648  strcpy(varName,":P5:");
649  else if (size[0] == 6)
650  strcpy(varName,":P6:");
651  else if (size[0] == 8)
652  strcpy(varName,":B8:");
653  else if (size[0] == 10)
654  strcpy(varName,":T10:");
655  else if (size[0] == 20)
656  strcpy(varName,":B20:");
657  else
658  strcpy(varName,":unknown");
659  } else if (gridType == 5) {
660  if (size[0] == 3)
661  strcpy(varName,":t3:");
662  else if (size[0] == 4)
663  strcpy(varName,":q4:");
664  else if (size[0] == 6)
665  strcpy(varName,":t6:");
666  else if (size[0] == 8)
667  strcpy(varName,":q8:");
668  else
669  strcpy(varName,":unknown");
670  } else {
671  strcpy(varName,":unknown");
672  }
673 
674  if (1) {
675  std::cerr << "Rocstar: Warning: reading old-style connectivity dataset "
676  << varName << " from " << index3 << " in file "
677  << (geomFile.empty() ? pathv[i] : geomFile.c_str())
678  << std::endl;
679  }
680  } else {
681  // If the table is empty, set number of elements to 0.
682  char* pos = strchr(label, '|');
683  if (pos && *(pos+2)=='0') {
684  size[1] = ghostCount = 0;
685  } else {
686  // Get a trustworthy count of the number of ghost elements.
687  std::istringstream in(pos+3);
688  in >> ghostCount;
689  }
690  }
691 
692  if (size[1]<0 || ghostCount < 0) {
693  std::cerr << "Rocstar: Error: Bad number of element or ghosts for attribute " << varName << " nElem=" << size[1] << " nGhost=" << ghostCount << std::endl;
695  "Bad number of element or ghosts for attribute.");
696  }
697  // Store the mesh info.
698  block->m_gridInfo.push_back(GridInfo_HDF4(varName, size[1], ghostCount, index3));
699  }
700  }
701  if (geom_id != sd_id) {
702  HDF4::SDend(geom_id);
703  } else {
704  index = index3;
705  }
706 
707  // Now search for datasets with variable data.
708  for (++index; index<nDataSets; ++index) {
709  HDF4_CHECK_RET(sds_id = HDF4::Select,
710  (sd_id, index, name, &rank, size, &dType, &nAttrs, nDataSets),
711  continue);
713 
714  // Get metadata on the variable.
716  (sds_id, label, units, varName, varType, MAX_NC_NAME),
717  continue);
718 
719  if (varName[0] == '\0' || varName[0] == ':') {
720  // Hmm, this is a geometry dataset.
721  continue;
722  }
723 
724  if (strncasecmp(varName, "block header", 12) == 0) {
725  // We've found another block header. We're done.
726  // Reverse index by one, as it will be incremented by the outer-loop
727  --index;
728  break;
729  }
730 
731  // Determine the location. Format of label is (FIXME: complete?)
732  // "<component letter: 1,2,3,x,y,z>-<attribute>"
733  // "|<location letter: w,p,c,n,e>"
734  // " AT TIME <time SS.MMMUUU> "
735  int ng=0; bool is_null=false;
736  location = 'w';
737  if ( label[0] != ':') {
738  char* pos = strchr(label, '|');
739  if (pos == NULL) {
740  /* Old HDF file without nice labels. For backward compatability,
741  guess the data location from the size of the data:
742  */
743  int sz=size[0]; // Should this be size[rank-1]?
744 
745  location='p'; /* guess a panel attribute */
746 
747  int num=block->m_numNodes, g=block->m_numGhostNodes;
748  if (num==sz) {location='n'; ng=0; /* nodes */ }
749  num+=g;
750  if (num==sz) {location='n'; ng=g; /* nodes and ghosts */ }
751 
752  if (1) {
753  num=block->m_gridInfo[0].m_numElements; g=block->m_gridInfo[0].m_numGhostElements;
754  if (num==sz) {location='e'; ng=0; /* elements */ }
755  num+=g;
756  if (num==sz) {location='e'; ng=g; /* elements and ghosts */ }
757  }
758 
759  if (0) { /* annoying compatability warning */
760  std::cerr << "Rocstar: Warning: Compatability warning: guessing variable '"
761  << varName << "' in dataset " << index << " in file "
762  << pathv[i] << " with label " << label
763  << " is of type " << location
764  << "(" << sz << ")" << std::endl;
765  /* display size of variable */
766  std::cerr << " size of variable: ";
767  for (int i=0;i<rank;i++) std::cerr<<size[i]<<',';
768  std::cerr << std::endl;
769  }
770  }
771  else { /* New HDF file: gives location of data directly. */
772  location = *(pos + 1);
773  // Also obtain the number of ghost items
774  if ( *(pos+2) == '0')
775  { size[0] = ng = 0; is_null=true; }
776  else if ( (*(pos + 2)==',' || *(pos + 2)=='@'))
777  { ng = std::atoi( pos+3); is_null=*(pos + 2)=='@'; }
778  }
779  }
780 
781  // Determine which component of the variable we're analyzing.
782  std::istringstream str(varType);
783  int vType = 0;
784  str>> vType;
785 
786  int nc = 0;
787  switch (vType) {
788  case 0:
789  // Scalar data.
790  nc = 1;
791  break;
792 
793  case 1:
794  // First component of vector data.
795  nc = 3;
796  break;
797 
798  case 11:
799  // First component of tensor data.
800  nc = 9;
801  break;
802 
803  case 2: case 3: {
804  // Second or third component of vector data.
805  VarInfo_HDF4 &vi = block->m_variables.back();
806  if (vi.m_name != varName || vi.m_indices.size() != 3) {
807  // We shouldn't be seeing 2 or 3 before we see 1.
808  std::cerr << "Rocstar: Warning: Found a vector component named " << varName
809  << " for which there is no X component at "
810  << " dataset " << index << " (" << name
811  << ") in file " << pathv[i] << std::endl;
812  continue;
813  }
814  vi.m_indices[vType-1] = index;
815  vi.m_is_null[vType-1] = is_null;
816  continue;
817  }
818  case 12: case 13:
819  case 21: case 22: case 23:
820  case 31: case 32: case 33: {
821  // Second, third, etc component of tensor data.
822  VarInfo_HDF4 &vi = block->m_variables.back();
823  if (vi.m_name != varName || vi.m_indices.size() != 9) {
824  // We shouldn't be seeing any of these before we see 11.
825  std::cerr << "Rocstar: Warning: Found a tensor component named " << varName
826  << " for which there is no (0,0) component at "
827  << "dataset " << index << " (" << name
828  << ") in file " << pathv[i] << std::endl;
829  continue;
830  }
831  vi.m_indices[3*(vType/10)+(vType%10)-4] = index;
832  vi.m_is_null[3*(vType/10)+(vType%10)-4] = is_null;
833  continue;
834  }
835  default:
836  // I don't know what kind of variable this is supposed to be.
837  // Assuming scalar.
838  vType = 0;
839  nc = 1;
840  break;
841  }
842 
843  int offset = 0; // Starting point for actual attribute name.
844  if ( varName[0]>='0' && varName[0]<='9') {
845  if ( std::strncmp( varName, "1-", 2)==0)
846  offset = 2; // Skip the "1-" part
847  else { // Append to the back
848  VarInfo_HDF4 &vi = block->m_variables.back();
849  unsigned int id = std::atoi( varName);
850  const char *aName = std::strchr(varName, '-');
851 
852  if ( aName==NULL || vi.m_name != (aName+1) ||
853  vi.m_indices.size() != id-1) {
854  // The individual components must be stored consecutively
855  std::cerr << "Rocstar: Warning: Found a vector named " << vi.m_name
856  << " whose components are not stored together "
857  << " in file " << pathv[i] << std::endl;
858  continue;
859  }
860 
861  vi.m_indices.push_back( index);
862  vi.m_is_null.push_back( is_null);
863  DEBUG_MSG("Correction: variable '" << vi.m_name << "' actually has "
864  << vi.m_indices.size() << " components.");
865  continue;
866  }
867  }
868 
869  DEBUG_MSG("Found variable '" << &varName[offset] << "', location == '"
870  << location << "', nComp == " << nc << ", nItems == "
871  << size[0] << ", nGhost == " << ng << ", isNull == "
872  << is_null);
873  block->m_variables.push_back
874  (VarInfo_HDF4(&varName[offset], location, HDF2COM[dType],
875  units, nc, index, size[0], ng, is_null));
876  }
877  blocks.insert(BlockMM_HDF4::value_type(matName, block));
878  }
879  }
880 }
881 
882 static void load_data_HDF4( BlockMM_HDF4::iterator p,
883  const BlockMM_HDF4::iterator& end,
884  const std::string& window,
885  const MPI_Comm* comm, int rank, int nprocs)
886 {
887  int local, i, ne = 0;
888  Block_HDF4* block;
889  std::string name;
890  bool structured = 0;
891  int32 sd_id = 0, sds_id, start[3], size[3];
892  void* data;
893  std::vector<int32>::iterator r;
894  std::vector<GridInfo_HDF4>::iterator s;
895  int with_pane=0;
896 
897  for ( ; p!=end; ++p, ++with_pane) {
898  block = (*p).second;
899 
900  // Panes are a local construct, so make sure that this pane is local.
901  local = COM_get_status( window.c_str(), block->m_paneId)>=0;
902 
903  if (!local) continue;
904 
905  if (block->m_geomFile.empty()) {
907  (block->m_file.c_str(), DFACC_READ),
908  continue);
909  } else {
911  (block->m_geomFile.c_str(), DFACC_READ),
912  continue);
913  }
914 
915  structured = (block->m_gridInfo.size() &&
916  block->m_gridInfo.front().m_name.substr(0,3)== ":st");
917 
918  // Let Roccom manage memory for nodal coordinates
919  // Moved allocation outside of dimension loop. Not sure if this fully
920  // accounts for single registration of "nc" versus "1-nc", "2-nc", etc.
921 
922  name = window + ".nc";
923  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == " << block->m_paneId << ", ptr == NULL, arg == 0 )");
924  COM_resize_array(name.c_str(), block->m_paneId, NULL, 1);
925 
926  // Read the nodal coordinates.
927  for (i=0; i<3; ++i) {
928  // Read the mesh only if number of nodes is positive
929  name = window + '.' + (char)('1' + i) + "-nc";
930  COM_get_array(name.c_str(), block->m_paneId, &data);
931 
932  if (block->m_numNodes && data) {
933  HDF4_CHECK_RET(sds_id = HDF4::SDselect, (sd_id, block->m_indices[i]),
934  continue);
936 
937  if (structured) {
938  start[0] = start[1] = start[2] = 0;
940  (sds_id, start, NULL, block->m_gridInfo.front().m_size, data));
941  } else {
942  start[0] = 0;
943  size[0] = block->m_numNodes;
944  HDF4_CHECK(HDF4::SDreaddata, (sds_id, start, NULL, size, data));;
945  }
946 #ifdef DEBUG_DUMP_PREFIX
947  {
948  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.' + block->time_level + ".hdf").c_str());
949  DebugDump(fout, block->m_numNodes, COM_DOUBLE, data);
950  }
951 #endif // DEBUG_DUMP_PREFIX
952  }
953  }
954 
955  // Read the connectivity tables.
956  if (!structured) {
957  ne = 0;
958  for (s=block->m_gridInfo.begin(); s!=block->m_gridInfo.end(); ++s) {
959  name = window + "." + (*s).m_name;
960  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == " << block->m_paneId << ", ptr == " << &data << ", arg == 1 )");
961  COM_resize_array(name.c_str(), block->m_paneId, &data, 1);
962 
963  start[0] = start[1] = 0;
964  std::istringstream sin((*s).m_name);
965  sin.get(); sin.get(); // Get rid if the leading two letter.
966  sin >> size[0];
967  size[1] = (*s).m_numElements;
968  ne += (*s).m_numElements;
969 
970  if ( size[1] && data) {
971  HDF4_CHECK_RET(sds_id = HDF4::SDselect, (sd_id, (*s).m_index),
972  continue);
973  HDF4_CHECK(HDF4::SDreaddata, (sds_id, start, NULL, size, data));
974 #ifdef DEBUG_DUMP_PREFIX
975  {
976  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.' + block->time_level + ".hdf").c_str());
977  DebugDump(fout, size[0] * size[1], COM_INT, data);
978  }
979 #endif // DEBUG_DUMP_PREFIX
980  HDF4::SDendaccess(sds_id);
981  }
982  }
983  }
984 
985  if (!block->m_geomFile.empty()) {
986  HDF4::SDend(sd_id);
987  HDF4_CHECK_RET(sd_id = HDF4::SDstart, (block->m_file.c_str(), DFACC_READ),
988  continue);
989  }
990 
991  // Read the attribute data.
992  std::vector<VarInfo_HDF4>::iterator q;
993  for (q=block->m_variables.begin(); q!=block->m_variables.end(); ++q) {
994  // Skip NULL attributes.
995  if ( (*q).m_is_null[0]) continue;
996  // Read in window attribute only for the first pane.
997  if ( with_pane && (*q).m_position=='w') continue;
998 
999  int loop = 1;
1000 
1001  //edited
1002  name = window + '.' + (*q).m_name;
1003  if ( (*q).m_position!='w') { // Allocate for nonwindow attribute
1004  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == " << block->m_paneId << ", ptr == " << &data << ", arg == 1 )");
1005  COM_resize_array(name.c_str(), block->m_paneId, &data,1);
1006  } else {
1007  COM_get_array(name.c_str(), 0, &data);
1008  }
1009 
1010  for (r=(*q).m_indices.begin();
1011  r!=(*q).m_indices.end(); ++r, ++loop) {
1012 
1013  // If scalar, name = window.attribute
1014  // If vector, name = window.#-attribute
1015  if( (*q).m_indices.size()==1)
1016  name = window + '.' + (*q).m_name;
1017  else {
1018  std::ostringstream sout;
1019  sout << window << '.' << loop << '-' << (*q).m_name;
1020  name = sout.str();
1021  }
1022 
1023  COM_get_array(name.c_str(), block->m_paneId,&data);
1024 
1025  bool nonempty;
1026  if (structured && ((*q).m_position=='n' || (*q).m_position=='e')) {
1027  start[0] = start[1] = start[2] = 0;
1028  if ((*q).m_position == 'n') {
1029  size[0] = block->m_gridInfo.front().m_size[0];
1030  size[1] = block->m_gridInfo.front().m_size[1];
1031  size[2] = block->m_gridInfo.front().m_size[2];
1032  } else {
1033  size[0] = std::max(int32(1),
1034  block->m_gridInfo.front().m_size[0]-1);
1035  size[1] = std::max(int32(1),
1036  block->m_gridInfo.front().m_size[1]-1);
1037  size[2] = std::max(int32(1),
1038  block->m_gridInfo.front().m_size[2]-1);
1039  }
1040 
1041  nonempty = block->m_numNodes && data;
1042 
1043  } else {
1044  start[0] = 0;
1045  size[0] = (*q).m_nitems;
1046 
1047  nonempty = size[0] && data;
1048  }
1049 
1050  if ( nonempty) {
1051  HDF4_CHECK_RET(sds_id = HDF4::SDselect, (sd_id, *r), continue);
1052  HDF4_CHECK(HDF4::SDreaddata, (sds_id, start, NULL, size, data));
1053 #ifdef DEBUG_DUMP_PREFIX
1054  {
1055  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.' + block->time_level + ".hdf").c_str());
1056  DebugDump(fout, (*q).m_nitems, (*q).m_dataType, data);
1057  }
1058 #endif // DEBUG_DUMP_PREFIX
1059  HDF4::SDendaccess(sds_id);
1060  }
1061  }
1062  }
1063  HDF4::SDend(sd_id);
1064  }
1065 }
1066 
1067 #ifdef USE_CGNS
1068 
1074 static void scan_files_CGNS( int pathc, char* pathv[],
1075  BlockMM_CGNS& blocks, std::string& time,
1076  std::map<DataType_t, COM_Type>& CGNS2COM)
1077 {
1078  bool has_timesteps = true; //Boeing fix
1079  double t = -1.0;
1080  std::string timeLevel;
1081  Block_CGNS* block;
1082 
1083 
1084  if (!time.empty()) {
1085  std::istringstream in(time);
1086  in >> t;
1087 
1088  std::ostringstream sout;
1089  sout << t;
1090  timeLevel = sout.str();
1091  }
1092 
1093  blocks.clear();
1094 
1095  // Iterate through each file.
1096  int i;
1097  for (i=0; i<pathc; ++i) {
1098  // Make sure this is a CGNS file.
1099  if (strcmp(&pathv[i][strlen(pathv[i])-5], ".cgns") != 0)
1100  continue;
1101 
1102  AutoCDer autoCD;
1103  std::string fname(pathv[i]);
1104  std::string::size_type cloc = fname.rfind('/');
1105  if (cloc != std::string::npos) {
1106  chdir(fname.substr(0, cloc).c_str());
1107  fname.erase(0, cloc + 1);
1108  }
1109 
1110  int fn;
1111  CG_CHECK_RET(cg_open, (fname.c_str(), MODE_READ, &fn), continue);
1112  AutoCloser<int> auto0(fn, cg_close);
1113 
1114  // Determine the number of bases.
1115  int nBases;
1116  CG_CHECK_RET(cg_nbases, (fn, &nBases), continue);
1117 
1118  // Iterate through the bases.
1119  char buffer[33];
1120  int B;
1121  for (B=1; B<=nBases; ++B) {
1122  // Get the name of the base/material/window, as well as the dimensions.
1123  // Physical dimensions should always be 3 in Roccom, but cell dims will
1124  // be 2 for surface meshes.
1125  char baseName[33];
1126  int cellDim, physDim;
1127  CG_CHECK_RET(cg_base_read, (fn, B, baseName, &cellDim, &physDim),
1128  continue);
1129 
1130  // If the baseName ends with "_ridges" then ignore it.
1131  int nameLen = std::strlen(baseName);
1132  if (nameLen > 7 && std::strcmp(&baseName[nameLen-7], "_ridges") == 0)
1133  continue;
1134 
1135  // If the no time was given, use the first time that we find.
1136  if (timeLevel.empty()) {
1137  int nSteps;
1138 
1139  int error_code = cg_biter_read(fn, B, buffer, &nSteps);
1140  if (error_code == CG_NODE_NOT_FOUND) {
1141  std::cerr << "Rocstar: Warning: cg_biter_read() failed with CG_NODE_NOT_FOUND"
1142  << " on Base " << B << " in file " << pathv[i] << std::endl;
1143  std::cerr << "Rocstar: Warning: No time steps given with Base "<< B <<std::endl;
1144  has_timesteps = false; //Boeing fix
1145  } else if (error_code == CG_ERROR) {
1146  std::cerr << "Rocstar: Warning: cg_biter_read() failed with CG_ERROR on Base " << B
1147  << " in file " << pathv[i] << std::endl;
1148  continue;
1149  }
1150  if (has_timesteps) {
1151  CG_CHECK(cg_goto, (fn, B, "BaseIterativeData_t", 1, "end"));
1152 
1153  std::vector<double> times(nSteps);
1154 
1155  CG_CHECK(cg_array_read_as, (1, RealDouble, &times[0]));
1156 
1157  int ti;
1158  for (ti=0; ti<nSteps; ++ti)
1159  DEBUG_MSG("Time " << ti << " == " << times[ti]);
1160 
1161  std::ostringstream sout;
1162  sout << times[0];
1163  timeLevel = sout.str();
1164  DEBUG_MSG("timeLevel == " << timeLevel);
1165 
1166  //WHAT'S THE STANDARD FORMAT FOR TIME STRINGS????
1167  sprintf(buffer, "%9.6f", times[0]);
1168  time = buffer;
1169  DEBUG_MSG("time == " << time);
1170  }
1171  }
1172 
1173  int nZones;
1174  CG_CHECK_RET(cg_nzones, (fn, B, &nZones), continue);
1175 
1176 
1177  // Create the name for the GridCoordinates_t node.
1178  // HACK: Assume no timesteps means Boeing CGNS file, and use
1179  // the "GridCoordinates" name. Otherwise default to Rocout
1180  // standard "Grid"
1181  // FIX: Should be a better way to determine which name to use
1182 
1183  std::string gridAttrName;
1184  if (has_timesteps)
1185  {
1186  gridAttrName = "Grid";
1187  if (timeLevel.length() + gridAttrName.length() > 32)
1188  gridAttrName.erase(32 - timeLevel.length());
1189  gridAttrName += timeLevel;
1190  }
1191  else
1192  {
1193  gridAttrName = "GridCoordinates";
1194  }
1195 
1196 
1197  // Create the name for the IntegralData_t node for window attributes.
1198  std::string winAttrName("WinData");
1199  if (timeLevel.length() + winAttrName.length() > 32)
1200  winAttrName.erase(32 - timeLevel.length());
1201  winAttrName += timeLevel;
1202 
1203  // Create the name for the IntegralData_t node for pane attributes.
1204  std::string paneAttrName("PaneData");
1205  if (timeLevel.length() + paneAttrName.length() > 32)
1206  paneAttrName.erase(32 - timeLevel.length());
1207  paneAttrName += timeLevel;
1208 
1209  // Create the name for the IntegralData_t node for connectivity attrs.
1210  std::string connAttrName("ConnData");
1211  if (timeLevel.length() + connAttrName.length() > 32)
1212  connAttrName.erase(32 - timeLevel.length());
1213  connAttrName += timeLevel;
1214 
1215  // Create the name for the FlowSolution_t node for element attributes.
1216  std::string elemAttrName("ElemData");
1217  if (timeLevel.length() + elemAttrName.length() > 32)
1218  elemAttrName.erase(32 - timeLevel.length());
1219  elemAttrName += timeLevel;
1220 
1221  // Create the name for the FlowSolution_t node for node attributes.
1222  std::string nodeAttrName("NodeData");
1223  if (timeLevel.length() + nodeAttrName.length() > 32)
1224  nodeAttrName.erase(32 - timeLevel.length());
1225  nodeAttrName += timeLevel;
1226 
1227  int Z;
1228  for (Z=1; Z<=nZones; ++Z) {
1229  int nPoints, nGhostPoints;
1230  std::string units;
1231  char zoneName[33];
1232  int gridSize[3], coreSize[9];
1233  CG_CHECK_RET(cg_zone_read, (fn, B, Z, zoneName, coreSize), continue);
1234 
1235  ZoneType_t zoneType;
1236  CG_CHECK_RET(cg_zone_type, (fn, B, Z, &zoneType), continue);
1237 
1238  int nGrids;
1239  CG_CHECK_RET(cg_ngrids, (fn, B, Z, &nGrids), continue);
1240 
1241  int G, rind[6] = { 0, 0, 0, 0, 0, 0 };
1242  for (G=1; G<=nGrids; ++G) {
1243  CG_CHECK_RET(cg_grid_read, (fn, B, Z, G, buffer), continue);
1244 
1245  if (gridAttrName != buffer)
1246  continue;
1247 
1248  CG_CHECK_RET(cg_goto,
1249  (fn, B, "Zone_t", Z, "GridCoordinates_t", G, "end"),
1250  break);
1251 
1252  if (cg_rind_read(rind) != 0)
1253  std::fill_n(rind, 6, 0);
1254 
1255  if (zoneType == Structured) {
1256  gridSize[0] = coreSize[0] + rind[0] + rind[1];
1257  gridSize[cellDim] = coreSize[cellDim] + rind[0] + rind[1];
1258  nPoints = gridSize[0];
1259  if (cellDim > 1) {
1260  gridSize[1] = coreSize[1] + rind[2] + rind[3];
1261  gridSize[cellDim+1] = coreSize[cellDim+1] + rind[2] + rind[3];
1262  nPoints *= gridSize[1];
1263  if (cellDim > 2) {
1264  gridSize[2] = coreSize[2] + rind[4] + rind[5];
1265  gridSize[5] = coreSize[5] + rind[5] + rind[5];
1266  nPoints *= gridSize[2];
1267  }
1268  }
1269  } else {
1270  nPoints = gridSize[0] = coreSize[0] + rind[0] + rind[1];
1271  }
1272  // Assuming that ROCCOM ghost layers are uniform for structured
1273  // meshes, and ghost nodes are at the end for unstructured meshes.
1274  nGhostPoints = rind[1];
1275 
1276  // Assume that CoordinateX is array 1.
1277  CG_CHECK_RET(cg_goto,
1278  (fn, B, "Zone_t", Z, "GridCoordinates_t", G, "DataArray_t", 1, "end"),
1279  break);
1280 
1281  // Also assume that if one of the coordinate arrays is null, then
1282  // they all are null.
1283  int nDescriptors;
1284  CG_CHECK_RET(cg_ndescriptors, (&nDescriptors), break);
1285 
1286  int D;
1287  char* text = NULL;
1288  for (D=1; D<=nDescriptors; ++D) {
1289  CG_CHECK_RET(cg_descriptor_read, (D, buffer, &text), continue);
1290 
1291  if (strcmp(buffer, "Range") == 0) {
1292  if (strcmp(text, "EMPTY") == 0)
1293  nPoints = nGhostPoints = 0;
1294  } else if (strcmp(buffer, "Units") == 0) {
1295  units = text;
1296  }
1297  free(text);
1298  }
1299 
1300  break;
1301  }
1302 
1303  // Determine the pane id. Skip any non-numeric prefix such as "block".
1304  std::string lbl(zoneName);
1305  std::string::size_type pos = lbl.find_first_of("0123456789");
1306  if (pos != std::string::npos)
1307  lbl.erase(0, pos);
1308 
1309  int paneId;
1310  {
1311  std::istringstream in(lbl);
1312  in >> paneId;
1313  }
1314 
1315  // Create and initialize a Block object.
1316  block = new Block_CGNS(pathv[i], B, Z, G, paneId, timeLevel, units,
1317  nPoints, nGhostPoints);
1318 
1319  if (zoneType == Structured) {
1320  block->m_gridInfo.push_back(GridInfo_CGNS(gridSize, cellDim,
1321  nGhostPoints));
1322  } else {
1323  // Get info on the connectivity tables.
1324  std::string rocElemType;
1325  int nSections;
1326  CG_CHECK_RET(cg_nsections, (fn, B, Z, &nSections),
1327  delete block; continue);
1328 
1329  int totalGhostElems = 0, S;
1330  for (S=1; S<=nSections; ++S) {
1331  ElementType_t elemType;
1332  int iStart, iEnd, iBoundry, pFlag;
1333  CG_CHECK_RET(cg_section_read,
1334  (fn, B, Z, S, buffer, &elemType, &iStart, &iEnd, &iBoundry, &pFlag),
1335  delete block; continue);
1336 
1337  int nElems = iEnd - iStart + 1;
1338  int nGhostElems = 0;
1339  std::string label = buffer;
1340  if (label.substr(0, 4) == "Null") {
1341  nElems = 0;
1342  label.erase(0, 4);
1343  } else if (label.substr(0, 5) == "Empty") {
1344  nElems = 0;
1345  label.erase(0, 5);
1346  } else {
1347  CG_CHECK_RET(cg_goto,
1348  (fn, B, "Zone_t", Z, "Elements_t", S, "end"),
1349  delete block; continue);
1350 
1351  int rind[2];
1352  if (cg_rind_read(rind) == 0)
1353  nGhostElems = rind[1];
1354  }
1355  // Fix for the Boeing fix
1356  // If the conn table name doesn't begin with a ':', it's not
1357  // a Rocout-generated file.
1358  if (label[0] != ':') {
1359  elementType_to_string(elemType, rocElemType);//Boeing Fix
1360  label = rocElemType + label;
1361  }
1362 
1363  totalGhostElems += nGhostElems;
1364  block->m_gridInfo.push_back(GridInfo_CGNS(label, nElems,
1365  nGhostElems));
1366  }
1367  gridSize[1] += totalGhostElems;
1368  }
1369 
1370  // Get the window attributes.
1371  if (cg_goto(fn, B, "end") != 0) {
1372  std::cerr << "Rocstar: Warning: cg_goto() failed to go to Base " << B << " in file "
1373  << pathv[i] << std::endl;
1374  } else {
1375  int nIntegrals;
1376  if (cg_nintegrals(&nIntegrals) != 0) {
1377  std::cerr << "Rocstar: Warning: cg_nintegrals() failed in Base " << B << " in file "
1378  << pathv[i] << std::endl;
1379  } else {
1380  int I;
1381  for (I=1; I<=nIntegrals; ++I) {
1382  CG_CHECK_RET(cg_integral_read, (I, buffer), continue);
1383 
1384  if (winAttrName != buffer)
1385  continue;
1386 
1387  block->m_W = I;
1388 
1389  CG_CHECK_RET(cg_goto, (fn, B, "IntegralData_t", I, "end"), break);
1390 
1391  int nArrays;
1392  CG_CHECK_RET(cg_narrays, (&nArrays), break);
1393 
1394  int A;
1395  for (A=1; A<=nArrays; ++A) {
1396  CG_CHECK_RET(cg_goto, (fn, B, "IntegralData_t", I, "end"),
1397  break);
1398 
1399  DataType_t dataType;
1400  int rank, size[3];
1401  CG_CHECK_RET(cg_array_info, (A, buffer, &dataType, &rank, size),
1402  continue);
1403 
1404  CG_CHECK_RET(cg_goto, (fn, B, "IntegralData_t", I, "DataArray_t", A, "end"),
1405  continue);
1406 
1407  std::string label = buffer;
1408  int nDescriptors;
1409  CG_CHECK_RET(cg_ndescriptors, (&nDescriptors), continue);
1410 
1411  char* text = NULL;
1412  std::string units;
1413  bool isNull = false;
1414  int nGhostItems = 0, D;
1415  for (D=1; D<=nDescriptors; ++D) {
1416  CG_CHECK_RET(cg_descriptor_read, (D, buffer, &text),
1417  continue);
1418 
1419  if (strcmp(buffer, "Range") == 0) {
1420  if (strcmp(text, "EMPTY") == 0) {
1421  nGhostItems = size[0] = 0;
1422  isNull = true;
1423  } else if (strcmp(text, "NULL") == 0)
1424  isNull = true;
1425  } else if (strcmp(buffer, "Ghost") == 0) {
1426  if (size[0] > 0) {
1427  std::istringstream in(text);
1428  in >> nGhostItems;
1429  }
1430  } else if (strcmp(buffer, "Units") == 0) {
1431  units = text;
1432  }
1433  free(text);
1434  }
1435 
1436  int nComps = 1, comp = 0;
1437  std::string::size_type i = label.rfind('#');
1438  if (i != std::string::npos) {
1439  std::istringstream in(&label[i+1]);
1440  in >> comp;
1441  --comp;
1442  in.get(); in.get();
1443  in >> nComps;
1444  label.erase(i);
1445  } else {
1446  i = label.length() - 1;
1447  if (label[i] >= 'X' && label[i] <= 'Z') {
1448  comp = label[i] - 'X';
1449  label.erase(i);
1450  --i;
1451  if (label[i] >= 'X' && label[i] <= 'Z') {
1452  comp += 3 * (label[i] - 'X');
1453  label.erase(i);
1454  nComps = 9;
1455  } else {
1456  nComps = 3;
1457  }
1458  }
1459  }
1460 
1461  if (comp != 0) {
1462  VarInfo_CGNS &vi = block->m_variables.back();
1463  vi.m_indices[comp] = A;
1464  vi.m_is_null[comp] = isNull;
1465  } else {
1466  block->m_variables.push_back
1467  (VarInfo_CGNS(label, 'w', CGNS2COM[dataType], units,
1468  nComps, A, size[0], nGhostItems, isNull));
1469  }
1470  }
1471  break;
1472  }
1473  }
1474  }
1475 
1476  // Get the pane and connectivity attributes.
1477  if (cg_goto(fn, B, "Zone_t", Z, "end") != 0) {
1478  std::cerr << "Rocstar: Warning: cg_goto() failed to go to Zone " << Z << " of Base "
1479  << B << " in file " << pathv[i] << std::endl;
1480  } else {
1481  int nIntegrals;
1482  if (cg_nintegrals(&nIntegrals) != 0) {
1483  std::cerr << "Rocstar: Warning: cg_nintegrals() failed in Zone " << Z << " of Base "
1484  << B << " in file " << pathv[i] << std::endl;
1485  } else {
1486  int I, found = 0;
1487  for (I=1; I<=nIntegrals && found<2; ++I) {
1488  CG_CHECK_RET(cg_integral_read, (I, buffer), continue);
1489 
1490  char attrType;
1491  if (paneAttrName == buffer) {
1492  attrType = 'p';
1493  block->m_P = I;
1494  } else if (connAttrName == buffer) {
1495  attrType = 'c';
1496  block->m_C = I;
1497  } else
1498  continue;
1499 
1500  ++found;
1501 
1502  CG_CHECK_RET(cg_goto,
1503  (fn, B, "Zone_t", Z, "IntegralData_t", I, "end"),
1504  break);
1505 
1506  int nArrays;
1507  CG_CHECK_RET(cg_narrays, (&nArrays), break);
1508 
1509  int A;
1510  for (A=1; A<=nArrays; ++A) {
1511  CG_CHECK_RET(cg_goto,
1512  (fn, B, "Zone_t", Z, "IntegralData_t", I, "end"),
1513  break);
1514 
1515  DataType_t dataType;
1516  int rank, size[3];
1517  CG_CHECK_RET(cg_array_info, (A, buffer, &dataType, &rank, size),
1518  continue);
1519 
1520  CG_CHECK_RET(cg_goto,
1521  (fn, B, "Zone_t", Z, "IntegralData_t", I, "DataArray_t", A, "end"),
1522  continue);
1523 
1524  std::string label = buffer;
1525  int nDescriptors;
1526  CG_CHECK_RET(cg_ndescriptors, (&nDescriptors), continue);
1527 
1528  char* text = NULL;
1529  std::string units;
1530  bool isNull = false;
1531  int nGhostItems = 0, D;
1532  for (D=1; D<=nDescriptors; ++D) {
1533  CG_CHECK_RET(cg_descriptor_read, (D, buffer, &text),
1534  continue);
1535 
1536  if (strcmp(buffer, "Range") == 0) {
1537  if (strcmp(text, "EMPTY") == 0) {
1538  nGhostItems = size[0] = 0;
1539  isNull = true;
1540  } else if (strcmp(text, "NULL") == 0)
1541  isNull = true;
1542  } else if (strcmp(buffer, "Ghost") == 0) {
1543  if (size[0] > 0) {
1544  std::istringstream in(text);
1545  in >> nGhostItems;
1546  }
1547  } else if (strcmp(buffer, "Units") == 0) {
1548  units = text;
1549  }
1550  free(text);
1551  }
1552 
1553  int nComps = 1, comp = 0;
1554  std::string::size_type i = label.rfind('#');
1555  if (i != std::string::npos) {
1556  std::istringstream in(&label[i+1]);
1557  in >> comp;
1558  --comp;
1559  in.get(); in.get();
1560  in >> nComps;
1561  label.erase(i);
1562  } else {
1563  i = label.length() - 1;
1564  if (label[i] >= 'X' && label[i] <= 'Z') {
1565  comp = label[i] - 'X';
1566  label.erase(i);
1567  --i;
1568  if (label[i] >= 'X' && label[i] <= 'Z') {
1569  comp += 3 * (label[i] - 'X');
1570  label.erase(i);
1571  nComps = 9;
1572  } else {
1573  nComps = 3;
1574  }
1575  }
1576  }
1577 
1578  if (comp != 0) {
1579  VarInfo_CGNS &vi = block->m_variables.back();
1580  vi.m_indices[comp] = A;
1581  vi.m_is_null[comp] = isNull;
1582  } else {
1583 //std::cout << "Units now == " << units << std::endl;
1584  block->m_variables.push_back
1585  (VarInfo_CGNS(label, attrType, CGNS2COM[dataType], units,
1586  nComps, A, size[0], nGhostItems, isNull));
1587  }
1588  }
1589  }
1590  }
1591  }
1592 
1593  // Get the element and node attributes.
1594  int nSols;
1595  if (cg_nsols(fn, B, Z, &nSols) != 0) {
1596  std::cerr << "Rocstar: Warning: cg_nsols() failed in Zone " << Z << " of Base "
1597  << B << " in file " << pathv[i] << std::endl;
1598  } else {
1599  GridLocation_t loc;
1600  int S, found = 0;
1601  for (S=1; S<=nSols && found<2; ++S) {
1602  CG_CHECK_RET(cg_sol_info, (fn, B, Z, S, buffer, &loc), continue);
1603 
1604  bool isNodal = false;
1605  if (buffer == elemAttrName ) {
1606  block->m_E = S;
1607  } else if (buffer == nodeAttrName ) {
1608  block->m_N = S;
1609  isNodal = true;
1610  } else
1611  continue;
1612 
1613  ++found;
1614 
1615  CG_CHECK_RET(cg_goto,
1616  (fn, B, "Zone_t", Z, "FlowSolution_t", S, "end"),
1617  break);
1618 
1619  int rind[6];
1620  if (cg_rind_read(rind) != 0)
1621  std::fill_n(rind, 6, 0);
1622 
1623  int nItems;
1624  int start = isNodal ? 0 : 1;
1625  if (zoneType == Structured) {
1626  start *= cellDim;
1627  // Note: the rind values should always be the same.
1628  nItems = coreSize[start] + rind[0] + rind[1];
1629  if (cellDim > 1) {
1630  nItems *= coreSize[start+1] + rind[2] + rind[3];
1631  if (cellDim > 2)
1632  nItems *= coreSize[start+2] + rind[4] + rind[5];
1633  }
1634  } else {
1635  // Note: rind[0] should always be 0.
1636  nItems = coreSize[start] + rind[0] + rind[1];
1637  }
1638 
1639  int nFields;
1640  CG_CHECK_RET(cg_nfields, (fn, B, Z, S, &nFields), break);
1641 
1642  int F;
1643  for (F=1; F<=nFields; ++F) {
1644  DataType_t dataType;
1645  CG_CHECK_RET(cg_field_info, (fn, B, Z, S, F, &dataType, buffer),
1646  continue);
1647 
1648  CG_CHECK_RET(cg_goto,
1649  (fn, B, "Zone_t", Z, "FlowSolution_t", S, "DataArray_t", F, "end"),
1650  continue);
1651 
1652  std::string label = buffer;
1653  int nDescriptors;
1654  CG_CHECK_RET(cg_ndescriptors, (&nDescriptors), continue);
1655 
1656  char* text = NULL;
1657  std::string units;
1658  bool isNull = false;
1659  int D;
1660  for (D=1; D<=nDescriptors; ++D) {
1661  CG_CHECK_RET(cg_descriptor_read, (D, buffer, &text), continue);
1662 
1663  if (strcmp(buffer, "Range") == 0) {
1664  if (strcmp(text, "EMPTY") == 0) {
1665  rind[1] = nItems = 0;
1666  isNull = true;
1667  } else if (strcmp(text, "NULL") == 0)
1668  isNull = true;
1669  } else if (strcmp(buffer, "Units") == 0)
1670  units = text;
1671  free(text);
1672  }
1673 
1674  int nComps = 1, comp = 0;
1675  std::string::size_type i = label.rfind('#');
1676  if (i != std::string::npos) {
1677  std::istringstream in(&label[i+1]);
1678  in >> comp;
1679  --comp;
1680  in.get(); in.get();
1681  in >> nComps;
1682  label.erase(i);
1683  } else {
1684  i = label.length() - 1;
1685  if (label[i] >= 'X' && label[i] <= 'Z') {
1686  comp = label[i] - 'X';
1687  label.erase(i);
1688  --i;
1689  if (label[i] >= 'X' && label[i] <= 'Z') {
1690  comp += 3 * (label[i] - 'X');
1691  label.erase(i);
1692  nComps = 9;
1693  } else {
1694  nComps = 3;
1695  }
1696  }
1697  }
1698 
1699  if (comp != 0) {
1700  // We assume that components are contiguous and in order.
1701  VarInfo_CGNS &vi = block->m_variables.back();
1702  if (vi.m_name != label)
1703  std::cerr << "Rocstar: Warning: attributes for " << label
1704  << " are not contiguous." << std::endl;
1705  else if (vi.m_indices.size() != nComps)
1706  std::cerr << "Rocstar: Warning: attribute " << label
1707  << " has inconsistent component count."
1708  << std::endl;
1709  vi.m_indices[comp] = F;
1710  vi.m_is_null[comp] = isNull;
1711  } else {
1712  block->m_variables.push_back
1713  (VarInfo_CGNS(label, isNodal ? 'n' : 'e', CGNS2COM[dataType],
1714  units, nComps, F, nItems, rind[1], isNull));
1715  }
1716  }
1717  }
1718  }
1719 
1720  // Check for old node attributes.
1721  int nDiscrete;
1722  if (cg_ndiscrete(fn, B, Z, &nDiscrete) != 0) {
1723  std::cerr << "Rocstar:Warning: cg_ndiscrete() failed in Zone " << Z << " of Base "
1724  << B << " in file " << pathv[i] << std::endl;
1725  } else {
1726  int S;
1727  for (S=1; S<=nDiscrete; ++S) {
1728  CG_CHECK_RET(cg_discrete_read, (fn, B, Z, S, buffer), continue);
1729 
1730  if (nodeAttrName != buffer)
1731  continue;
1732 
1733  block->m_N = S;
1734 
1735  CG_CHECK_RET(cg_goto,
1736  (fn, B, "Zone_t", Z, "DiscreteData_t", S, "end"),
1737  break);
1738 
1739  int rind[6];
1740  if (cg_rind_read(rind) != 0)
1741  std::fill_n(rind, 6, 0);
1742 
1743  int nItems;
1744  if (zoneType == Structured) {
1745  // Note: the rind values should always be the same.
1746  nItems = coreSize[0] + rind[0] + rind[1];
1747  if (cellDim > 1) {
1748  nItems *= coreSize[1] + rind[2] + rind[3];
1749  if (cellDim > 2)
1750  nItems *= coreSize[2] + rind[4] + rind[5];
1751  }
1752  } else {
1753  // Note: rind[0] should always be 0.
1754  nItems = coreSize[0] + rind[0] + rind[1];
1755  }
1756 
1757  int nArrays;
1758  CG_CHECK_RET(cg_narrays, (&nArrays), break);
1759 
1760  int A;
1761  for (A=1; A<=nArrays; ++A) {
1762  CG_CHECK_RET(cg_goto,
1763  (fn, B, "Zone_t", Z, "DiscreteData_t", S, "end"),
1764  break);
1765 
1766  DataType_t dataType;
1767  int rank, size[3];
1768  CG_CHECK_RET(cg_array_info, (A, buffer, &dataType, &rank, size),
1769  continue);
1770  std::string label = buffer;
1771 
1772  // 'rank' should equal the cell dimension for structured,
1773  // 1 for unstructured grids. 'size' should be the core size
1774  // plus rind layers.
1775  COM_assertion_msg(rank = (zoneType == Structured ? cellDim : 1),
1776  ("Bad rank for nodal attribute '"
1777  + label + "'\n").c_str());
1778  // TODO: Verify the size, too.
1779 
1780  CG_CHECK_RET(cg_goto,
1781  (fn, B, "Zone_t", Z, "DiscreteData_t", S, "DataArray_t", A, "end"),
1782  continue);
1783 
1784  int nDescriptors;
1785  CG_CHECK_RET(cg_ndescriptors, (&nDescriptors), continue);
1786 
1787  char* text = NULL;
1788  std::string units;
1789  bool isNull = false;
1790  int D;
1791  for (D=1; D<=nDescriptors; ++D) {
1792  CG_CHECK_RET(cg_descriptor_read, (D, buffer, &text), continue);
1793 
1794  if (strcmp(buffer, "Range") == 0) {
1795  if (strcmp(text, "EMPTY") == 0) {
1796  rind[1] = nItems = 0;
1797  isNull = true;
1798  } else if (strcmp(text, "NULL") == 0)
1799  isNull = true;
1800  } else if (strcmp(buffer, "Units") == 0)
1801  units = text;
1802  free(text);
1803  }
1804 
1805  int nComps = 1, comp = 0;
1806  std::string::size_type i = label.rfind('#');
1807  if (i != std::string::npos) {
1808  std::istringstream in(&label[i+1]);
1809  in >> comp;
1810  --comp;
1811  in.get(); in.get();
1812  in >> nComps;
1813  label.erase(i);
1814  } else {
1815  i = label.length() - 1;
1816  if (label[i] >= 'X' && label[i] <= 'Z') {
1817  comp = label[i] - 'X';
1818  label.erase(i);
1819  --i;
1820  if (label[i] >= 'X' && label[i] <= 'Z') {
1821  comp += 3 * (label[i] - 'X');
1822  label.erase(i);
1823  nComps = 9;
1824  } else {
1825  nComps = 3;
1826  }
1827  }
1828  }
1829 
1830  if (comp != 0) {
1831  // We assume that components are contiguous and in order.
1832  VarInfo_CGNS &vi = block->m_variables.back();
1833  vi.m_indices[comp] = A;
1834  vi.m_is_null[comp] = isNull;
1835  } else {
1836  block->m_variables.push_back
1837  (VarInfo_CGNS(label, 'n', CGNS2COM[dataType], units,
1838  nComps, A, nItems, rind[1], isNull));
1839  }
1840  }
1841 
1842  break;
1843  }
1844  }
1845 
1846  blocks.insert(BlockMM_CGNS::value_type(baseName, block));
1847  }
1848  }
1849  }
1850 }
1851 
1852 static void load_data_CGNS( BlockMM_CGNS::iterator p,
1853  const BlockMM_CGNS::iterator& end,
1854  const std::string& window,
1855  const MPI_Comm* comm, int rank, int nprocs)
1856 {
1857  int i;
1858  Block_CGNS* block;
1859  std::string name;
1860  void* data;
1861  int with_pane;
1862 
1863  for ( with_pane=0; p!=end; ++p, ++with_pane) {
1864  block = (*p).second;
1865 
1866  // Panes are a local construct, so make sure that this pane is local.
1867  bool local = COM_get_status( window.c_str(), block->m_paneId) >= 0;
1868 
1869  if (!local) continue;
1870 
1871  AutoCDer autoCD;
1872  std::string fname(block->m_file);
1873  std::string::size_type cloc = fname.rfind('/');
1874  if (cloc != std::string::npos) {
1875  chdir(fname.substr(0, cloc).c_str());
1876  fname.erase(0, cloc + 1);
1877  }
1878 
1879  int fn;
1880  CG_CHECK_RET(cg_open, (fname.c_str(), MODE_READ, &fn), continue);
1881  AutoCloser<int> auto0(fn, cg_close);
1882 
1883  bool structured = (!block->m_gridInfo.empty() &&
1884  block->m_gridInfo.front().m_name.substr(0,3) == ":st");
1885 
1886  // Let Roccom manage memory for nodal coordinates
1887  // Moved allocation outside of dimension loop. Not sure if this fully
1888  // accounts for single registration of "nc" versus "1-nc", "2-nc", etc.
1889 
1890  name = window + ".nc";
1891  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == " << block->m_paneId << ", ptr == NULL, arg == 1 )");
1892  COM_resize_array(name.c_str(), block->m_paneId, NULL, 1);
1893 
1894  // Read the nodal coordinates.
1895  for (i=1; i<4; ++i) {
1896  // Read the mesh only if number of nodes is positive
1897  name = window + '.' + (char)('0' + i) + "-nc";
1898  COM_get_array(name.c_str(), block->m_paneId, &data);
1899 
1900  if (block->m_numNodes > 0 && data != NULL) {
1901  CG_CHECK_RET(cg_goto,
1902  (fn, block->m_B, "Zone_t", block->m_Z,
1903  "GridCoordinates_t", block->m_G, "end"),
1904  continue);
1905 
1906  CG_CHECK(cg_array_read, (i, data));
1907 #ifdef DEBUG_DUMP_PREFIX
1908  {
1909  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.'
1910  + block->time_level + ".cgns").c_str());
1911  DebugDump(fout, block->m_numNodes, COM_DOUBLE, data);
1912  }
1913 #endif // DEBUG_DUMP_PREFIX
1914  }
1915  }
1916 
1917  // Read the connectivity tables.
1918  if (!structured) {
1919  std::vector<GridInfo_CGNS>::iterator s;
1920  for (i=1,s=block->m_gridInfo.begin();s!=block->m_gridInfo.end();++i,++s) {
1921  name = window + "." + (*s).m_name;
1922  DEBUG_MSG("Calling COM_resize_array( name == '" << name
1923  << "', paneid == " << block->m_paneId << ", ptr == "
1924  << &data << ", arg == 1 )");
1925  COM_resize_array(name.c_str(), block->m_paneId, &data, 1);
1926 
1927  if ((*s).m_numElements > 0 && data != NULL) {
1928  int nn;
1929  std::istringstream in(&(*s).m_name[2]);
1930  in >> nn;
1931  std::vector<int> cbuf((*s).m_numElements * nn);
1932  CG_CHECK_RET(cg_elements_read,
1933  (fn, block->m_B, block->m_Z, i, &cbuf[0], NULL),
1934  continue);
1935 
1936  // Scramble the conn table the way Roccom likes it.
1937  int elem, node, zz;
1938  for (elem=0,zz=0; elem<(*s).m_numElements; ++elem)
1939  for (node=0; node<nn; ++node,++zz)
1940  ((int*)data)[node*(*s).m_numElements+elem] = cbuf[zz];
1941 #ifdef DEBUG_DUMP_PREFIX
1942  {
1943  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.' + block->time_level + ".cgns").c_str());
1944  DebugDump(fout, (*s).m_numElements * nn, COM_INT, data);
1945  }
1946 #endif // DEBUG_DUMP_PREFIX
1947  }
1948  }
1949  }
1950 
1951  // Read the attribute data.
1952  std::vector<VarInfo_CGNS>::iterator q;
1953  for (q=block->m_variables.begin(); q!=block->m_variables.end(); ++q) {
1954  // Skip NULL attributes.
1955  if ( (*q).m_is_null[0]) continue;
1956  // Read in window attribute only for the first pane.
1957  if ( with_pane && (*q).m_position=='w') continue;
1958 
1959 
1960  name = window + '.' + (*q).m_name;
1961  if ( (*q).m_position!='w') { // Allocate for nonwindow attribute
1962  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == " << block->m_paneId << ", ptr == " << &data << ", arg == 1 )");
1963  COM_resize_array(name.c_str(), block->m_paneId, &data, 1);
1964  } else {
1965  COM_get_array(name.c_str(), 0, &data);
1966  }
1967 
1968  switch((*q).m_position) {
1969  case 'w':
1970  CG_CHECK_RET(cg_goto,
1971  (fn, block->m_B, "IntegralData_t", block->m_W, "end"),
1972  continue);
1973  break;
1974 
1975  case 'p':
1976  CG_CHECK_RET(cg_goto,
1977  (fn, block->m_B, "Zone_t", block->m_Z, "IntegralData_t", block->m_P, "end"),
1978  continue);
1979  break;
1980 
1981  case 'c':
1982  CG_CHECK_RET(cg_goto,
1983  (fn, block->m_B, "Zone_t", block->m_Z, "IntegralData_t", block->m_C, "end"),
1984  continue);
1985  break;
1986 
1987  case 'e':
1988  CG_CHECK_RET(cg_goto,
1989  (fn, block->m_B, "Zone_t", block->m_Z, "FlowSolution_t", block->m_E, "end"),
1990  continue);
1991  break;
1992 
1993  case 'n':
1994  CG_CHECK_RET(cg_goto,
1995  (fn, block->m_B, "Zone_t", block->m_Z, "FlowSolution_t", block->m_N, "end"),
1996  continue);
1997  break;
1998  }
1999 
2000  int loop;
2001  std::vector<int>::iterator r;
2002  for (r=(*q).m_indices.begin(),loop=1; r!=(*q).m_indices.end();
2003  ++r,++loop) {
2004 
2005  // If scalar, name = window.attribute
2006  // If vector, name = window.#-attribute
2007  if( (*q).m_indices.size() == 1)
2008  name = window + '.' + (*q).m_name;
2009  else {
2010  std::ostringstream sout;
2011  sout << window << '.' << loop << '-' << (*q).m_name;
2012  name = sout.str();
2013  }
2014 
2015  COM_get_array(name.c_str(), block->m_paneId, &data);
2016 
2017  if ((*q).m_nitems == 0 || data == NULL) continue;
2018 
2019  CG_CHECK(cg_array_read, (*r, data));
2020 #ifdef DEBUG_DUMP_PREFIX
2021  {
2022  std::ofstream fout((DEBUG_DUMP_PREFIX + name + '.' + block->time_level + ".cgns").c_str());
2023  DebugDump(fout, (*q).m_nitems, (*q).m_dataType, data);
2024  }
2025 #endif // DEBUG_DUMP_PREFIX
2026  }
2027  }
2028  }
2029 }
2030 #endif // USE_CGNS
2031 
2032 static void new_attributes(BlockMM_HDF4::iterator hdf4,
2033  const BlockMM_HDF4::iterator& hdf4End,
2034 #ifdef USE_CGNS
2035  BlockMM_CGNS::iterator cgns,
2036  const BlockMM_CGNS::iterator& cgnsEnd,
2037 #endif // USE_CGNS
2038  const std::string& window,
2039  const MPI_Comm* comm, int rank, int nprocs)
2040 {
2041 
2042  // Build an MPI message to synchronize variable names.
2043  std::ostringstream sout;
2044  std::set<std::string> added;
2045 
2046  while (hdf4 != hdf4End) {
2047  std::vector<VarInfo_HDF4> &vars = hdf4->second->m_variables;
2048  std::vector<VarInfo_HDF4>::const_iterator q;
2049 
2050  for (q=vars.begin(); q!=vars.end(); ++q){
2051  if (added.count((*q).m_name) == 0) {
2052  sout << (*q).m_name << '!' << (*q).m_position << '!'
2053  << (*q).m_dataType << '!' << (*q).m_indices.size()
2054  << '!' << (*q).m_units << '!';
2055  if ( (*q).m_position=='w')
2056  sout << (*q).m_nitems << '!' << (*q).m_ng;
2057  sout << '|';
2058  added.insert((*q).m_name);
2059  }
2060  }
2061  ++hdf4;
2062  }
2063 
2064 #ifdef USE_CGNS
2065  while (cgns != cgnsEnd) {
2066  std::vector<VarInfo_CGNS> &vars = cgns->second->m_variables;
2067  std::vector<VarInfo_CGNS>::const_iterator q;
2068 
2069  for (q=vars.begin(); q!=vars.end(); ++q){
2070  if (added.count((*q).m_name) == 0) {
2071  sout << (*q).m_name << '!' << (*q).m_position << '!'
2072  << (*q).m_dataType << '!' << (*q).m_indices.size()
2073  << '!' << (*q).m_units << '!';
2074  if ( (*q).m_position=='w')
2075  sout << (*q).m_nitems << '!' << (*q).m_ng;
2076  sout << '|';
2077  added.insert((*q).m_name);
2078  }
2079  }
2080  ++cgns;
2081  }
2082 #endif // USE_CGNS
2083 
2084  // Get the lengths of all of the messages.
2085  std::string msg = sout.str();
2086  int len = msg.length();
2087  std::vector<int> lengths(nprocs);
2088  if ( *comm != MPI_COMM_NULL)
2089  MPI_Allgather(&len, 1, MPI_INT, &lengths[0], 1, MPI_INT, *comm);
2090  else
2091  lengths[0] = len;
2092 
2093  // Compute the total length and displacements for each process's message.
2094  int globlen = lengths[0];
2095  std::vector<int> disp(nprocs, 0);
2096  for (int i=1; i<nprocs; ++i) {
2097  globlen += lengths[i];
2098  disp[i] = disp[i-1] + lengths[i-1];
2099  }
2100 
2101  // Give each process a huge glob with every attribute of every process.
2102  std::vector<char> buffer(len+1,'\0');
2103  std::vector<char> glob(globlen+1,'\0');
2104  std::strcpy( &buffer[0], msg.c_str());
2105  if ( *comm != MPI_COMM_NULL)
2106  MPI_Allgatherv(&buffer[0], len, MPI_CHAR, &glob[0], &lengths[0], &disp[0],
2107  MPI_CHAR, *comm);
2108  else
2109  glob = buffer;
2110 
2111 //std::cout << "glob == \"" << &glob[0] << '"' << std::endl;
2112  std::string name;
2113  char buf[256];
2114  char position;
2115  COM_Type dType;
2116  int numComponents;
2117  char* token = &glob[0];
2118  added.clear();
2119  // printf("parsing string: '%s'\n",token);
2120  while (1) {
2121  char *nextToken = strchr(token,'|');
2122  if (nextToken==0) break;
2123  *nextToken++=0; /* eliminate and advance over separator */
2124  // printf("parsed token: '%s'\n",token);
2125  std::istringstream sin(token);
2126  sin.getline(buf, sizeof(buf), '!');
2127  if (added.count(buf) == 0) {
2128  added.insert(buf);
2129  name = window + '.';
2130  name += buf;
2131  position = sin.get(); sin.get();
2132  sin >> dType; sin.get();
2133  sin >> numComponents; sin.get();
2134  sin.getline(buf, sizeof(buf), '!');
2135  DEBUG_MSG("Calling COM_new_attribute( name == '" << name << "', position == '" << position << "', datatype == " << dType << ", nComp == " << numComponents << ", units == '" << buf << "' )");
2136  COM_new_attribute(name.c_str(), position, dType, numComponents, buf);
2137 
2138  if ( position == 'w') { // Set size and allocate for window attributes
2139  int nitems, ng;
2140  sin >> nitems; sin.get();
2141  sin >> ng; sin.get();
2142  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == 0, nitems == " << nitems << ", nghost == " << ng << " )");
2143  COM_set_size(name.c_str(), 0, nitems, ng);
2144  DEBUG_MSG("Calling COM_resize_array( name == '" << name << "', paneid == 0 )");
2145  COM_resize_array(name.c_str(), 0);
2146  }
2147  }
2148  token = nextToken;
2149  }
2150 }
2151 
2152 // Broadcast window attributes if a process does not have any pane.
2153 static void broadcast_win_attributes( bool isEmpty, const std::string& window,
2154  const MPI_Comm *comm, int rank,
2155  int nprocs)
2156 {
2157  // Build an MPI message to synchronize variable names.
2158  int empty = isEmpty ? 1 : 0;
2159  std::vector<int> is_empty(nprocs);
2160  if ( *comm != MPI_COMM_NULL)
2161  MPI_Allgather(&empty, 1, MPI_INT, &is_empty[0], 1, MPI_INT, *comm);
2162  else
2163  is_empty[0] = empty;
2164 
2165  // Broadcast from the nonempty processor with highest rank.
2166  int last_empty=-1, root=-1;
2167  for (int i=0; i<nprocs; ++i) {
2168  if ( is_empty[i]) last_empty = i;
2169  else root = i;
2170  }
2171 
2172  if ( last_empty<0) return; // No need to broadcast.
2173 
2174  // Obtain the list of attributes
2175  int na; char *atts;
2176  COM_get_attributes( window.c_str(), &na, &atts);
2177 
2178  // Loop through the attributes
2179  std::istringstream is(atts);
2180  for ( int i=0; i<na; ++i) {
2181  // Obtain the attribute name
2182  std::string aname; is >> aname;
2183  char loc;
2184  int type, ncomp;
2185 
2186  COM_get_attribute( (window+"."+aname).c_str(), &loc, &type, &ncomp, NULL);
2187  if ( loc !='w') continue; // Skip non-window attributes;
2188 
2189  void *addr;
2190  int count, strd;
2191  COM_get_array( (window+"."+aname).c_str(), 0, &addr, &strd, &count);
2192 
2193  int len = COM_get_sizeof( type, count*ncomp);
2194  if ( *comm != MPI_COMM_NULL)
2195  MPI_Bcast( addr, len, MPI_CHAR, root, *comm);
2196  }
2197  COM_free_buffer( &atts);
2198 }
2199 
2200 void Rocin::register_panes(BlockMM_HDF4::iterator hdf4,
2201  const BlockMM_HDF4::iterator& hdf4End,
2202 #ifdef USE_CGNS
2203  BlockMM_CGNS::iterator cgns,
2204  const BlockMM_CGNS::iterator& cgnsEnd,
2205 #endif // USE_CGNS
2206  const std::string& window, RulesPtr is_local,
2207  const MPI_Comm* comm, int rank, int nprocs)
2208 {
2209  int local;
2210  std::string name;
2211  bool is_first=true;
2212  for ( ; hdf4!=hdf4End; ++hdf4) {
2213  Block_HDF4* block = (*hdf4).second;
2214 
2215  // Panes are a local construct, so make sure that this pane is local.
2216  if ( m_is_local)
2217  (this->*m_is_local)(block->m_paneId, rank, nprocs, &local);
2218  else if (is_local)
2219  is_local(block->m_paneId, rank, nprocs, &local);
2220  else
2221  local = 1;
2222 
2223  if (!local) continue;
2224 
2225  // Register the mesh unit & number of nodes
2226  name = window + ".nc";
2227  if (is_first && !block->m_units.empty()) {
2228 
2229  DEBUG_MSG("Calling COM_new_attribute( name == '" << name << "', position == 'n', datatype == COM_DOUBLE, nComp == 3, units == '" << block->m_units << "' )");
2230  COM_new_attribute(name.c_str(),'n',COM_DOUBLE,3,block->m_units.c_str());
2231  is_first = false;
2232  }
2233 
2234  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << block->m_numNodes << ", nghost == " << block->m_numGhostNodes << " )");
2235  COM_set_size(name.c_str(), block->m_paneId,
2236  block->m_numNodes,block->m_numGhostNodes);
2237 
2238  // Register the connectivity tables or the mesh dimensions
2239  // need to specify attribute names for multiple connectivity tables
2240  if (block->m_gridInfo.size() &&
2241  block->m_gridInfo.front().m_name.substr(0,3) == ":st") {
2242  int mysize[3], ndim = block->m_gridInfo.front().m_name[3] - '0';
2243  mysize[0] = block->m_gridInfo.front().m_size[2];
2244  mysize[1] = block->m_gridInfo.front().m_size[1];
2245  mysize[2] = block->m_gridInfo.front().m_size[0];
2246  name = window + '.' + block->m_gridInfo.front().m_name;
2247 
2248  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << ndim << ", nghost == " << block->m_gridInfo.front().m_numGhostElements << " )");
2249  COM_set_size(name.c_str(), block->m_paneId, ndim,
2250  block->m_gridInfo.front().m_numGhostElements);
2251  COM_set_array(name.c_str(),block->m_paneId,mysize);
2252  } else {
2253  std::vector<GridInfo_HDF4>::iterator q;
2254  for (q=block->m_gridInfo.begin(); q!=block->m_gridInfo.end(); ++q){
2255  name = window + "." + (*q).m_name;
2256  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << (*q).m_numElements << ", nghost == " << (*q).m_numGhostElements << " )");
2257  COM_set_size(name.c_str(), block->m_paneId,
2258  (*q).m_numElements, (*q).m_numGhostElements);
2259  }
2260  }
2261 
2262  // Set sizes for pane attributes.
2263  std::vector<VarInfo_HDF4> &vars = block->m_variables;
2264  std::vector<VarInfo_HDF4>::const_iterator q;
2265 
2266  for ( q=vars.begin(); q!=vars.end(); ++q) {
2267  if ( (*q).m_position == 'p' || (*q).m_position == 'c') {
2268  name = window + "." + (*q).m_name;
2269  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << (*q).m_nitems << ", nghost == " << (*q).m_ng << " )");
2270  COM_set_size( name.c_str(), block->m_paneId,
2271  (*q).m_nitems, (*q).m_ng);
2272  }
2273  }
2274  }
2275 
2276 #ifdef USE_CGNS
2277  for ( ; cgns!=cgnsEnd; ++cgns) {
2278  Block_CGNS* block = (*cgns).second;
2279 
2280  // Panes are a local construct, so make sure that this pane is local.
2281  if ( m_is_local)
2282  (this->*m_is_local)(block->m_paneId, rank, nprocs, &local);
2283  else if (is_local)
2284  is_local(block->m_paneId, rank, nprocs, &local);
2285  else
2286  local = 1;
2287 
2288  if (!local) continue;
2289 
2290  // Register the mesh unit & number of nodes
2291  name = window + ".nc";
2292  if (is_first && !block->m_units.empty()) {
2293 
2294  DEBUG_MSG("Calling COM_new_attribute( name == '" << name << "', position == 'n', datatype == COM_DOUBLE, nComp == 3, units == '" << block->m_units << "' )");
2295  COM_new_attribute(name.c_str(),'n',COM_DOUBLE,3,block->m_units.c_str());
2296  is_first = false;
2297  }
2298 
2299  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << block->m_numNodes << ", nghost == " << block->m_numGhostNodes << " )");
2300  COM_set_size(name.c_str(), block->m_paneId,
2301  block->m_numNodes,block->m_numGhostNodes);
2302 
2303  // Register the connectivity tables or the mesh dimensions
2304  // need to specify attribute names for multiple connectivity tables
2305  if (block->m_gridInfo.size() &&
2306  block->m_gridInfo.front().m_name.substr(0,3) == ":st") {
2307  int ndim = block->m_gridInfo.front().m_name[3] - '0';
2308  name = window + '.' + block->m_gridInfo.front().m_name;
2309 
2310  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << ndim << ", nghost == " << block->m_gridInfo.front().m_numGhostElements << " )");
2311  COM_set_size(name.c_str(), block->m_paneId, ndim,
2312  block->m_gridInfo.front().m_numGhostElements);
2313  COM_set_array(name.c_str(), block->m_paneId,
2314  block->m_gridInfo.front().m_size);
2315  } else {
2316  std::vector<GridInfo_CGNS>::iterator q;
2317  for (q=block->m_gridInfo.begin(); q!=block->m_gridInfo.end(); ++q){
2318  name = window + "." + (*q).m_name;
2319  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << (*q).m_numElements << ", nghost == " << (*q).m_numGhostElements << " )");
2320  COM_set_size(name.c_str(), block->m_paneId,
2321  (*q).m_numElements, (*q).m_numGhostElements);
2322  }
2323  }
2324 
2325  // Set sizes for pane attributes.
2326  std::vector<VarInfo_CGNS> &vars = block->m_variables;
2327  std::vector<VarInfo_CGNS>::const_iterator q;
2328 
2329  for ( q=vars.begin(); q!=vars.end(); ++q) {
2330  if ( (*q).m_position == 'p' || (*q).m_position == 'c') {
2331  name = window + "." + (*q).m_name;
2332  DEBUG_MSG("Calling COM_set_size( name == '" << name << "', paneid == " << block->m_paneId << ", nitems == " << (*q).m_nitems << ", nghost == " << (*q).m_ng << " )");
2333  COM_set_size( name.c_str(), block->m_paneId,
2334  (*q).m_nitems, (*q).m_ng);
2335  }
2336  }
2337  }
2338 #endif // USE_CGNS
2339 }
2340 
2341 template<class BLOCK>
2342 void free_blocks(BLOCK& blocks)
2343 {
2344  typename BLOCK::iterator p;
2345  for (p=blocks.begin(); p!=blocks.end(); ++p)
2346  delete (*p).second;
2347 
2348  blocks.clear();
2349 }
2350 
2351 void Rocin::init(const std::string &mname) {
2352  HDF4::init();
2353 
2354  Rocin *rin = new Rocin();
2355 
2357  rin->m_HDF2COM[DFNT_CHAR8] = COM_CHAR;
2358  rin->m_HDF2COM[DFNT_INT32] = COM_INT;
2359  rin->m_HDF2COM[DFNT_FLOAT32] = COM_FLOAT;
2360  rin->m_HDF2COM[DFNT_FLOAT64] = COM_DOUBLE;
2361 
2362 #ifdef USE_CGNS
2363  rin->m_CGNS2COM[Character] = COM_CHAR;
2365  rin->m_CGNS2COM[Integer] = COM_INT;
2366  rin->m_CGNS2COM[RealSingle] = COM_FLOAT;
2367  rin->m_CGNS2COM[RealDouble] = COM_DOUBLE;
2368 #endif // USE_CGNS
2369 
2370  COM_new_window( mname.c_str(), MPI_COMM_SELF);
2371 
2372  std::string glb=mname+".global";
2373 
2374  DEBUG_MSG("Calling COM_new_attribute( name == '" << glb << "', position == 'w', datatype == COM_OBJECT, nComp == 1, units == '' )");
2375  COM_new_attribute( glb.c_str(), 'w', COM_OBJECT, 1, "");
2376  COM_set_object( glb.c_str(), 0, rin);
2377 
2378  // Register the function read_windows
2381  COM_set_member_function( (mname+".read_windows").c_str(),
2382  (Member_func_ptr)&Rocin::read_windows,
2383  glb.c_str(), "biiIIIBI", types);
2384 
2385  // Register the function read_window
2386  types[3] = COM_MPI_COMM; types[4] = COM_VOID;
2387  types[5] = COM_STRING; types[6] = COM_INT;
2388  COM_set_member_function( (mname+".read_window").c_str(),
2389  (Member_func_ptr)&Rocin::read_window,
2390  glb.c_str(), "biiIIBI", types);
2391 
2392  // Register the function read_by_control_file
2393  types[4] = COM_STRING; types[5] = COM_INT;
2394  COM_set_member_function( (mname+".read_by_control_file").c_str(),
2395  (Member_func_ptr)&Rocin::read_by_control_file,
2396  glb.c_str(), "biiIBI", types);
2397 
2398  // Register the function obtain_attribute
2399  types[1] = COM_METADATA;
2400  types[2] = COM_METADATA;
2401  types[3] = COM_INT;
2402  COM_set_member_function( (mname+".obtain_attribute").c_str(),
2403  (Member_func_ptr)&Rocin::obtain_attribute,
2404  glb.c_str(), "bioI", types);
2405 
2406  // Regsister the function read_parameter_file
2407  types[1] = COM_STRING;
2408  types[2] = COM_STRING;
2409  types[3] = COM_MPI_COMM;
2410  COM_set_member_function( (mname+".read_parameter_file").c_str(),
2411  (Member_func_ptr)&Rocin::read_parameter_file,
2412  glb.c_str(), "biiI", types);
2413 
2414  COM_window_init_done( mname.c_str());
2415 }
2416 
2417 void Rocin::finalize(const std::string &mname) {
2418  // Retrieve Rocin object from Roccom
2419  Rocin *rin;
2420  std::string glb=mname+".global";
2421 
2422  COM_get_object( glb.c_str(), 0, &rin);
2423 
2424  COM_delete_window( mname.c_str());
2425 
2426  // Delete the object
2427  delete rin;
2428  HDF4::finalize();
2429 }
2430 
2431 void Rocin::obtain_attribute( const COM::Attribute *attribute_in,
2432  COM::Attribute *user_attribute,
2433  int *pane_id)
2434 {
2435  // obtain a valid attribute object from user_attribute's name
2436  COM_assertion_msg((attribute_in != NULL && user_attribute != NULL),
2437  "Null attributes are not valid arguments to Rocin::obtain_attribute\n");
2438 
2439  if ( attribute_in != user_attribute) {
2440  COM::Window *win = user_attribute->window();
2441  win->inherit(const_cast<Attribute*>(attribute_in), user_attribute->name(),
2442  COM::Pane::INHERIT_COPY, true, NULL, pane_id?*pane_id:0);
2443  }
2444 }
2445 
2446 void Rocin::explicit_local( const int& pid, const int& comm_rank,
2447  const int& comm_size, int* il)
2448 {
2449  *il = m_pane_ids.count(pid);
2450 }
2451 
2452 void Rocin::cyclic_local(const int& pid, const int& comm_rank,
2453  const int& comm_size, int* il)
2454 {
2455  *il = (pid - m_offset) % comm_size == comm_rank;
2456 }
2457 
2458 void Rocin::blockcyclic_local(const int& pid, const int& comm_rank,
2459  const int& comm_size, int* il)
2460 {
2461  int proc = (pid-m_offset) / m_base;
2462  if ( proc>=comm_size) proc %= comm_size;
2463  *il = proc == comm_rank;
2464 }
2465 
2466 void Rocin::read_by_control_file( const char* control_file_name,
2467  const char* window_name,
2468  const MPI_Comm* comm,
2469  char* time_level,
2470  const int* str_len)
2471 {
2472  const MPI_Comm default_comm=COM_get_default_communicator();
2473  const MPI_Comm comm_null=MPI_COMM_NULL;
2474  const MPI_Comm* myComm;
2475  int myRank, comm_size;
2476 
2477  // Determine the directory name of the control_file_name
2478  std::string dir_name = control_file_name;
2479  std::string::size_type pos = dir_name.find_last_of('/');
2480  if ( pos == std::string::npos)
2481  dir_name = "";
2482  else
2483  dir_name.erase( pos+1);
2484 
2485  if ( comm && *comm == MPI_COMM_NULL || !comm)
2486  myComm = COMMPI_Initialized() ? &default_comm : &comm_null;
2487  else
2488  myComm = comm;
2489 
2490  // Set myRank to a wild card if MPI is not initialized
2491  if ( !COMMPI_Initialized() || *myComm == MPI_COMM_NULL) {
2492  myRank = -1;
2493  comm_size = 1;
2494  }
2495  else {
2496  MPI_Comm_rank(*myComm, &myRank);
2497  MPI_Comm_size(*myComm, &comm_size);
2498  if(comm_size == 1)
2499  myRank = -1;
2500  }
2501 
2502  std::ifstream fin(control_file_name);
2503  if (!fin.is_open()) {
2504  std::cerr << "Rocstar: Error: read_by_control_file unable to open " << control_file_name
2505  << " for reading." << std::endl;
2506  return;
2507  }
2508 
2509  std::vector<std::string> patterns;
2510  std::string buffer;
2511  int rank = -54321;
2512  m_pane_ids.clear();
2513 
2514  while (!fin.eof()) {
2515  std::vector<std::string> local_patterns;
2516  while (!fin.eof() && (myRank<0 || rank != myRank) ) {
2517  if (buffer != "@Proc:") {
2518  fin >> buffer;
2519  continue;
2520  }
2521 
2522  while (fin.peek() == ' ' || fin.peek() == '\t' || fin.peek() == '\n')
2523  fin.get();
2524 
2525  if (fin.peek() == '*') {
2526  fin.get();
2527  rank = myRank;
2528  break;
2529  } else {
2530  fin >> rank;
2531  // If myRank is a wild card, then any rank will match with it.
2532  if (myRank < 0) {
2533  rank = myRank;
2534  break;
2535  } else if (rank == myRank)
2536  break;
2537  }
2538 
2539  buffer="";
2540  }
2541 
2542  if (fin.eof()) {
2543  if ( rank != myRank)
2544  std::cerr << "Rocstar: Error (read_by_control_file): control file "
2545  << control_file_name
2546  << " does not contain information for process " << myRank
2547  << std::endl;
2548  break;
2549  }
2550 
2551  fin >> buffer;
2552  if (buffer != "@Files:") {
2553  std::cerr << "Rocstar: Error (read_by_control_file): in control file "
2554  << control_file_name
2555  << ": expected '@Files' but found '" << buffer << '\''
2556  << std::endl;
2557  return;
2558  }
2559 
2560  fin >> buffer;
2561 
2562  while (buffer != "@Panes:" && buffer != "@Proc:") {
2563  // The @Panes section may not be present
2564  if (fin.eof()) break;
2565 
2566  std::string::size_type pos = buffer.find("%t");
2567  if (pos != std::string::npos)
2568  buffer.replace(pos, 2, time_level);
2569 
2570  pos = buffer.find('%');
2571  if ( pos != std::string::npos) {
2572  std::string::size_type pos_key =
2573  buffer.find_first_not_of("0123456789", pos+1);
2574 
2575  COM_assertion_msg( pos_key != std::string::npos,
2576  (std::string("Incomplete placeholder in file name ")+buffer).c_str());
2577 
2578  std::string width = buffer.substr(pos+1, pos_key-pos-1);
2579 
2580  int w = 4; // The default rankwidth is 4, if width is empty
2581  if ( !width.empty()) {
2582  std::istringstream sin(width);
2583  sin >> w;
2584  }
2585 
2586  std::ostringstream sout;
2587 
2588  switch( buffer[pos_key]) {
2589  case 'p': {
2590  // If myRank<0, then match the rank with any integer of width w
2591  if ( myRank<0)
2592  for ( int i=0; i<w; ++i) sout << "[0-9]";
2593  else
2594  sout << std::setfill('0') << std::setw(w) << myRank;
2595 
2596  break;
2597  }
2598  case 'i':
2599  case 'b': {
2600  // TODO: Use the mapping rule on the next line to distribute files.
2601  // For now, have all processes read all files that match the number
2602  // of digits for the block or pane ID in the filenames.
2603  for ( int i=0; i<w; ++i) sout << "[0-9]";
2604  break;
2605  }
2606  default:
2607  COM_assertion_msg( false, (std::string("Unknown keyword in file name ")+buffer).c_str());
2608  }
2609 
2610  buffer.replace(pos, pos_key - pos + 1, sout.str());
2611  }
2612 
2613  // Determine whether buffer has directory part. If not, prepend that
2614  // of the control file. If so, then use it as is.
2615  if ( !dir_name.empty()) {
2616 /*
2617  std::string::size_type pos = buffer.find_last_of('/');
2618  if ( pos == std::string::npos) buffer.insert(0, dir_name);
2619 */
2620  // when it is not absolute path and does not have same prefix
2621  if (buffer[0] != '/' &&
2622  strncmp(buffer.c_str(), dir_name.c_str(), std::min(buffer.size(), dir_name.size()))) buffer.insert(0, dir_name);
2623  }
2624 
2625  // Insert buffer into patterns.
2626  local_patterns.push_back(buffer);
2627 
2628  fin >> buffer;
2629  }
2630 
2631  // The @Panes section may not be present
2632  if (buffer == "@Proc:") {
2633  patterns.insert(patterns.end(), local_patterns.begin(),
2634  local_patterns.end());
2635  continue;
2636  }
2637 
2638  m_base = 0;
2639  m_offset = 0;
2640  m_is_local = NULL;
2641 
2642  if ( !fin.eof())
2643  fin >> buffer;
2644  else
2645  buffer = "-1";
2646 
2647  // Read in panes.
2648  if (buffer == "@Cyclic") {
2649  fin >> m_offset;
2651  } else if (buffer == "@BlockCyclic") {
2652  fin >> m_base;
2653  fin >> m_offset;
2655  } else if (buffer == "@Block" || buffer == "@BlockBlockCyclic") {
2656  int block;
2657  fin >> block;
2658  fin >> m_base;
2659  fin >> m_offset;
2660  int quot = block/comm_size, rem = block-quot*comm_size;
2661  if ( rank < rem) {
2662  m_base *= quot+1;
2663  }
2664  else {
2665  m_offset += rem;
2666  m_base *= quot;
2667  }
2669  } else if (buffer == "@All" || buffer == "*") {
2670  m_is_local = NULL;
2671  } else if (buffer[0] == '@' && buffer != "@Panes:" ) {
2672  if ( buffer != "@Proc:") { // Skip empty @Panes section.
2673  std::cerr << "Rocstar: Error (read_by_control_file): in control file "
2674  << control_file_name << ": expected pane info but found '"
2675  << buffer << '\'' << std::endl;
2676  return;
2677  } else {
2678  // ignore file when no pane
2679  local_patterns.clear();
2680  }
2681  } else {
2683 
2684  for (;;) {
2685  if (buffer[0] < '0' || buffer[0] > '9')
2686  break;
2687 
2688  std::istringstream sin(buffer);
2689  int p=-1;
2690 
2691  sin >> p;
2692 
2693  if ( p>=0) {
2694  m_pane_ids.insert(p);
2695  } else {
2696  break;
2697  }
2698 
2699  if (!fin.eof()) fin >> buffer;
2700  else break;
2701  }
2702  }
2703 
2704  patterns.insert(patterns.end(), local_patterns.begin(),
2705  local_patterns.end());
2706 
2707  if ( myRank >= 0 && rank == myRank) break;
2708  }
2709  fin.close();
2710 
2711  if ( myRank>=0 && rank != myRank)
2712  std::cerr << "Rocstar: Warning: Did not find matching control blocks for process " << myRank << std::endl;
2713 
2714  // If myRank is a wild card and panes aren't specified explicitly, then
2715  // make all panes local.
2716  if (myRank < 0 && m_is_local != &Rocin::explicit_local)
2717  m_is_local = NULL;
2718 
2719  // Convert the patterns into a single string
2720  std::string files;
2721  std::vector<std::string>::const_iterator p;
2722  for (p=patterns.begin(); p!=patterns.end(); ++p)
2723  files = files+" "+(*p).c_str();
2724 
2725  // Invoke read_window
2726  //std::cout << __FILE__ << __LINE__ << " files = " << files << std::endl;
2727  read_window(files.c_str(), window_name, myComm, NULL, time_level, str_len);
2728 
2729  m_pane_ids.clear();
2730  m_offset = 0;
2731  m_base = 0;
2732  m_is_local = NULL;
2733 }
2734 
2736 
2750 void Rocin::read_window( const char* filename_patterns,
2751  const char* window_name,
2752  const MPI_Comm* comm,
2753  RulesPtr is_local,
2754  char* time_level,
2755  const int* str_len)
2756 {
2757  read_windows( filename_patterns, window_name, "", comm, is_local,
2758  time_level, str_len);
2759 }
2760 
2761 std::string
2763 {
2764  char buf[1024];
2765  return(std::string(getcwd(buf,1024)));
2766 }
2769 
2786 void Rocin::read_windows(const char* filename_patterns,
2787  const char* window_prefix,
2788  const char* material_names,
2789  const MPI_Comm* comm,
2790  RulesPtr is_local,
2791  char* time_level,
2792  const int* str_len)
2793 {
2794  //std::cout << __FILE__ << __LINE__
2795  // << " filename_patterns = " << filename_patterns
2796  // << std::endl;
2797  const MPI_Comm default_comm=COM_get_default_communicator();
2798  const MPI_Comm comm_null=MPI_COMM_NULL;
2799  const MPI_Comm* myComm =
2800  COMMPI_Initialized()? (comm ? comm : &default_comm ) : &comm_null;
2801 
2802  int rank, nprocs;
2803  if ( *myComm != MPI_COMM_NULL) {
2804  MPI_Comm_rank(*myComm, &rank);
2805  MPI_Comm_size(*myComm, &nprocs);
2806  }
2807  else {
2808  rank = 0; nprocs=1;
2809  }
2810 
2811  DEBUG_MSG("time_level == " << (time_level == NULL ? "<Null>" : time_level));
2812  std::string time( time_level?time_level:"");
2813  DEBUG_MSG("time == " << time);
2814 
2815  std::set<std::string> materials;
2816  char* buffer;
2817  char* token;
2818 
2819  // Insert list of material names into materials.
2820  if (material_names != NULL) {
2821  buffer = new char[strlen(material_names)+1];
2822  strcpy(buffer, material_names);
2823 
2824  token = strtok(buffer, " \t\n");
2825  while (token != NULL) {
2826  materials.insert(token);
2827  token = strtok(NULL, " \t\n");
2828  }
2829  delete[] buffer;
2830  }
2831 
2832  buffer = new char[strlen(filename_patterns)+1];
2833  strcpy(buffer, filename_patterns);
2834 
2835  BlockMM_HDF4 blocks_HDF4;
2836 #ifdef USE_CGNS
2837  BlockMM_CGNS blocks_CGNS;
2838 #endif // USE_CGNS
2839 
2840  token = strtok(buffer, " \t\n");
2841  if (token != NULL) {
2842 #ifndef _NO_GLOB_
2843  glob_t globbuf;
2844 
2845  glob(token, 0, cast_err_func(glob,glob_error), &globbuf);
2846  token = strtok(NULL, " \t\n");
2847  while (token != NULL) {
2848  glob(token, GLOB_APPEND, cast_err_func(glob,glob_error), &globbuf);
2849  token = strtok(NULL, " \t\n");
2850  }
2851 
2852  if ( globbuf.gl_pathc==0 && buffer[0]!='\0')
2853  std::cerr << "Rocstar: Warning: Found no matching files for pattern "
2854  << buffer << std::endl;
2855 
2856  // Extracts metadata from a list of files.
2857  // Opens each file, scans dataset, identifies windows, panes, and attribute
2858  // Puts this information into blocks.
2859  // MS
2860  //std::cout << __FILE__ << __LINE__
2861  // << "gl_pathv = " << globbuf.gl_pathv[0]
2862  // << std::endl;
2863  // search for hdf or cgns
2864  bool isHDF = false;
2865  bool isCGNS = false;
2866  if ((std::string(globbuf.gl_pathv[0])).find(".hdf") != std::string::npos){
2867  isHDF = true;
2868  std::cout << "npos = " << (std::string(globbuf.gl_pathv[0])).find(".hdf") <<std::endl;
2869  }
2870  isCGNS = isHDF ? false:true;
2871  //std::cout << "isHdf = " << isHDF << " isCGNS = " << isCGNS << std::endl;
2872  // MS End
2873  if (isHDF){
2874  scan_files_HDF4(globbuf.gl_pathc, globbuf.gl_pathv, blocks_HDF4, time,
2875  m_HDF2COM);
2876  //std::cout << "Read HDF!" << std::endl;
2877  } else {
2878 #ifdef USE_CGNS
2879  scan_files_CGNS(globbuf.gl_pathc, globbuf.gl_pathv, blocks_CGNS, time,
2880  m_CGNS2COM);
2881  //std::cout << "Read CGNS!" << std::endl;
2882 #endif
2883  }
2884 // Original
2885 //#ifndef USE_CGNS
2886 // scan_files_HDF4(globbuf.gl_pathc, globbuf.gl_pathv, blocks_HDF4, time,
2887 // m_HDF2COM);
2888 //#else
2889 // scan_files_CGNS(globbuf.gl_pathc, globbuf.gl_pathv, blocks_CGNS, time,
2890 // m_CGNS2COM);
2891 //#endif
2892 // Original End
2893  globfree(&globbuf);
2894 #else // No glob function on this system
2895  // Create a char** of n filenames matching patterns stored in buffer
2896  // each token is a new pattern
2897  std::list<std::string> matching_filenames;
2898  while (token != NULL) {
2899  std::string dirname(CWD());
2900  std::string tstring(token);
2901  std::string::size_type x = tstring.find_last_of("/");
2902  if(x != std::string::npos){
2903  dirname += ("/" + tstring.substr(0,x));
2904  tstring.erase(0,x+1);
2905  }
2906  Directory directory(dirname);
2907  if(directory){
2908  Directory::iterator di = directory.begin();
2909  while(di != directory.end()){
2910  if(!fnmatch(tstring.c_str(),di->c_str(),0))
2911  matching_filenames.push_back(dirname + "/" + *di);
2912  di++;
2913  }
2914  }
2915  token = strtok(NULL, " \t\n");
2916  }
2917  if(matching_filenames.empty() && buffer[0] != '\0')
2918  std::cerr << "Rocstar: Warning: Found no matching files for pattern "
2919  << buffer << std::endl;
2920  unsigned int nmatch = matching_filenames.size();
2921  std::vector<char *> matches(nmatch);
2922  std::list<std::string>::iterator li = matching_filenames.begin();
2923  unsigned int ccount = 0;
2924  while(li != matching_filenames.end()){
2925  unsigned int lis = li->size();
2926  matches[ccount++] = new char [lis+1];
2927  strcpy(matches[ccount-1],li->c_str());
2928  matches[ccount-1][lis] = '\0';
2929  li++;
2930  }
2931 #ifndef USE_CGNS
2932  scan_files_HDF4(nmatch, &matches[0], blocks_HDF4, time,
2933  m_HDF2COM);
2934 #else
2935  scan_files_CGNS(nmatch, &matches[0], blocks_CGNS, time,
2936  m_CGNS2COM);
2937 #endif
2938  ccount = 0;
2939  while(ccount < nmatch){
2940  if(matches[ccount])
2941  delete [] matches[ccount];
2942  ccount++;
2943  }
2944 #endif
2945  }
2946 
2947  delete[] buffer;
2948 
2949  // Copy out time level
2950  if ( time_level && str_len && *str_len) {
2951  // TODO: Run MPI_Allgather to send time level to those with no data
2952  // and check whether all processes obtained the same non-empty time level.
2953  std::strncpy( time_level, time.c_str(), *str_len-1);
2954  time_level[*str_len-1] = '\0';
2955  }
2956 
2957  std::string name;
2958  std::set<std::string>::iterator p = materials.begin();
2959  std::pair<BlockMM_HDF4::iterator, BlockMM_HDF4::iterator> range_HDF4;
2960 #ifdef USE_CGNS
2961  std::pair<BlockMM_CGNS::iterator, BlockMM_CGNS::iterator> range_CGNS;
2962 #endif // USE_CGNS
2963 
2964  if (materials.empty()) {
2965  // Default value of material_names is NULL
2966  // we assume the file only contains one type of material, and
2967  // the window name is the window_prefix.
2968  range_HDF4.first = blocks_HDF4.begin();
2969  range_HDF4.second = blocks_HDF4.end();
2970 #ifdef USE_CGNS
2971  range_CGNS.first = blocks_CGNS.begin();
2972  range_CGNS.second = blocks_CGNS.end();
2973 #endif // USE_CGNS
2974  name = window_prefix;
2975 
2976  COM_new_window(name.c_str(), *myComm);
2977 
2978  new_attributes( range_HDF4.first, range_HDF4.second,
2979 #ifdef USE_CGNS
2980  range_CGNS.first, range_CGNS.second,
2981 #endif // USE_CGNS
2982  name, myComm, rank, nprocs);
2983  register_panes( range_HDF4.first, range_HDF4.second,
2984 #ifdef USE_CGNS
2985  range_CGNS.first, range_CGNS.second,
2986 #endif // USE_CGNS
2987  name, is_local, myComm, rank, nprocs);
2988 
2989  load_data_HDF4(range_HDF4.first, range_HDF4.second,
2990  name, myComm, rank, nprocs);
2991 #ifdef USE_CGNS
2992  load_data_CGNS(range_CGNS.first, range_CGNS.second,
2993  name, myComm, rank, nprocs);
2994 #endif // USE_CGNS
2995 
2996  broadcast_win_attributes( range_HDF4.first == range_HDF4.second
2997 #ifdef USE_CGNS
2998  && range_CGNS.first == range_CGNS.second
2999 #endif // USE_CGNS
3000  , name, myComm, rank, nprocs);
3001 
3002  COM_window_init_done(name.c_str());
3003  } else {
3004 
3005  // Iterate through each material (one window per material).
3006  while (p != materials.end()) {
3007  if (blocks_HDF4.count(*p) == 0
3008 #ifdef USE_CGNS
3009  && blocks_CGNS.count(*p) == 0
3010 #endif // USE_CGNS
3011  ) {
3012  std::cerr << "Rocstar: Warning (read_windows): could not find '" << *p << "'."
3013  << std::endl;
3014  ++p; // Increment p.
3015  continue;
3016  }
3017 
3018  range_HDF4 = blocks_HDF4.equal_range(*p);
3019 #ifdef USE_CGNS
3020  range_CGNS = blocks_CGNS.equal_range(*p);
3021 #endif // USE_CGNS
3022  name = window_prefix + *p;
3023 
3024  COM_new_window(name.c_str(), *myComm);
3025 
3026  new_attributes( range_HDF4.first, range_HDF4.second,
3027 #ifdef USE_CGNS
3028  range_CGNS.first, range_CGNS.second,
3029 #endif // USE_CGNS
3030  name, myComm, rank, nprocs);
3031  register_panes( range_HDF4.first, range_HDF4.second,
3032 #ifdef USE_CGNS
3033  range_CGNS.first, range_CGNS.second,
3034 #endif // USE_CGNS
3035  name, is_local, myComm, rank, nprocs);
3036 
3037  load_data_HDF4(range_HDF4.first, range_HDF4.second,
3038  name, myComm, rank, nprocs);
3039 #ifdef USE_CGNS
3040  load_data_CGNS(range_CGNS.first, range_CGNS.second,
3041  name, myComm, rank, nprocs);
3042 #endif // USE_CGNS
3043 
3044  broadcast_win_attributes( range_HDF4.first == range_HDF4.second
3045 #ifdef USE_CGNS
3046  && range_CGNS.first == range_CGNS.second
3047 #endif // USE_CGNS
3048  , name, myComm, rank, nprocs);
3049 
3050  COM_window_init_done(name.c_str());
3051 
3052  ++p;
3053  }
3054  }
3055 
3056  // Free memory.
3057  free_blocks(blocks_HDF4);
3058 #ifdef USE_CGNS
3059  free_blocks(blocks_CGNS);
3060 #endif // USE_CGNS
3061 }
3062 
3063 extern "C" void Rocin_load_module( const char *name)
3064 { Rocin::init( std::string(name)); }
3065 
3066 extern "C" void Rocin_unload_module( const char *name)
3067 { Rocin::finalize( std::string(name)); }
3068 
3069 #ifndef DOXYGEN_SHOULD_SKIP_THIS
3070 // All possible Fortran bindings
3071 
3072 extern "C" void COM_F_FUNC2(rocin_load_module, ROCIN_LOAD_MODULE)( const char *name, long int length)
3073 { Rocin_load_module( std::string(name, length).c_str()); }
3074 extern "C" void COM_F_FUNC2(rocin_unload_module, ROCIN_UNLOAD_MODULE)( const char *name, long int length)
3075 { Rocin_unload_module( std::string(name, length).c_str()); }
3076 
3077 #endif // DOXYGEN_SHOULD_SKIP_THIS
3078 
3079 
3080 
3081 
3082 
3083 
3084 
static void load_data_HDF4(BlockMM_HDF4::iterator p, const BlockMM_HDF4::iterator &end, const std::string &window, const MPI_Comm *comm, int rank, int nprocs)
Definition: Rocin.C:882
void blockcyclic_local(const int &pid, const int &comm_rank, const int &comm_size, int *il)
Definition: Rocin.C:2458
int m_numGhostNodes
Number of ghost nodes in a mesh.
Definition: rocin_block.h:98
static int32 SDselect(int32 sd_id, int32 index)
Definition: HDF4.C:268
Struct containing necessary information on a mesh of a pane.
Definition: rocin_block.h:55
int COM_Type
Indices for derived data types.
Definition: roccom_basic.h:122
void Rocin_load_module(const char *name)
Load the module Rocin into Roccom using the given module name.
Definition: Rocin.C:3063
void read_windows(const char *filename_patterns, const char *window_prefix, const char *material_names=NULL, const MPI_Comm *comm=NULL, RulesPtr is_local=NULL, char *time_level=NULL, const int *str_len=NULL)
Create a series of Roccom windows by reading in a list of files.
Definition: Rocin.C:2786
std::vector< int32 > m_indices
HDF4 dataset indices for each component.
Definition: rocin_block.h:46
#define MAX_NC_VARS
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_SELF
Automatically save and restore the current working directory.
Definition: Rocout_cgns.C:139
void COM_delete_window(const char *wname)
Definition: roccom_c++.h:94
T cast_err_func(int(*glob)(const char *, int, T, glob_t *), int(*errfunc)(const char *, int))
Cast glob_error for portability (IBMSP has a different prototype)
Definition: Rocin.C:130
void COM_get_attribute(const std::string wa_str, char *loc, int *type, int *ncomp, std::string *unit)
Definition: roccom_c++.h:269
int m_numNodes
Number of nodes in the mesh.
Definition: rocin_block.h:97
static intn SDend(int32 sd_id)
Definition: HDF4.C:200
std::vector< bool > m_is_null
Whether or not a component in NULL.
Definition: rocin_block.h:49
#define COM_assertion_msg(EX, msg)
double s
Definition: blastest.C:80
void read_window(const char *filename_patterns, const char *window_name, const MPI_Comm *comm=NULL, RulesPtr is_local=NULL, char *time_level=NULL, const int *str_len=NULL)
Create a single Roccom window by reading in a list of files.
Definition: Rocin.C:2750
static void finalize(const std::string &mname)
Finalize the module by deregistering it from Roccom.
Definition: Rocin.C:2417
static intn SDendaccess(int32 sds_id)
Definition: HDF4.C:288
char * m_cwd
Definition: Rocout_cgns.C:147
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
int m_base
Definition: Rocin.h:243
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
~AutoCloser()
Definition: Rocin.C:183
static void scan_files_HDF4(int pathc, char *pathv[], BlockMM_HDF4 &blocks, std::string &time, std::map< int32, COM_Type > &HDF2COM)
Extract metadata from the list of files.
Definition: Rocin.C:340
void COM_get_array(const char *wa_str, int pane_id, void **addr, int *strd, int *cap)
Get the address for an attribute on a specific pane.
boolean empty(T_VertexSet s)
int32 m_indices[3]
HDF4 dataset indices of the nodal coordinates.
Definition: rocin_block.h:93
C/C++ Data types.
Definition: roccom_basic.h:129
std::set< int > m_pane_ids
Definition: Rocin.h:242
Struct containing necessary information for a pane.
Definition: rocin_block.h:81
Automatically close open files, datasets, etc.
Definition: Rocin.C:179
T2(* m_close)(T1)
Definition: Rocin.C:186
real *8 function offset(vNorm, x2, y2, z2)
Definition: PlaneNorm.f90:211
void COM_set_object(const char *wa_str, int pane_id, Type *addr)
Definition: roccom_c++.h:144
void cyclic_local(const int &pid, const int &comm_rank, const int &comm_size, int *il)
Definition: Rocin.C:2452
Definition: adj.h:150
#define COM_F_FUNC2(lowcase, uppercase)
Definition: roccom_basic.h:87
void register_panes(BlockMM_HDF4::iterator hdf4, const BlockMM_HDF4::iterator &hdf4End, const std::string &window, RulesPtr is_local, const MPI_Comm *comm, int rank, int nprocs)
Definition: Rocin.C:2200
static void broadcast_win_attributes(bool isEmpty, const std::string &window, const MPI_Comm *comm, int rank, int nprocs)
Definition: Rocin.C:2153
#define MAX_NC_NAME
std::string m_geomFile
External geometry file (may be empty).
Definition: rocin_block.h:92
int strncasecmp(const char *const s1, const char *const s2, const int l)
Compare the first n characters of two C-strings, ignoring the case.
Definition: CImg.h:4915
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
#define HDF4_CHECK(routine, args)
Definition: Rocin.C:170
bool is_local(int pid, int comm_rank, int comm_size)
Definition: adj.h:203
rational * A
Definition: vinci_lass.c:67
static void init(const std::string &mname)
Initialize the module by registering it to Roccom with the given module name.
Definition: Rocin.C:2351
std::vector< GridInfo_HDF4 > m_gridInfo
Dimensions or conn table(s)
Definition: rocin_block.h:99
static void init()
Create and start the I/O thread.
Definition: HDF4.C:108
void read_parameter_file(const char *file_name, const char *window_name, const MPI_Comm *comm=NULL)
Read in parameters from a given file into the given window.
void COM_get_attributes(const char *wname, int *na, std::string &names)
Definition: roccom_c++.h:360
int m_paneId
The pane id.
Definition: rocin_block.h:94
static int32 FindFirstGeometryDataset(int32 sd_id, const std::string &geomFile, const std::string &matName, const std::string &label, int32 hIndex, int32 *index)
Find the first geometry dataset for the given block.
Definition: Rocin.C:285
std::string m_file
Data file.
Definition: rocin_block.h:91
int strcasecmp(const char *const s1, const char *const s2)
Compare two C-strings, ignoring the case.
Definition: CImg.h:4928
NT & sin
#define DEBUG_MSG(x)
Definition: Rocin.C:77
static int32 Select(int32 sd_id, int32 &index, char *name, int32 *rank, int32 *size, int32 *dType, int32 *nAttrs, int32 dsCount=-1)
&quot;Open&quot; and &quot;close&quot; HDF files efficiently.
Definition: HDF4.C:675
#define HDF4_CHECK_RET(routine, args, retval)
Perform HDF4 error-checking.
Definition: Rocin.C:144
std::string m_name
Name of variable.
Definition: rocin_block.h:42
Definition: Rocin.h:64
static intn SDreaddata(int32 sds_id, int32 *start, int32 *stride, int32 *end, VOIDP data)
Definition: HDF4.C:467
Rocin()
Default constructor.
Definition: Rocin.h:67
blockLoc i
Definition: read.cpp:79
void int int REAL * x
Definition: read.cpp:74
Struct containing necessary information about an attribute in a window.
Definition: rocin_block.h:33
void COM_window_init_done(const char *w_str, int pane_changed=true)
Definition: roccom_c++.h:102
const NT & n
int COM_get_sizeof(const COM_Type type, int c)
Definition: roccom_c++.h:560
static intn SDfileinfo(int32 id, int32 *dsCount, int32 *nAttrs)
Definition: HDF4.C:219
std::string m_units
The mesh&#39;s units of measurement.
Definition: rocin_block.h:96
void COM_new_window(const char *wname, MPI_Comm c=MPI_COMM_NULL)
Definition: roccom_c++.h:86
bool blocks
Input data is block-structured grid.
Definition: hdf2pltV2.C:51
std::map< int32, COM_Type > m_HDF2COM
Definition: Rocin.h:246
Rocin creates a series of Roccom windows by reading in a list of files.
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
std::string CWD()
Definition: Rocin.C:2762
static void finalize()
Destroy the I/O thread.
Definition: HDF4.C:128
void free_blocks(BLOCK &blocks)
Definition: Rocin.C:2342
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
std::multimap< std::string, Block_HDF4 * > BlockMM_HDF4
Definition: rocin_block.h:102
unsigned long time()
Get the value of a system timer with a millisecond precision.
Definition: CImg.h:4605
NT q
void obtain_attribute(const COM::Attribute *attribute_in, COM::Attribute *user_attribute, int *pane_id=NULL)
Fill the destination (second) attribute from files using the data corresponding to the source (first)...
Definition: Rocin.C:2431
void explicit_local(const int &pid, const int &comm_rank, const int &comm_size, int *il)
Definition: Rocin.C:2446
void read_by_control_file(const char *control_file_name, const char *window_name, const MPI_Comm *comm=NULL, char *time_level=NULL, const int *str_len=NULL)
Create a single Roccom window by reading in the files specified by the given control file...
Definition: Rocin.C:2466
static int32 SDstart(const char *filename, int32 accessMode)
Definition: HDF4.C:177
AutoCloser(T1 id, T2(*f)(T1))
Definition: Rocin.C:182
static void new_attributes(BlockMM_HDF4::iterator hdf4, const BlockMM_HDF4::iterator &hdf4End, const std::string &window, const MPI_Comm *comm, int rank, int nprocs)
Definition: Rocin.C:2032
static intn SDgetdatastrs(int32 sds_id, char *label, char *units, char *format, char *coordsys, intn length)
Definition: HDF4.C:376
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 COM_free_buffer(int **buf)
Definition: roccom_c++.h:397
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
static int glob_error(const char *epath, int gerrno)
Error callback for glob.
Definition: Rocin.C:119
T1 m_id
Definition: Rocin.C:185
std::vector< VarInfo_HDF4 > m_variables
Info on each variable.
Definition: rocin_block.h:100
Fortran Data types.
Definition: roccom_basic.h:133
int COMMPI_Initialized()
Definition: commpi.h:168
MPI_Comm COM_get_default_communicator()
Definition: roccom_c++.h:69
MemberRulePtr m_is_local
Definition: Rocin.h:241
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation ** files(the"Software")
void COM_resize_array(const char *wa_str, int pane_id=0, void **addr=NULL, int strd=-1, int cap=0)
Resize an attribute on a specific pane and return the address by setting addr.
Definition: roccom_c++.h:200
#define CG_CHECK(routine, args)
Perform CGNS error-checking.
Definition: Rocout_cgns.C:68
int m_offset
Definition: Rocin.h:244
int COM_get_status(const char *waname, const int pane_id)
Definition: roccom_c++.h:431
std::string time_level
The dataset&#39;s time stamp.
Definition: rocin_block.h:95
void Rocin_unload_module(const char *name)
Unload the module Rocin from Roccom.
Definition: Rocin.C:3066