1 /*
2  * Copyright (c) 2006 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 #include "exodusII.h"
37 #include "exodusII_int.h"
38 #include <stdlib.h> /* for free() */
39 
40 /*! write out the connectivity array */
41 #define EX_WRITE_CONN(TNAME,VARCONN,VARCONNVAL) \
42    if (ex_int64_status(exoid) & EX_BULK_INT64_API) { \
43      status = nc_put_var_longlong(exoid, VARCONN, VARCONNVAL); \
44    } else { \
45      status = nc_put_var_int(exoid, VARCONN, VARCONNVAL); \
46    } \
47    if (status != NC_NOERR) { \
48       exerrval = status; \
49       sprintf(errmsg, \
50       "Error: failed to write connectivity array for %s block %"PRId64" in file id %d", \
51                 TNAME,blk_id,exoid); \
52       ex_err("ex_put_conn",errmsg, exerrval); \
53       return(EX_FATAL); \
54    }
55 
56 /*!
57  * writes the connectivity array for a block
58  * \param exoid           exodus file id
59  * \param blk_type        type of block
60  * \param blk_id          id of block
61  * \param node_conn       node-element connectivity
62  * \param elem_edge_conn  element-edge connectivity (NULL if none)
63  * \param elem_face_conn  element-face connectivity (NULL if none)
64  */
65 
ex_put_conn(int exoid,ex_entity_type blk_type,ex_entity_id blk_id,const void_int * node_conn,const void_int * elem_edge_conn,const void_int * elem_face_conn)66 int ex_put_conn (int   exoid,
67                  ex_entity_type blk_type,
68                  ex_entity_id   blk_id,
69                  const void_int  *node_conn,
70                  const void_int  *elem_edge_conn,
71                  const void_int  *elem_face_conn)
72 {
73    int connid=-1, blk_id_ndx, status;
74    char errmsg[MAX_ERR_LENGTH];
75 
76    exerrval = 0; /* clear error code */
77 
78    blk_id_ndx = ex_id_lkup(exoid,blk_type,blk_id);
79    if (exerrval != 0) {
80      if (exerrval == EX_NULLENTITY) {
81        sprintf(errmsg,
82          "Warning: connectivity array not allowed for NULL %s block %"PRId64" in file id %d",
83 	       ex_name_of_object(blk_type),blk_id,exoid);
84        ex_err("ex_put_conn",errmsg,EX_MSG);
85        return (EX_WARN);
86        }
87      else {
88        sprintf(errmsg,
89          "Error: failed to locate %s block id %"PRId64" in id array in file id %d",
90          ex_name_of_object(blk_type),blk_id, exoid);
91        ex_err("ex_put_conn",errmsg,exerrval);
92        return (EX_FATAL);
93        }
94      }
95 
96 /* inquire id's of previously defined dimensions  */
97    if (node_conn) {
98      switch (blk_type) {
99      case EX_ELEM_BLOCK:
100        status = nc_inq_varid (exoid, VAR_CONN(blk_id_ndx), &connid);
101        break;
102      case EX_FACE_BLOCK:
103        status = nc_inq_varid (exoid, VAR_FBCONN(blk_id_ndx), &connid);
104        break;
105      case EX_EDGE_BLOCK:
106        status = nc_inq_varid (exoid, VAR_EBCONN(blk_id_ndx), &connid);
107        break;
108      default:
109        exerrval = 1005;
110        sprintf(errmsg,
111 	       "Internal Error: unrecognized block type in switch: %d in file id %d",
112 	       blk_type,exoid);
113        ex_err("ex_putt_conn",errmsg,EX_MSG);
114        return (EX_FATAL);
115      }
116      if (status != NC_NOERR) {
117        exerrval = status;
118        sprintf(errmsg,
119 	       "Error: failed to locate connectivity array for %s block %"PRId64" in file id %d",
120 	       ex_name_of_object(blk_type),blk_id,exoid);
121        ex_err("ex_put_conn",errmsg, exerrval);
122        return(EX_FATAL);
123      }
124 
125      EX_WRITE_CONN(ex_name_of_object(blk_type),connid,node_conn);
126    }
127 
128    /* If there are edge and face connectivity arrays that belong with the element
129     * block, write them now. Warn if they are required but not specified or
130     * specified but not required.
131     */
132    if ( blk_type == EX_ELEM_BLOCK ) {
133      int nedpereldim, nfapereldim;
134      size_t num_ed_per_elem, num_fa_per_elem;
135 
136      status = nc_inq_dimid (exoid, DIM_NUM_EDG_PER_EL(blk_id_ndx), &nedpereldim);
137      if (status != NC_NOERR && elem_edge_conn != 0)
138        {
139        exerrval = status;
140        sprintf(errmsg,
141          "Error: edge connectivity specified but failed to "
142          "locate number of edges/element in block %"PRId64" in file id %d",
143          blk_id,exoid);
144        ex_err("ex_put_conn",errmsg,exerrval);
145        return(EX_FATAL);
146        }
147 
148      status = nc_inq_dimid (exoid, DIM_NUM_FAC_PER_EL(blk_id_ndx), &nfapereldim);
149      if (status != NC_NOERR && elem_face_conn != 0)
150        {
151        exerrval = status;
152        sprintf(errmsg,
153          "Error: face connectivity specified but failed to "
154          "locate number of faces/element in block %"PRId64" in file id %d",
155          blk_id,exoid);
156        ex_err("ex_put_conn",errmsg,exerrval);
157        return(EX_FATAL);
158        }
159 
160      num_ed_per_elem = 0;
161      if ((elem_edge_conn != 0) &&
162 	 (status = nc_inq_dimlen(exoid, nedpereldim, &num_ed_per_elem) != NC_NOERR))
163        {
164        exerrval = status;
165        sprintf(errmsg,
166          "Error: failed to get number of edges/elem in block %"PRId64" in file id %d",
167          blk_id,exoid);
168        ex_err("ex_put_conn",errmsg,exerrval);
169        return(EX_FATAL);
170        }
171 
172      num_fa_per_elem = 0;
173      if ((elem_face_conn != 0) &&
174 	 (status = nc_inq_dimlen(exoid, nfapereldim, &num_fa_per_elem) != NC_NOERR))
175        {
176        exerrval = status;
177        sprintf(errmsg,
178          "Error: failed to get number of faces/elem in block %"PRId64" in file id %d",
179          blk_id,exoid);
180        ex_err("ex_put_conn",errmsg,exerrval);
181        return(EX_FATAL);
182        }
183 
184      if ( (num_ed_per_elem == 0 && elem_edge_conn != 0) ||
185           (num_ed_per_elem != 0 && elem_edge_conn == 0) )
186        {
187        exerrval = (EX_FATAL);
188        sprintf(errmsg,
189          "Error: number of edges per element (%ld) doesn't "
190          "agree with elem_edge_conn (0x%p)",
191 	       (long)num_ed_per_elem, (void*)elem_edge_conn );
192        ex_err("ex_put_conn",errmsg,exerrval);
193        return (EX_FATAL);
194        }
195 
196      if ( (num_fa_per_elem == 0 && elem_face_conn != 0) ||
197           (num_fa_per_elem != 0 && elem_face_conn == 0) )
198        {
199        exerrval = (EX_FATAL);
200        sprintf(errmsg,
201          "Error: number of faces per element (%ld) doesn't "
202          "agree with elem_face_conn (0x%p)",
203 	       (long)num_fa_per_elem, (void*)elem_face_conn );
204        ex_err("ex_put_conn",errmsg,exerrval);
205        return (EX_FATAL);
206        }
207 
208      if ( num_ed_per_elem != 0 ) {
209        status = nc_inq_varid(exoid, VAR_ECONN(blk_id_ndx), &connid);
210        if (status != NC_NOERR)
211          {
212          exerrval = status;
213          sprintf(errmsg,
214            "Error: failed to locate connectivity array for "
215            "element edge block %"PRId64" in file id %d",
216            blk_id,exoid);
217          ex_err("ex_put_conn",errmsg, exerrval);
218          return(EX_FATAL);
219          }
220        EX_WRITE_CONN("element edge",connid,elem_edge_conn);
221      }
222 
223      if ( num_fa_per_elem != 0 ) {
224        status = nc_inq_varid (exoid, VAR_FCONN(blk_id_ndx), &connid);
225        if (status != NC_NOERR)
226          {
227          exerrval = status;
228          sprintf(errmsg,
229            "Error: failed to locate connectivity array for "
230            "element face block %"PRId64" in file id %d",
231            blk_id,exoid);
232          ex_err("ex_put_conn",errmsg, exerrval);
233          return(EX_FATAL);
234          }
235        EX_WRITE_CONN("element face",connid,elem_face_conn);
236      }
237    }
238 
239    return (EX_NOERR);
240 
241 }
242