libMesh
Functions
meshid.C File Reference

Go to the source code of this file.

Functions

void handle_error (int error, std::string message)
 
void usage_error (const char *progname)
 
void gen_random_string (std::string &s, const int len)
 
int main (int argc, char **argv)
 

Function Documentation

void gen_random_string ( std::string &  s,
const int  len 
)

Definition at line 244 of file meshid.C.

References libmesh_nullptr.

Referenced by main().

245 {
246  static const char alphanum[] =
247  "0123456789"
248  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
249  "abcdefghijklmnopqrstuvwxyz";
250 
251  // Seed the random number generator with the current time
252  srand( static_cast<unsigned>(time(libmesh_nullptr)) );
253 
254  s.resize(len);
255  for (int i = 0; i < len; ++i)
256  {
257  unsigned int alphai = static_cast<unsigned int>
258  (rand() / (RAND_MAX+1.0) * (sizeof(alphanum)-1));
259  s[i] = alphanum[alphai];
260  }
261 }
const class libmesh_nullptr_t libmesh_nullptr
void handle_error ( int  error,
std::string  message 
)

Definition at line 224 of file meshid.C.

Referenced by main().

225 {
226  std::cout << "Error " << error << " occurred while working with the netCDF API" << std::endl;
227  std::cout << message << std::endl;
228 
229  exit(1);
230 }
int main ( int  argc,
char **  argv 
)

Definition at line 53 of file meshid.C.

References gen_random_string(), handle_error(), libMesh::Trees::NODES, and usage_error().

