1 /*
2  * Copyright(C) 1999-2020 National Technology & Engineering Solutions
3  * of Sandia, LLC (NTESS).  Under the terms of Contract DE-NA0003525 with
4  * NTESS, the U.S. Government retains certain rights in this software.
5  *
6  * See packages/seacas/LICENSE for details
7  */
8 /*****************************************************************************
9  *
10  * exgfrm - ex_get_coordinate_frames: read coordinate frames
11  *
12  * entry conditions -
13  *   input parameters:
14  *       int         exoid               exodus file id
15  *
16  * NOTE:
17  *    cf_ids, pt_coordinates and tags may all be NULL, otherwise, they
18  *    must have sufficient memory to store the output data. Two calls
19  *    to this routine are anticipated (one to get nframes, the second
20  *    to fill the data. i.e.
21  *      ex_get_coordinate_frames(exoid,&nframes,0,0,0);
22  *        ... allocate memory ...
23  *      ex_get_coordinate_frames(exoid,&nframe,id,coords,tags);
24  *
25  *
26  * output conditions -
27  *       int*         nframes             number of coordinate frames in model
28  *       const int*   cf_ids             coordinate ids
29  *                                       dimension int[nframes]
30  *       const void*  pt_coordinates     pointer to coordinates. 9 values per
31  *                                       coordinate frame
32  *                                       dimension float[9*nframes]
33  *       const char*  tags               character tag for each frame.
34  *                                        'r' - rectangular
35  *                                        'c' - cylindrical
36  *                                        's' - spherical
37  *                                        dimension char[nframes]
38  *
39  * returns -
40  *      EX_NOERR         for no error
41  *      EX_FATAL         for fatal errors
42  *
43  *****************************************************************************/
44 
45 #include "exodusII.h"     // for ex_err, etc
46 #include "exodusII_int.h" // for EX_FATAL, EX_NOERR, etc
47 
48 /*!
49  * Coordinate frames are stored in the database as a series of three
50  * points (defined in the basic cartesian coordinate system). The
51  * first of these points describes the origin of the new system.  The
52  * second point lies on the 3 axis (or Z axis) of the frame. The third
53  * point is in the 1-3 (xz) plane. Each coordinate frame is identified
54  * by a unique, integer coordinate ID, and by a character tag
55  * indicating whether the frame is rectangular cartesian
56  * "R", cylindrical "C, or spherical "S".
57  * Because the coordinates are floating point values,
58  * the application code must declare the arrays passed to be the
59  * appropriate type "float" or "double" to match the
60  * compute word size passed in ex_create() or
61  * ex_open().
62  * \param        exoid    exodus file id
63  * \param[in,out] nframes  if 'cf_ids' is NULL, then nframes is returned with
64  * the number
65  *                        of defined coordinate frames. Else it is the number of
66  * coordinate
67  *                        frames to read.
68  * \param[out] cf_ids The (nframes) coordinate frame Ids. If cf_ids is
69  *                    NULL, no data will be returned in this or any other array.
70  * Only
71  *                    nframes will be modified. Otherwise, space must be
72  * allocated to
73  *                    store 'nframes' integers before making this call.
74  * \param[out] pt_coordinates The (9*nframes) coordinates of the three
75  *                            points defining each coordinate axis. The first
76  * three values are
77  *                            the origin of the first frame. The next three
78  * values are the
79  *                            coordinates of a point on the 3rd axis of the
80  * first frame. The next
81  *                            three values are the coordinates of a point in the
82  * plane of the 1-3
83  *                            axis. The pattern is repeated for each frame. If
84  * 'cf_ids'
85  *                            is null, no data will be returned in this array.
86  * Otherwise, space
87  *                            must be allocated for 9*nframes floating point
88  * values. The size of
89  *                            the allocation depends upon the compute word size.
90  * \param[out] tags The (nframes) character tags associated with each
91  *                  coordinate frame. If 'cf_ids' is NULL, no data will be
92  *                  returned in this array. Otherwise, space must be allocated
93  * for
94  *                  'nframes' characters.
95  */
96 
ex_get_coordinate_frames(int exoid,int * nframes,void_int * cf_ids,void * pt_coordinates,char * tags)97 int ex_get_coordinate_frames(int exoid, int *nframes, void_int *cf_ids, void *pt_coordinates,
98                              char *tags)
99 
100 {
101   int    status;
102   int    dimid; /* ID of the dimension of # frames */
103   char   errmsg[MAX_ERR_LENGTH];
104   int    varids;    /* variable id for the frame ids  */
105   size_t start = 0; /* start value for varputs        */
106   size_t count = 0; /* number vars to put in varput   */
107 
108   EX_FUNC_ENTER();
109   if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) {
110     EX_FUNC_LEAVE(EX_FATAL);
111   }
112 
113   /* get the dimensions */
114   assert(nframes != NULL);
115   status = nc_inq_dimid(exoid, DIM_NUM_CFRAMES, &dimid);
116   if (status != NC_NOERR) {
117     *nframes = 0;
118     EX_FUNC_LEAVE(EX_NOERR);
119   }
120 
121   (void)nc_inq_dimlen(exoid, dimid, &count);
122   *nframes = (int)count;
123 
124   if (count == 0) {
125     EX_FUNC_LEAVE(EX_NOERR);
126   }
127 
128   if (cf_ids) {
129     if ((status = nc_inq_varid(exoid, VAR_FRAME_IDS, &varids)) != NC_NOERR) {
130       snprintf(errmsg, MAX_ERR_LENGTH,
131                "ERROR: failed to read number coordinate ids from file id %d", exoid);
132       ex_err_fn(exoid, __func__, errmsg, status);
133       EX_FUNC_LEAVE(EX_FATAL);
134     }
135 
136     if (ex_int64_status(exoid) & EX_IDS_INT64_API) {
137       status = nc_get_var_longlong(exoid, varids, cf_ids);
138     }
139     else {
140       status = nc_get_var_int(exoid, varids, cf_ids);
141     }
142 
143     if (status != NC_NOERR) {
144       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to read coordinate frame ids from file id %d",
145                exoid);
146       ex_err_fn(exoid, __func__, errmsg, status);
147       EX_FUNC_LEAVE(EX_FATAL);
148     }
149   }
150 
151   if (tags) {
152     if ((status = nc_inq_varid(exoid, VAR_FRAME_TAGS, &varids)) != NC_NOERR ||
153         (nc_get_vara_text(exoid, varids, &start, &count, tags) != NC_NOERR)) {
154       snprintf(errmsg, MAX_ERR_LENGTH,
155                "ERROR: failed to read number coordinate tags from file id %d", exoid);
156       ex_err_fn(exoid, __func__, errmsg, status);
157       EX_FUNC_LEAVE(EX_FATAL);
158     }
159   }
160 
161   if (pt_coordinates) {
162     if ((status = nc_inq_varid(exoid, VAR_FRAME_COORDS, &varids)) != NC_NOERR) {
163       snprintf(errmsg, MAX_ERR_LENGTH,
164                "ERROR: failed to read number coordinate tags from file id %d", exoid);
165       ex_err_fn(exoid, __func__, errmsg, status);
166       EX_FUNC_LEAVE(EX_FATAL);
167     }
168 
169     if (ex__comp_ws(exoid) == 4) {
170       status = nc_get_var_float(exoid, varids, pt_coordinates);
171     }
172     else {
173       status = nc_get_var_double(exoid, varids, pt_coordinates);
174     }
175 
176     if (status != NC_NOERR) {
177       snprintf(errmsg, MAX_ERR_LENGTH,
178                "ERROR: failed to read number coordinate tags from file id %d", exoid);
179       ex_err_fn(exoid, __func__, errmsg, status);
180       EX_FUNC_LEAVE(EX_FATAL);
181     }
182   }
183 
184   EX_FUNC_LEAVE(EX_NOERR);
185 }
186