libMesh
Loading...
Searching...
No Matches
meshid.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19// Open the mesh named in command line arguments,
20// update ids of one or more of the following entries
21// as prescribed on the command line:
22// blocks, sidesets and nodesets
23
24#include <iostream>
25#include <time.h> // time
26#include <stdlib.h> // rand, srand
27
28#include "libmesh/libmesh_config.h"
29
30#ifdef LIBMESH_HAVE_EXODUS_API
31
32#include "libmesh/ignore_warnings.h"
33#include "exodusII.h"
34#include "exodusII_int.h"
35#include "libmesh/restore_warnings.h"
36
37#include "libmesh/getpot.h"
38
39#define EXODUS_DIM 0x8
40#define BLOCKS 0x4
41#define SIDES 0x2
42#define NODES 0x1
43
44// Report error from NetCDF and exit
45void handle_error(int error, std::string message);
46
47// Report error in input flags and exit
48void usage_error(const char * progname);
49
50// Generate a random string, seed RNG with current time.
51void gen_random_string(std::string & s, const int len);
52
53
54
55int main(int argc, char ** argv)
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}
215
216#else // LIBMESH_HAVE_EXODUS_API
217
218int main(int, char **)
219{
220 std::cerr << "Error: meshid requires libMesh configured with --enable-exodus" << std::endl;
221}
222#endif // LIBMESH_HAVE_EXODUS_API
223
224
225
226void handle_error(int error, std::string message)
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}
233
234
235
236void usage_error(const char * progname)
237{
238 std::cout << "Usage: " << progname
239 << " --input inputmesh --oldid <n> --newid <n> [--nodesetonly | --sidesetonly | --blockonly]"
240 << std::endl;
241 exit(1);
242}
243
244
245
246void gen_random_string(std::string & s, const int len)
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}
void gen_random_string(std::string &s, const int len)
Definition meshid.C:246
void handle_error(int error, std::string message)
Definition meshid.C:226
void usage_error(const char *progname)
Definition meshid.C:236
int main()