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

◆ gen_random_string()

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

Definition at line 246 of file meshid.C.

Referenced by main().

247 {
248  static const char alphanum[] =
249  "0123456789"
250  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
251  "abcdefghijklmnopqrstuvwxyz";
252 
253  // Seed the random number generator with the current time
254  srand( static_cast<unsigned>(time(nullptr)) );
255 
256  s.resize(len);
257  for (int i = 0; i < len; ++i)
258  {
259  unsigned int alphai = static_cast<unsigned int>
260  (rand() / (RAND_MAX+1.0) * (sizeof(alphanum)-1));
261  s[i] = alphanum[alphai];
262  }
263 }

◆ handle_error()

void handle_error ( int  error,
std::string  message 
)

Definition at line 226 of file meshid.C.

Referenced by main().

227 {
228  std::cout << "Error " << error << " occurred while working with the netCDF API" << std::endl;
229  std::cout << message << std::endl;
230 
231  exit(1);
232 }

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 55 of file meshid.C.

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

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

◆ usage_error()

void usage_error ( const char *  progname)

Definition at line 236 of file meshid.C.

Referenced by main().

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