54 {
55  GetPot cl(argc, argv);
56 
57  // Command line parsing
58  if (!cl.search("--input"))
59  {
60  std::cerr << "No --input argument found!" << std::endl;
61  usage_error(argv[0]);
62  }
63  const char * meshname = cl.next("");
64 
65  if (!cl.search("--oldid"))
66  {
67  std::cerr << "No --oldid argument found!" << std::endl;
68  usage_error(argv[0]);
69  }
70  long oldid = cl.next(0);
71 
72  if (!cl.search("--newid"))
73  {
74  std::cerr << "No --newid argument found!" << std::endl;
75  usage_error(argv[0]);
76  }
77  long newid = cl.next(0);
78 
79  unsigned char flags = 0;
80  if (cl.search("--nodesetonly"))
81  flags |= NODES;
82  if (cl.search("--sidesetonly"))
83  flags |= SIDES;
84  if (cl.search("--blockonly"))
85  flags |= BLOCKS;
86  if (cl.search("--dim"))
87  flags |= EXODUS_DIM;
88 
89  // No command line flags were set, turn on NODES, SIDES, and BLOCKS
90  if (!flags)
91  flags = NODES | SIDES | BLOCKS; // ALL except EXODUS_DIM on
92 
93  // flags are exclusive
94  if (flags != NODES &&
95  flags != SIDES &&
96  flags != BLOCKS &&
97  flags != EXODUS_DIM &&
98  flags != (NODES | SIDES | BLOCKS))
99  {
100  std::cerr << "Only one of the following options may be active [--nodesetonly | --sidesetonly | --blockonly | --dim]!" << std::endl;
101  usage_error(argv[0]);
102  }
103 
104  // Processing
105  std::string var_name, dim_name;
106  int status;
107  int nc_id, var_id, dim_id;
108  size_t dim_len;
109 
110  status = nc_open (meshname, NC_WRITE, &nc_id);
111  if (status != NC_NOERR) handle_error(status, "Error while opening file.");
112 
113  for (unsigned char mask = 8; mask; mask/=2)
114  {
115  // These are char *'s #defined in exodusII_int.h
116  switch (flags & mask)
117  {
118  case BLOCKS:
119  dim_name = DIM_NUM_EL_BLK;
120  var_name = VAR_ID_EL_BLK;
121  break;
122  case SIDES:
123  dim_name = DIM_NUM_SS;
124  var_name = VAR_SS_IDS;
125  break;
126  case NODES:
127  dim_name = DIM_NUM_NS;
128  var_name = VAR_NS_IDS;
129  break;
130  case EXODUS_DIM:
131  dim_name = DIM_NUM_DIM;
132  // var_name not used for setting dimension
133  break;
134  default:
135  // We don't match this flag, so go to the next mask
136  continue;
137  }
138 
139  // Get the ID and length of the variable in question - stored in a dimension field
140  status = nc_inq_dimid (nc_id, dim_name.c_str(), &dim_id);
141  if (status != NC_NOERR) handle_error(status, "Error while inquiring about a dimension's ID.");
142 
143  status = nc_inq_dimlen (nc_id, dim_id, &dim_len);
144  if (status != NC_NOERR) handle_error(status, "Error while inquiring about a dimension's length.");
145 
146  if ((flags & mask) != EXODUS_DIM)
147  {
148  // Now get the variable values themselves
149  std::vector<long> var_vals(dim_len);
150 
151  status = nc_inq_varid (nc_id, var_name.c_str(), &var_id);
152  if (status != NC_NOERR) handle_error(status, "Error while inquiring about a variable's ID.");
153 
154  status = nc_get_var_long (nc_id, var_id, &var_vals[0]);
155  if (status != NC_NOERR) handle_error(status, "Error while retrieving a variable's values.");
156 
157  // Update the variable value specified on the command line
158  for (unsigned int i=0; i<dim_len; ++i)
159  if (var_vals[i] == oldid)
160  var_vals[i] = newid;
161 
162  // Save that value back to the NetCDF database
163  status = nc_put_var_long (nc_id, var_id, &var_vals[0]);
164  if (status != NC_NOERR) handle_error(status, "Error while writing a variable's values.");
165  }
166 
167  // Redefine the dimension
168  else
169  {
170  // The value stored in dim_len is actually the dimension?
171  if (dim_len == (size_t)oldid)
172  {
173  // Trying to change def's always raises
174  // Error -38: /* Operation not allowed in data mode */
175  // unless you are in "define" mode. So let's go there now.
176 
177  // Try to put the file into define mode
178  status = nc_redef(nc_id);
179  if (status != NC_NOERR) handle_error(status, "Error while putting file into define mode.");
180 
181  // Rename the "num_dim" dimension. Note: this will fail if there is already a dimension
182  // which has the name you are trying to use. This can happen, for example if you have already
183  // changed the dimension of this exodus file once using this very script. There appears
184  // to be no way to delete a dimension using basic NetCDF interfaces, so to workaround this
185  // we just rename it to an arbitrary unique string that Exodus will ignore.
186 
187  // Construct a string with 6 random alpha-numeric characters at the end.
188  std::string random_dim_name;
189  gen_random_string(random_dim_name, 6);
190  random_dim_name = std::string("ignored_num_dim_") + random_dim_name;
191 
192  // Rename the old dimension variable to our randomly-chosen name
193  status = nc_rename_dim(nc_id, dim_id, random_dim_name.c_str());
194  if (status != NC_NOERR) handle_error(status, "Error while trying to rename num_dim.");
195 
196  // Now define a new "num_dim" value of newid
197  int dummy=0;
198  status = nc_def_dim (nc_id, dim_name.c_str(), newid, &dummy);
199  if (status != NC_NOERR) handle_error(status, "Error while trying to define num_dim.");
200 
201  // Leave define mode
202  status = nc_enddef(nc_id);
203  if (status != NC_NOERR) handle_error(status, "Error while leaving define mode.");
204  }
205  }
206  } // end for
207 
208  // Write out the dataset
209  status = nc_close(nc_id);
210 
211  return (status != NC_NOERR);
212 }
MPI_Status status
Status object for querying messages.
Definition: parallel.h:176
void gen_random_string(std::string &s, const int len)
Definition: meshid.C:244
void usage_error(const char *progname)
Definition: meshid.C:234
void handle_error(int error, std::string message)
Definition: meshid.C:224
void usage_error ( const char *  progname)

Definition at line 234 of file meshid.C.

Referenced by main().

235 {
236  std::cout << "Usage: " << progname
237  << " --input inputmesh --oldid <n> --newid <n> [--nodesetonly | --sidesetonly | --blockonly]"
238  << std::endl;
239  exit(1);
240 }