1 /*
2  * Copyright (c) 1998 Sandia Corporation. Under the terms of Contract
3  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement
4  * retains certain rights in this software.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *
13  *     * Redistributions in binary form must reproduce the above
14  *       copyright notice, this list of conditions and the following
15  *       disclaimer in the documentation and/or other materials provided
16  *       with the distribution.
17  *
18  *     * Neither the name of Sandia Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35 /*****************************************************************************/
36 /*****************************************************************************/
37 /* Function(s) contained in this file:
38  *      ex_get_loadbal_param()
39  *****************************************************************************
40  * This function retrieves the load balance parameters.
41  *****************************************************************************
42  *  Variable Index:
43  *      exoid             - The NetCDF ID of an already open NemesisI file.
44  *      num_int_nodes    - The number of internal FEM nodes.
45  *      num_bor_nodes    - The number of border FEM nodes.
46  *      num_ext_nodes    - The number of external FEM nodes.
47  *      num_int_elems    - The number of internal FEM elements.
48  *      num_bor_elems    - The number of border FEM elements.
49  *      num_node_cmaps   - The number of nodal communication maps.
50  *      num_elem_cmaps   - The number of elemental communication maps.
51  *      processor        - The processor the file being read was written for.
52  */
53 /*****************************************************************************/
54 /*****************************************************************************/
55 /*****************************************************************************/
56 
57 #include <stdio.h>
58 
59 #include <netcdf.h>
60 
61 #include "exodusII.h"
62 #include "exodusII_int.h"
63 
ex_get_loadbal_param(int exoid,void_int * num_int_nodes,void_int * num_bor_nodes,void_int * num_ext_nodes,void_int * num_int_elems,void_int * num_bor_elems,void_int * num_node_cmaps,void_int * num_elem_cmaps,int processor)64 int ex_get_loadbal_param(int   exoid,
65                          void_int  *num_int_nodes,
66                          void_int  *num_bor_nodes,
67                          void_int  *num_ext_nodes,
68                          void_int  *num_int_elems,
69                          void_int  *num_bor_elems,
70                          void_int  *num_node_cmaps,
71                          void_int  *num_elem_cmaps,
72                          int   processor
73                          )
74 {
75   const char  *func_name="ex_get_loadbal_param";
76 
77   int     dimid, varid, status;
78   size_t  start[1];
79   size_t  nin, nbn, nen, nie, nbe, nncm, necm;
80   int64_t varidx[2];
81   char    ftype[2];
82   int     nmstat;
83 
84   char   errmsg[MAX_ERR_LENGTH];
85   /*-----------------------------Execution begins-----------------------------*/
86   if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
87     *(int64_t*)num_int_nodes = 0;
88     *(int64_t*)num_bor_nodes = 0;
89     *(int64_t*)num_ext_nodes = 0;
90     *(int64_t*)num_int_elems = 0;
91     *(int64_t*)num_bor_elems = 0;
92     *(int64_t*)num_node_cmaps = 0;
93     *(int64_t*)num_elem_cmaps = 0;
94   } else {
95     *(int*)num_int_nodes = 0;
96     *(int*)num_bor_nodes = 0;
97     *(int*)num_ext_nodes = 0;
98     *(int*)num_int_elems = 0;
99     *(int*)num_bor_elems = 0;
100     *(int*)num_node_cmaps = 0;
101     *(int*)num_elem_cmaps = 0;
102   }
103 
104   exerrval = 0; /* clear error code */
105 
106   /* Check the file version information */
107   if ((dimid=ne_check_file_version(exoid)) != EX_NOERR) return (dimid);
108 
109   /* Get the file type */
110   if (ex_get_file_type(exoid, ftype) != EX_NOERR) {
111     exerrval = EX_MSG;
112     sprintf(errmsg,
113             "Error: unable to find file type for file ID %d",
114             exoid);
115     ex_err(func_name, errmsg, exerrval);
116 
117     return (EX_FATAL);
118   }
119 
120   /* Get the status for this node map */
121   if ((status = nc_inq_varid(exoid, VAR_INT_N_STAT, &varid)) != NC_NOERR) {
122     exerrval = status;
123     sprintf(errmsg,
124             "Error: failed to find variable ID for \"%s\" from file ID %d",
125             VAR_INT_N_STAT, exoid);
126     ex_err(func_name, errmsg, exerrval);
127 
128     return (EX_FATAL);
129   }
130 
131   if (ftype[0] == 's')
132     start[0] = processor;
133   else
134     start[0] = 0;
135 
136   if ((status = nc_get_var1_int(exoid, varid, start, &nmstat)) != NC_NOERR) {
137     exerrval = status;
138     sprintf(errmsg,
139 	    "Error: failed to get status for \"%s\" from file ID %d",
140 	    VAR_INT_N_STAT, exoid);
141     ex_err(func_name, errmsg, exerrval);
142     return (EX_FATAL);
143   }
144 
145   if (nmstat == 1) {
146     if (ex_get_idx(exoid, VAR_NODE_MAP_INT_IDX, varidx, processor) == -1) {
147       exerrval = status;
148       sprintf(errmsg,
149 	      "Error: failed to find index variable, \"%s\", in file ID %d",
150 	      VAR_NODE_MAP_INT_IDX, exoid);
151       ex_err(func_name, errmsg, exerrval);
152 
153       return (EX_FATAL);
154     }
155 
156     /* check if I need to get the dimension of the internal node map */
157     if (varidx[1] == -1) {
158       /* Get the dimension ID for the number of internal nodes */
159       if ((status = nc_inq_dimid(exoid, DIM_NUM_INT_NODES, &dimid)) != NC_NOERR) {
160 	exerrval = status;
161 	sprintf(errmsg,
162 		"Error: failed to find dimension ID for \"%s\" in file ID %d",
163 		DIM_NUM_INT_NODES, exoid);
164 	ex_err(func_name, errmsg, exerrval);
165 
166 	return (EX_FATAL);
167       }
168 
169       /*
170        * Get the value of the dimension representing the total number of
171        * internal FEM nodes.
172        */
173       if ((status = nc_inq_dimlen(exoid, dimid, &nin)) != NC_NOERR) {
174 	exerrval = status;
175 	sprintf(errmsg,
176 		"Error: failed to find length of dimension \"%s\" in file ID %d",
177 		DIM_NUM_INT_NODES, exoid);
178 	ex_err(func_name, errmsg, exerrval);
179 
180 	return (EX_FATAL);
181       }
182 
183       /* set the end value for the node map */
184       varidx[1] = nin;
185     }  /* End "if (varidx[1] = -1)" */
186 
187     /* now get the number of nodes */
188     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
189       *(int64_t*)num_int_nodes = varidx[1] - varidx[0];
190     } else {
191       *(int*)num_int_nodes = varidx[1] - varidx[0];
192     }
193   }
194 
195   /* Get the status for this node map */
196   if ((status = nc_inq_varid(exoid, VAR_BOR_N_STAT, &varid)) != NC_NOERR) {
197     exerrval = status;
198     sprintf(errmsg,
199 	    "Error: failed to find variable ID for \"%s\" from file ID %d",
200 	    VAR_BOR_N_STAT, exoid);
201     ex_err(func_name, errmsg, exerrval);
202 
203     return (EX_FATAL);
204   }
205 
206   if (ftype[0] == 's')
207     start[0] = processor;
208   else
209     start[0] = 0;
210 
211   if ((status = nc_get_var1_int(exoid, varid, start, &nmstat)) != NC_NOERR) {
212     exerrval = status;
213     sprintf(errmsg,
214 	    "Error: failed to get status for \"%s\" from file ID %d",
215 	    VAR_BOR_N_STAT, exoid);
216     ex_err(func_name, errmsg, exerrval);
217     return (EX_FATAL);
218   }
219 
220   if (nmstat == 1) {
221     if (ex_get_idx(exoid, VAR_NODE_MAP_BOR_IDX, varidx, processor) == -1) {
222       exerrval = status;
223       sprintf(errmsg,
224 	      "Error: failed to find index variable, \"%s\", in file ID %d",
225 	      VAR_NODE_MAP_BOR_IDX, exoid);
226       ex_err(func_name, errmsg, exerrval);
227 
228       return (EX_FATAL);
229     }
230 
231     /* check if I need to get the dimension of the border node map */
232     if (varidx[1] == -1) {
233       /* Get the dimension ID for the number of border nodes */
234       if ((status = nc_inq_dimid(exoid, DIM_NUM_BOR_NODES, &dimid)) != NC_NOERR) {
235 	exerrval = status;
236 	sprintf(errmsg,
237 		"Error: failed to find dimension ID for \"%s\" in file ID %d",
238 		DIM_NUM_BOR_NODES, exoid);
239 	ex_err(func_name, errmsg, exerrval);
240 
241 	return (EX_FATAL);
242       }
243 
244       /*
245        * Get the value of the dimension representing the number of border
246        * FEM nodes.
247        */
248       if ((status = nc_inq_dimlen(exoid, dimid, &nbn)) != NC_NOERR) {
249 	exerrval = status;
250 	sprintf(errmsg,
251 		"Error: failed to find length of dimension \"%s\" in file ID %d",
252 		DIM_NUM_BOR_NODES, exoid);
253 	ex_err(func_name, errmsg, exerrval);
254 
255 	return (EX_FATAL);
256       }
257 
258       /* set the end value for the node map */
259       varidx[1] = nbn;
260     }  /* End "if (varidx[1] == -1)" */
261 
262     /* now calculate the number of nodes */
263     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
264       *(int64_t*)num_bor_nodes = varidx[1] - varidx[0];
265     } else {
266       *(int*)num_bor_nodes = varidx[1] - varidx[0];
267     }
268   }
269 
270   /* Get the status for this node map */
271   if ((status = nc_inq_varid(exoid, VAR_EXT_N_STAT, &varid)) != NC_NOERR) {
272     exerrval = status;
273     sprintf(errmsg,
274 	    "Error: failed to find variable ID for \"%s\" from file ID %d",
275 	    VAR_EXT_N_STAT, exoid);
276     ex_err(func_name, errmsg, exerrval);
277 
278     return (EX_FATAL);
279   }
280 
281   if (ftype[0] == 's')
282     start[0] = processor;
283   else
284     start[0] = 0;
285 
286   if ((status = nc_get_var1_int(exoid, varid, start, &nmstat)) != NC_NOERR) {
287     exerrval = status;
288     sprintf(errmsg,
289 	    "Error: failed to get status for \"%s\" from file ID %d",
290 	    VAR_EXT_N_STAT, exoid);
291     ex_err(func_name, errmsg, exerrval);
292     return (EX_FATAL);
293   }
294 
295   if (nmstat == 1) {
296     if (ex_get_idx(exoid, VAR_NODE_MAP_EXT_IDX, varidx, processor) == -1) {
297       exerrval = status;
298       sprintf(errmsg,
299 	      "Error: failed to find index variable, \"%s\", in file ID %d",
300 	      VAR_NODE_MAP_EXT_IDX, exoid);
301       ex_err(func_name, errmsg, exerrval);
302 
303       return (EX_FATAL);
304     }
305 
306     /* check if I need to get the dimension of the external node map */
307     if (varidx[1] == -1) {
308       /* Get the dimension ID for the number of external nodes */
309       if ((status = nc_inq_dimid(exoid, DIM_NUM_EXT_NODES, &dimid)) != NC_NOERR) {
310 	exerrval = status;
311 	sprintf(errmsg,
312 		"Error: failed to find dimension ID for \"%s\" in file ID %d",
313 		DIM_NUM_EXT_NODES, exoid);
314 	ex_err(func_name, errmsg, exerrval);
315 
316 	return (EX_FATAL);
317       }
318 
319       /*
320        * Get the value of the dimension representing the number of external
321        * FEM nodes.
322        */
323       if ((status = nc_inq_dimlen(exoid, dimid, &nen)) != NC_NOERR) {
324 	exerrval = status;
325 	sprintf(errmsg,
326 		"Error: failed to find length of dimension \"%s\" in file ID %d",
327 		DIM_NUM_EXT_NODES, exoid);
328 	ex_err(func_name, errmsg, exerrval);
329 
330 	return (EX_FATAL);
331       }
332       /* set the end value for the node map */
333       varidx[1] = nen;
334     }  /* End "if (varidx[1] == -1)" */
335 
336     /* now get the number of nodes */
337     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
338       *(int64_t*)num_ext_nodes = varidx[1] - varidx[0];
339     } else {
340       *(int*)num_ext_nodes = varidx[1] - varidx[0];
341     }
342   }
343 
344   /* Get the status for this element map */
345   if ((status = nc_inq_varid(exoid, VAR_INT_E_STAT, &varid)) != NC_NOERR) {
346     exerrval = status;
347     sprintf(errmsg,
348 	    "Error: failed to find variable ID for \"%s\" from file ID %d",
349 	    VAR_INT_E_STAT, exoid);
350     ex_err(func_name, errmsg, exerrval);
351     return (EX_FATAL);
352   }
353 
354   if (ftype[0] == 's')
355     start[0] = processor;
356   else
357     start[0] = 0;
358 
359   if ((status = nc_get_var1_int(exoid, varid, start, &nmstat)) != NC_NOERR) {
360     exerrval = status;
361     sprintf(errmsg,
362 	    "Error: failed to get status for \"%s\" from file ID %d",
363 	    VAR_INT_E_STAT, exoid);
364     ex_err(func_name, errmsg, exerrval);
365     return (EX_FATAL);
366   }
367 
368   if (nmstat == 1) {
369     if (ex_get_idx(exoid, VAR_ELEM_MAP_INT_IDX, varidx, processor) == -1) {
370       exerrval = status;
371       sprintf(errmsg,
372 	      "Error: failed to find index variable, \"%s\", in file ID %d",
373 	      VAR_ELEM_MAP_INT_IDX, exoid);
374       ex_err(func_name, errmsg, exerrval);
375 
376       return (EX_FATAL);
377     }
378 
379     /* check if I need to get the dimension of the internal element map */
380     if (varidx[1] == -1) {
381       /* Get the dimension ID for the number of internal elements */
382       if ((status = nc_inq_dimid(exoid, DIM_NUM_INT_ELEMS, &dimid)) != NC_NOERR) {
383 	exerrval = status;
384 	sprintf(errmsg,
385 		"Error: failed to find dimension ID for \"%s\" from file ID %d",
386 		DIM_NUM_INT_ELEMS, exoid);
387 	ex_err(func_name, errmsg, exerrval);
388 
389 	return (EX_FATAL);
390       }
391 
392       /*
393        * Get the value of the dimension representing the number of internal
394        * FEM elements.
395        */
396       if ((status = nc_inq_dimlen(exoid, dimid, &nie)) != NC_NOERR) {
397 	exerrval = status;
398 	sprintf(errmsg,
399 		"Error: failed to find length of dimesion \"%s\" in file ID %d",
400 		DIM_NUM_INT_ELEMS, exoid);
401 	ex_err(func_name, errmsg, exerrval);
402 	return (EX_FATAL);
403       }
404 
405       /* set the end value for the node map */
406       varidx[1] = nie;
407     }  /* End "if (varidx[1] == -1)" */
408 
409     /* now get the number of elements */
410     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
411       *(int64_t*)num_int_elems = varidx[1] - varidx[0];
412     } else {
413       *(int*)num_int_elems = varidx[1] - varidx[0];
414     }
415   }
416 
417   /* Get the status for this element map */
418   if ((status = nc_inq_varid(exoid, VAR_BOR_E_STAT, &varid)) != NC_NOERR) {
419     exerrval = status;
420     sprintf(errmsg,
421 	    "Error: failed to find variable ID for \"%s\" from file ID %d",
422 	    VAR_BOR_E_STAT, exoid);
423     ex_err(func_name, errmsg, exerrval);
424     return (EX_FATAL);
425   }
426 
427   if (ftype[0] == 's')
428     start[0] = processor;
429   else
430     start[0] = 0;
431 
432   if ((status = nc_get_var1_int(exoid, varid, start, &nmstat)) != NC_NOERR) {
433     exerrval = status;
434     sprintf(errmsg,
435 	    "Error: failed to get status for \"%s\" from file ID %d",
436 	    VAR_BOR_E_STAT, exoid);
437     ex_err(func_name, errmsg, exerrval);
438     return (EX_FATAL);
439   }
440 
441   if (nmstat == 1) {
442     if (ex_get_idx(exoid, VAR_ELEM_MAP_BOR_IDX, varidx, processor) == -1) {
443       exerrval = status;
444       sprintf(errmsg,
445 	      "Error: failed to find index variable, \"%s\", in file ID %d",
446 	      VAR_ELEM_MAP_BOR_IDX, exoid);
447       ex_err(func_name, errmsg, exerrval);
448 
449       return (EX_FATAL);
450     }
451 
452     /* check if I need to get the dimension of the border element map */
453     if (varidx[1] == -1) {
454       /* Get the dimension ID for the number of border elements */
455       if ((status = nc_inq_dimid(exoid, DIM_NUM_BOR_ELEMS, &dimid)) != NC_NOERR) {
456 	exerrval = status;
457 	sprintf(errmsg,
458 		"Error: failed to find dimension ID for \"%s\" from file ID %d",
459 		DIM_NUM_BOR_ELEMS, exoid);
460 	ex_err(func_name, errmsg, exerrval);
461 
462 	return (EX_FATAL);
463       }
464 
465       /*
466        * Get the value of the dimension representing the number of border
467        * FEM elements.
468        */
469       if ((status = nc_inq_dimlen(exoid, dimid, &nbe)) != NC_NOERR) {
470 	exerrval = status;
471 	sprintf(errmsg,
472 		"Error: failed to find length of dimesion \"%s\" in file ID %d",
473 		DIM_NUM_BOR_ELEMS, exoid);
474 	ex_err(func_name, errmsg, exerrval);
475 	return (EX_FATAL);
476       }
477 
478       /* set the end value for the node map */
479       varidx[1] = nbe;
480     }  /* End "if (varidx[1] == -1)" */
481 
482     /* now get the number of nodes */
483     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
484       *(int64_t*)num_bor_elems = varidx[1] - varidx[0];
485     } else {
486       *(int*)num_bor_elems = varidx[1] - varidx[0];
487     }
488   } /* End "if (nmstat == 1)" */
489 
490   if (ex_get_idx(exoid, VAR_N_COMM_INFO_IDX, varidx, processor) == -1) {
491     exerrval = status;
492     sprintf(errmsg,
493 	    "Error: failed to find index variable, \"%s\", in file ID %d",
494 	    VAR_N_COMM_INFO_IDX, exoid);
495     ex_err(func_name, errmsg, exerrval);
496 
497     return (EX_FATAL);
498   }
499 
500   /* check if I need to get the dimension of the nodal comm map */
501   if (varidx[1] == -1) {
502     /* Get the nodal comm map information */
503     if ((status = nc_inq_dimid(exoid, DIM_NUM_N_CMAPS, &dimid)) != NC_NOERR)
504       varidx[1] = 0;
505     else {
506       if ((status = nc_inq_dimlen(exoid, dimid, &nncm)) != NC_NOERR) {
507 	exerrval = status;
508 	sprintf(errmsg,
509 		"Error: failed to find length of dimension \"%s\" in file ID %d",
510 		DIM_NUM_N_CMAPS, exoid);
511 	ex_err(func_name, errmsg, exerrval);
512 	return (EX_FATAL);
513       }
514       /* set the end value for the node map */
515       varidx[1] = nncm;
516     }
517   }  /* End "if (varidx[1] == -1)" */
518 
519     if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
520       *(int64_t*)num_node_cmaps = varidx[1] - varidx[0];
521     } else {
522       *(int*)num_node_cmaps = varidx[1] - varidx[0];
523     }
524 
525   if (ex_get_idx(exoid, VAR_E_COMM_INFO_IDX, varidx, processor) == -1) {
526     exerrval = status;
527     sprintf(errmsg,
528 	    "Error: failed to find index variable, \"%s\", in file ID %d",
529 	    VAR_E_COMM_INFO_IDX, exoid);
530     ex_err(func_name, errmsg, exerrval);
531 
532     return (EX_FATAL);
533   }
534 
535   /* check if I need to get the dimension of the elemental comm map */
536   if (varidx[1] == -1) {
537     /* Get the elemental comm map information */
538     if ((status = nc_inq_dimid(exoid, DIM_NUM_E_CMAPS, &dimid)) != NC_NOERR)
539       varidx[1] = 0;
540     else {
541       if ((status = nc_inq_dimlen(exoid, dimid, &necm)) != NC_NOERR) {
542 	exerrval = status;
543 	sprintf(errmsg,
544 		"Error: failed to find length of dimension \"%s\" in file ID %d",
545 		DIM_NUM_E_CMAPS, exoid);
546 	ex_err(func_name, errmsg, exerrval);
547 	return (EX_FATAL);
548       }
549 
550       /* set the end value for the node map */
551       varidx[1] = necm;
552     }
553   }  /* End "if (varidx[1] == -1)" */
554 
555   if (ex_int64_status(exoid) & EX_BULK_INT64_API) {
556     *(int64_t*)num_elem_cmaps = varidx[1] - varidx[0];
557   } else {
558     *(int*)num_elem_cmaps = varidx[1] - varidx[0];
559   }
560 
561   return (EX_NOERR);
562 }
563