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 #include "exodusII.h"     // for ex_err, etc
10 #include "exodusII_int.h" // for ex__comp_ws, EX_FATAL, etc
11 
12 /*!
13  The function ex_get_glob_var_time() reads the values of a
14  single global variable through a specified number of time
15  steps. Memory must be allocated for the global variable values array
16  before this function is invoked.
17 
18  Because global variables are floating point values, the application
19  code must declare the array passed to be the appropriate type
20  (float or double) to match the compute word size passed in
21  ex_create() or ex_open().
22 
23 \return In case of an error, ex_get_glob_var_time() returns a
24  negative number; a warning will return a positive number. Possible
25  causes of errors include:
26   - data file not properly opened with call to ex_create() or ex_open()
27   - specified global variable does not exist.
28   - a warning value is returned if no global variables are stored in the file.
29 
30  \param exoid           exodus file ID returned from a previous call to
31 ex_create() or ex_open().
32 
33  \param glob_var_index  The index of the desired global variable. The first
34 variable has an index of 1.
35 
36  \param beg_time_step   The beginning time step for which a global variable
37 value is desired.
38                         This is not a time value but rather a time step number,
39 as
40                         described under ex_put_time(). The first time step is 1.
41 
42  \param end_time_step   The last time step for which a global variable value is
43 desired. If
44                         negative, the last time step in the database will be
45 used. The first
46                         time step is 1.
47 
48  \param[out] glob_var_vals Returned array of (end_time_step - beg_time_step + 1)
49 values
50                            for the glob_var_index$^{th}$ global variable.
51 
52 The following is an example of using this function:
53 
54 ~~~{.c}
55 int error, exoid, num_time_steps, var_index;
56 int beg_time, end_time;
57 
58 float *var_values;
59 
60 num_time_steps = ex_inquire_int(exoid, EX_INQ_TIME);
61 
62 var_index = 1;
63 beg_time = 1;
64 end_time = -1;
65 
66 var_values = (float *) calloc (num_time_steps, sizeof(float));
67 
68 error = ex_get_glob_var_time(exoid, var_index, beg_time,
69                              end_time, var_values);
70 ~~~
71 
72 */
73 
ex__get_glob_var_time(int exoid,int glob_var_index,int beg_time_step,int end_time_step,void * glob_var_vals)74 int ex__get_glob_var_time(int exoid, int glob_var_index, int beg_time_step, int end_time_step,
75                           void *glob_var_vals)
76 {
77   int    status;
78   int    varid;
79   size_t start[2], count[2];
80   char   errmsg[MAX_ERR_LENGTH];
81 
82   EX_FUNC_ENTER();
83   if (ex__check_valid_file_id(exoid, __func__) == EX_FATAL) {
84     EX_FUNC_LEAVE(EX_FATAL);
85   }
86 
87   /* Check that times are in range */
88   {
89     int num_time_steps = ex_inquire_int(exoid, EX_INQ_TIME);
90 
91     if (num_time_steps == 0) {
92       snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: there are no time_steps on the file id %d", exoid);
93       ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
94       EX_FUNC_LEAVE(EX_FATAL);
95     }
96 
97     if (beg_time_step <= 0 || beg_time_step > num_time_steps) {
98       snprintf(errmsg, MAX_ERR_LENGTH,
99                "ERROR: beginning time_step is out-of-range. Value = %d, "
100                "valid range is 1 to %d in file id %d",
101                beg_time_step, num_time_steps, exoid);
102       ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
103       EX_FUNC_LEAVE(EX_FATAL);
104     }
105 
106     if (end_time_step < 0) {
107       /* user is requesting the maximum time step;  we find this out using the
108        * database inquire function to get the number of time steps;  the ending
109        * time step number is 1 less due to 0 based array indexing in C
110        */
111       end_time_step = num_time_steps;
112     }
113     else if (end_time_step < beg_time_step || end_time_step > num_time_steps) {
114       snprintf(errmsg, MAX_ERR_LENGTH,
115                "ERROR: end time_step is out-of-range. Value = %d, valid "
116                "range is %d to %d in file id %d",
117                beg_time_step, end_time_step, num_time_steps, exoid);
118       ex_err_fn(exoid, __func__, errmsg, EX_BADPARAM);
119       EX_FUNC_LEAVE(EX_FATAL);
120     }
121   }
122   end_time_step--;
123 
124   /* read values of global variables */
125   start[0] = --beg_time_step;
126   start[1] = --glob_var_index;
127 
128   count[0] = end_time_step - beg_time_step + 1;
129   count[1] = 1;
130 
131   /* inquire previously defined variable */
132   if ((status = nc_inq_varid(exoid, VAR_GLO_VAR, &varid)) != NC_NOERR) {
133     snprintf(errmsg, MAX_ERR_LENGTH, "ERROR: failed to locate global variables in file id %d",
134              exoid);
135     ex_err_fn(exoid, __func__, errmsg, status);
136     EX_FUNC_LEAVE(EX_WARN);
137   }
138 
139   if (ex__comp_ws(exoid) == 4) {
140     status = nc_get_vara_float(exoid, varid, start, count, glob_var_vals);
141   }
142   else {
143     status = nc_get_vara_double(exoid, varid, start, count, glob_var_vals);
144   }
145 
146   if (status != NC_NOERR) {
147     snprintf(errmsg, MAX_ERR_LENGTH,
148              "ERROR: failed to get global variable %d values from file id %d", glob_var_index,
149              exoid);
150     ex_err_fn(exoid, __func__, errmsg, status);
151     EX_FUNC_LEAVE(EX_FATAL);
152   }
153   EX_FUNC_LEAVE(EX_NOERR);
154 }
155