Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #ifdef WIN32
17 : : #ifdef _DEBUG
18 : : // turn off warnings that say they debugging identifier has been truncated
19 : : // this warning comes up when using some STL containers
20 : : #pragma warning( disable : 4786 )
21 : : #endif
22 : : #endif
23 : :
24 : : #include "WriteNCDF.hpp"
25 : :
26 : : #include "netcdf.h"
27 : : #include <utility>
28 : : #include <algorithm>
29 : : #include <time.h>
30 : : #include <string>
31 : : #include <vector>
32 : : #include <stdio.h>
33 : : #include <string.h>
34 : : #include <assert.h>
35 : :
36 : : #include "moab/Interface.hpp"
37 : : #include "moab/Range.hpp"
38 : : #include "moab/CN.hpp"
39 : : #include "moab/FileOptions.hpp"
40 : : #include "MBTagConventions.hpp"
41 : : #include "Internals.hpp"
42 : : #include "ExoIIUtil.hpp"
43 : : #include "moab/WriteUtilIface.hpp"
44 : : #include "exodus_order.h"
45 : :
46 : : #ifndef MOAB_HAVE_NETCDF
47 : : #error Attempt to compile WriteNCDF with NetCDF support disabled
48 : : #endif
49 : :
50 : : namespace moab
51 : : {
52 : :
53 : : const int TIME_STR_LEN = 11;
54 : :
55 : : #define INS_ID( stringvar, prefix, id ) sprintf( stringvar, prefix, id )
56 : :
57 : : #define GET_DIM( ncdim, name, val ) \
58 : : { \
59 : : int gdfail = nc_inq_dimid( ncFile, name, &ncdim ); \
60 : : if( NC_NOERR == gdfail ) \
61 : : { \
62 : : size_t tmp_val; \
63 : : gdfail = nc_inq_dimlen( ncFile, ncdim, &tmp_val ); \
64 : : if( NC_NOERR != gdfail ) { MB_SET_ERR( MB_FAILURE, "WriteNCDF:: couldn't get dimension length" ); } \
65 : : else \
66 : : val = tmp_val; \
67 : : } \
68 : : else \
69 : : val = 0; \
70 : : }
71 : :
72 : : #define GET_DIMB( ncdim, name, varname, id, val ) \
73 : : INS_ID( name, varname, id ); \
74 : : GET_DIM( ncdim, name, val );
75 : :
76 : : #define GET_VAR( name, id, dims ) \
77 : : { \
78 : : id = -1; \
79 : : int gvfail = nc_inq_varid( ncFile, name, &id ); \
80 : : if( NC_NOERR == gvfail ) \
81 : : { \
82 : : int ndims; \
83 : : gvfail = nc_inq_varndims( ncFile, id, &ndims ); \
84 : : if( NC_NOERR == gvfail ) \
85 : : { \
86 : : dims.resize( ndims ); \
87 : : gvfail = nc_inq_vardimid( ncFile, id, &dims[0] ); \
88 : : } \
89 : : } \
90 : : }
91 : :
92 : 9 : WriterIface* WriteNCDF::factory( Interface* iface )
93 : : {
94 [ + - ]: 9 : return new WriteNCDF( iface );
95 : : }
96 : :
97 : 9 : WriteNCDF::WriteNCDF( Interface* impl )
98 [ + - ]: 9 : : mdbImpl( impl ), ncFile( 0 ), mCurrentMeshHandle( 0 ), mGeomDimensionTag( 0 ), repeat_face_blocks( 0 )
99 : : {
100 [ - + ]: 9 : assert( impl != NULL );
101 : :
102 [ + - ]: 9 : impl->query_interface( mWriteIface );
103 : :
104 : : // Initialize in case tag_get_handle fails below
105 : : //! Get and cache predefined tag handles
106 : 9 : int negone = -1;
107 : : impl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mMaterialSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
108 [ + - ]: 9 : &negone );
109 : :
110 : : impl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mDirichletSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
111 [ + - ]: 9 : &negone );
112 : :
113 : : impl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mNeumannSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
114 [ + - ]: 9 : &negone );
115 : :
116 [ + - ]: 9 : mGlobalIdTag = impl->globalId_tag();
117 : :
118 : 9 : int dum_val_array[] = { -1, -1, -1, -1 };
119 : : impl->tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, mHasMidNodesTag, MB_TAG_SPARSE | MB_TAG_CREAT,
120 [ + - ]: 9 : dum_val_array );
121 : :
122 : : impl->tag_get_handle( "distFactor", 0, MB_TYPE_DOUBLE, mDistFactorTag,
123 [ + - ]: 9 : MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_CREAT );
124 : :
125 [ + - ]: 9 : impl->tag_get_handle( "qaRecord", 0, MB_TYPE_OPAQUE, mQaRecordTag, MB_TAG_SPARSE | MB_TAG_VARLEN | MB_TAG_CREAT );
126 : :
127 [ + - ]: 9 : impl->tag_get_handle( "WriteNCDF element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT );
128 : 9 : }
129 : :
130 : 27 : WriteNCDF::~WriteNCDF()
131 : : {
132 : 9 : mdbImpl->release_interface( mWriteIface );
133 : :
134 : 9 : mdbImpl->tag_delete( mEntityMark );
135 : :
136 [ + - ]: 9 : if( 0 != ncFile ) ncFile = 0;
137 [ - + ]: 18 : }
138 : :
139 : 0 : void WriteNCDF::reset_block( std::vector< MaterialSetData >& block_info )
140 : : {
141 : 0 : std::vector< MaterialSetData >::iterator iter;
142 : :
143 [ # # ][ # # ]: 0 : for( iter = block_info.begin(); iter != block_info.end(); ++iter )
[ # # ]
144 : : {
145 [ # # ][ # # ]: 0 : iter->elements.clear();
146 : : }
147 : 0 : }
148 : :
149 : 18 : void WriteNCDF::time_and_date( char* time_string, char* date_string )
150 : : {
151 : : struct tm* local_time;
152 : : time_t calendar_time;
153 : :
154 : 18 : calendar_time = time( NULL );
155 : 18 : local_time = localtime( &calendar_time );
156 : :
157 [ + - ][ - + ]: 18 : assert( NULL != time_string && NULL != date_string );
158 : :
159 : 18 : strftime( time_string, TIME_STR_LEN, "%H:%M:%S", local_time );
160 : 18 : strftime( date_string, TIME_STR_LEN, "%m/%d/%Y", local_time );
161 : :
162 : : // Terminate with NULL character
163 : 18 : time_string[10] = (char)NULL;
164 : 18 : date_string[10] = (char)NULL;
165 : 18 : }
166 : :
167 : 9 : ErrorCode WriteNCDF::write_file( const char* exodus_file_name, const bool overwrite, const FileOptions& opts,
168 : : const EntityHandle* ent_handles, const int num_sets,
169 : : const std::vector< std::string >& qa_records, const Tag*, int, int user_dimension )
170 : : {
171 [ + - ][ + - ]: 9 : assert( 0 != mMaterialSetTag && 0 != mNeumannSetTag && 0 != mDirichletSetTag );
[ - + ]
172 : :
173 [ - + ][ # # ]: 9 : if( user_dimension == 0 ) mdbImpl->get_dimension( user_dimension );
174 : :
175 [ + - ][ - + ]: 9 : if( opts.get_null_option( "REPEAT_FACE_BLOCKS" ) == MB_SUCCESS ) repeat_face_blocks = 1;
176 : :
177 [ + - ][ + - ]: 18 : std::vector< EntityHandle > blocks, nodesets, sidesets, entities;
[ + - ][ + - ]
178 : :
179 : : // Separate into blocks, nodesets, sidesets
180 : :
181 [ + + ]: 9 : if( num_sets == 0 )
182 : : {
183 : : // Default to all defined block, nodeset and sideset-type sets
184 [ + - ]: 7 : Range this_range;
185 [ + - ]: 7 : mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mMaterialSetTag, NULL, 1, this_range );
186 [ + - ][ + - ]: 7 : std::copy( this_range.begin(), this_range.end(), std::back_inserter( blocks ) );
[ + - ][ + - ]
187 [ + - ]: 7 : this_range.clear();
188 [ + - ]: 7 : mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mDirichletSetTag, NULL, 1, this_range );
189 [ + - ][ + - ]: 7 : std::copy( this_range.begin(), this_range.end(), std::back_inserter( nodesets ) );
[ + - ][ + - ]
190 [ + - ]: 7 : this_range.clear();
191 [ + - ]: 7 : mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mNeumannSetTag, NULL, 1, this_range );
192 [ + - ][ + - ]: 7 : std::copy( this_range.begin(), this_range.end(), std::back_inserter( sidesets ) );
[ + - ][ + - ]
193 : :
194 : : // If there is nothing to write, write everything as one block.
195 [ - + ][ # # ]: 7 : if( blocks.empty() && nodesets.empty() && sidesets.empty() )
[ # # ][ - + ]
196 : : {
197 [ # # ]: 0 : this_range.clear();
198 [ # # ][ # # ]: 0 : for( int d = user_dimension; d > 0 && this_range.empty(); --d )
[ # # ][ # # ]
199 [ # # ]: 0 : mdbImpl->get_entities_by_dimension( 0, d, this_range, false );
200 [ # # ][ # # ]: 0 : if( this_range.empty() ) return MB_FILE_WRITE_ERROR;
201 : :
202 : : EntityHandle block_handle;
203 : 0 : int block_id = 1;
204 [ # # ]: 0 : mdbImpl->create_meshset( MESHSET_SET, block_handle );
205 [ # # ]: 0 : mdbImpl->tag_set_data( mMaterialSetTag, &block_handle, 1, &block_id );
206 [ # # ]: 0 : mdbImpl->add_entities( block_handle, this_range );
207 [ # # ][ + - ]: 7 : blocks.push_back( block_handle );
208 : 7 : }
209 : : }
210 : : else
211 : : {
212 : : int dummy;
213 [ + + ]: 4 : for( const EntityHandle* iter = ent_handles; iter < ent_handles + num_sets; ++iter )
214 : : {
215 [ + - ][ + - ]: 2 : if( MB_SUCCESS == mdbImpl->tag_get_data( mMaterialSetTag, &( *iter ), 1, &dummy ) && -1 != dummy )
[ + - ][ + - ]
216 [ + - ]: 2 : blocks.push_back( *iter );
217 [ # # ][ # # ]: 0 : else if( MB_SUCCESS == mdbImpl->tag_get_data( mDirichletSetTag, &( *iter ), 1, &dummy ) && -1 != dummy )
[ # # ][ # # ]
218 [ # # ]: 0 : nodesets.push_back( *iter );
219 [ # # ][ # # ]: 0 : else if( MB_SUCCESS == mdbImpl->tag_get_data( mNeumannSetTag, &( *iter ), 1, &dummy ) && -1 != dummy )
[ # # ][ # # ]
220 [ # # ]: 0 : sidesets.push_back( *iter );
221 : : }
222 : : }
223 : :
224 : : // If there is nothing to write just return.
225 [ - + ][ # # ]: 9 : if( blocks.empty() && nodesets.empty() && sidesets.empty() ) return MB_FILE_WRITE_ERROR;
[ # # ][ - + ]
226 : :
227 : : // Try to get mesh information
228 [ + - ]: 18 : ExodusMeshInfo mesh_info;
229 : :
230 [ + - ]: 18 : std::vector< MaterialSetData > block_info;
231 [ + - ]: 18 : std::vector< NeumannSetData > sideset_info;
232 [ + - ]: 18 : std::vector< DirichletSetData > nodeset_info;
233 : :
234 : 9 : mesh_info.num_dim = user_dimension;
235 : :
236 [ + - ]: 9 : if( qa_records.empty() )
237 : : {
238 : : // qa records are empty - initialize some MB-standard ones
239 [ + - ][ + - ]: 9 : mesh_info.qaRecords.push_back( "MB" );
240 [ + - ][ + - ]: 9 : mesh_info.qaRecords.push_back( "0.99" );
241 : : char string1[80], string2[80];
242 [ + - ]: 9 : time_and_date( string2, string1 );
243 [ + - ][ + - ]: 9 : mesh_info.qaRecords.push_back( string2 );
244 [ + - ][ + - ]: 9 : mesh_info.qaRecords.push_back( string1 );
245 : : }
246 : : else
247 : : {
248 : : // Constrained to multiples of 4 qa records
249 [ # # ]: 0 : assert( qa_records.size() % 4 == 0 );
250 : :
251 [ # # ][ # # ]: 0 : std::copy( qa_records.begin(), qa_records.end(), std::back_inserter( mesh_info.qaRecords ) );
252 : : }
253 : :
254 : 9 : block_info.clear();
255 [ + - ][ - + ]: 9 : if( gather_mesh_information( mesh_info, block_info, sideset_info, nodeset_info, blocks, sidesets, nodesets ) !=
256 : : MB_SUCCESS )
257 : : {
258 [ # # ]: 0 : reset_block( block_info );
259 : 0 : return MB_FAILURE;
260 : : }
261 : :
262 : : // Try to open the file after gather mesh info succeeds
263 [ + - ][ + - ]: 9 : int fail = nc_create( exodus_file_name, overwrite ? NC_CLOBBER : NC_NOCLOBBER, &ncFile );
264 [ - + ]: 9 : if( NC_NOERR != fail )
265 : : {
266 [ # # ]: 0 : reset_block( block_info );
267 : 0 : return MB_FAILURE;
268 : : }
269 : :
270 [ + - ][ - + ]: 9 : if( write_header( mesh_info, block_info, sideset_info, nodeset_info, exodus_file_name ) != MB_SUCCESS )
271 : : {
272 [ # # ]: 0 : reset_block( block_info );
273 : 0 : return MB_FAILURE;
274 : : }
275 : :
276 : : {
277 : : // write dummy time_whole
278 : 9 : double timev = 0.0; // dummy, to make paraview happy
279 : 9 : size_t start = 0, count = 1;
280 : : int nc_var;
281 [ + - ]: 9 : std::vector< int > dims;
282 [ + - ][ + - ]: 9 : GET_VAR( "time_whole", nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
283 [ + - ]: 9 : fail = nc_put_vara_double( ncFile, nc_var, &start, &count, &timev );
284 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing dist factor array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
285 : : }
286 : :
287 [ + - ][ - + ]: 9 : if( write_nodes( mesh_info.num_nodes, mesh_info.nodes, mesh_info.num_dim ) != MB_SUCCESS )
288 : : {
289 [ # # ]: 0 : reset_block( block_info );
290 : 0 : return MB_FAILURE;
291 : : }
292 : :
293 [ + - ][ - + ]: 9 : if( !mesh_info.polyhedronFaces.empty() )
294 : : {
295 [ # # ][ # # ]: 0 : if( write_poly_faces( mesh_info ) != MB_SUCCESS )
296 : : {
297 [ # # ]: 0 : reset_block( block_info );
298 : 0 : return MB_FAILURE;
299 : : }
300 : : }
301 : :
302 [ + - ][ - + ]: 9 : if( write_elementblocks( mesh_info, block_info ) )
303 : : {
304 [ # # ]: 0 : reset_block( block_info );
305 : 0 : return MB_FAILURE;
306 : : }
307 : :
308 : : // Write the three maps
309 [ + - ][ - + ]: 9 : if( write_global_node_order_map( mesh_info.num_nodes, mesh_info.nodes ) != MB_SUCCESS )
310 : : {
311 [ # # ]: 0 : reset_block( block_info );
312 : 0 : return MB_FAILURE;
313 : : }
314 : :
315 [ + - ][ - + ]: 9 : if( write_global_element_order_map( mesh_info.num_elements ) != MB_SUCCESS )
316 : : {
317 [ # # ]: 0 : reset_block( block_info );
318 : 0 : return MB_FAILURE;
319 : : }
320 : :
321 [ + - ][ - + ]: 9 : if( write_element_order_map( mesh_info.num_elements ) != MB_SUCCESS )
322 : : {
323 [ # # ]: 0 : reset_block( block_info );
324 : 0 : return MB_FAILURE;
325 : : }
326 : :
327 : : /*
328 : : if (write_elementmap(mesh_info) != MB_SUCCESS)
329 : : return MB_FAILURE;
330 : : */
331 : :
332 [ + - ][ - + ]: 9 : if( write_BCs( sideset_info, nodeset_info ) != MB_SUCCESS )
333 : : {
334 [ # # ]: 0 : reset_block( block_info );
335 : 0 : return MB_FAILURE;
336 : : }
337 : :
338 [ + - ][ - + ]: 9 : if( write_qa_records( mesh_info.qaRecords ) != MB_SUCCESS ) return MB_FAILURE;
339 : :
340 : : // Copy the qa records into the argument
341 : : // mesh_info.qaRecords.swap(qa_records);
342 : : // Close the file
343 [ + - ]: 9 : fail = nc_close( ncFile );
344 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Trouble closing file" ); }
[ # # ][ # # ]
[ # # ][ # # ]
345 : :
346 : 18 : return MB_SUCCESS;
347 : : }
348 : :
349 : 9 : ErrorCode WriteNCDF::gather_mesh_information( ExodusMeshInfo& mesh_info, std::vector< MaterialSetData >& block_info,
350 : : std::vector< NeumannSetData >& sideset_info,
351 : : std::vector< DirichletSetData >& nodeset_info,
352 : : std::vector< EntityHandle >& blocks,
353 : : std::vector< EntityHandle >& sidesets,
354 : : std::vector< EntityHandle >& nodesets )
355 : : {
356 : : ErrorCode rval;
357 : 9 : std::vector< EntityHandle >::iterator vector_iter, end_vector_iter;
358 : :
359 : 9 : mesh_info.num_nodes = 0;
360 : 9 : mesh_info.num_elements = 0;
361 : 9 : mesh_info.num_elementblocks = 0;
362 : 9 : mesh_info.num_polyhedra_blocks = 0;
363 : :
364 : 9 : int id = 0;
365 : :
366 : 9 : vector_iter = blocks.begin();
367 : 9 : end_vector_iter = blocks.end();
368 : :
369 [ + - ]: 9 : std::vector< EntityHandle > parent_meshsets;
370 : :
371 : : // Clean out the bits for the element mark
372 [ + - ]: 9 : rval = mdbImpl->tag_delete( mEntityMark );
373 [ - + ]: 9 : if( MB_SUCCESS != rval ) return rval;
374 [ + - ]: 9 : rval = mdbImpl->tag_get_handle( "WriteNCDF element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT );
375 [ - + ]: 9 : if( MB_SUCCESS != rval ) return rval;
376 : :
377 : 9 : int highest_dimension_of_element_blocks = 0;
378 : :
379 [ + - ][ + - ]: 34 : for( vector_iter = blocks.begin(); vector_iter != blocks.end(); ++vector_iter )
[ + + ]
380 : : {
381 [ + - ]: 25 : MaterialSetData block_data;
382 : :
383 : : // For the purpose of qa records, get the parents of these blocks
384 [ + - ][ + - ]: 25 : if( mdbImpl->get_parent_meshsets( *vector_iter, parent_meshsets ) != MB_SUCCESS ) return MB_FAILURE;
[ - + ]
385 : :
386 : : // Get all Entity Handles in the mesh set
387 [ + - ]: 50 : Range dummy_range;
[ + - - ]
388 [ + - ][ + - ]: 25 : rval = mdbImpl->get_entities_by_handle( *vector_iter, dummy_range, true );
389 [ - + ]: 25 : if( MB_SUCCESS != rval ) return rval;
390 : :
391 : : // Skip empty blocks
392 [ + - ][ - + ]: 25 : if( dummy_range.empty() ) continue;
393 : :
394 : : // Get the block's id
395 [ + - ][ + - ]: 25 : if( mdbImpl->tag_get_data( mMaterialSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS )
[ - + ]
396 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Couldn't get block id from a tag for an element block" ); }
[ # # ][ # # ]
[ # # ]
397 : :
398 : 25 : block_data.id = id;
399 : 25 : block_data.number_attributes = 0;
400 : :
401 : : // Wait a minute, we are doing some filtering here that doesn't make sense at this level CJS
402 : :
403 : : // Find the dimension of the last entity in this range
404 [ + - ][ + - ]: 25 : int this_dim = CN::Dimension( TYPE_FROM_HANDLE( dummy_range.back() ) );
[ + - ]
405 [ - + ][ # # ]: 25 : if( this_dim > 3 ) { MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Block " << id << " contains entity sets" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
406 [ + - ][ + - ]: 25 : block_data.elements = dummy_range.subset_by_dimension( this_dim );
407 : :
408 : : // End of -- wait a minute, we are doing some filtering here that doesn't make sense at this
409 : : // level CJS
410 : :
411 : : // Get the entity type for this block, verifying that it's the same for all elements
412 [ + - ][ + - ]: 25 : EntityType entity_type = TYPE_FROM_HANDLE( block_data.elements.front() );
413 [ + - ][ - + ]: 25 : if( !block_data.elements.all_of_type( entity_type ) )
414 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Entities in block " << id << " not of common type" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
415 : :
416 : 25 : int dimension = -1;
417 [ + + ][ + + ]: 25 : if( entity_type == MBQUAD || entity_type == MBTRI )
418 : 7 : dimension = 2; // Output shells by default
419 [ + + ]: 18 : else if( entity_type == MBEDGE )
420 : 3 : dimension = 1;
421 : : else
422 [ + - ]: 15 : dimension = CN::Dimension( entity_type );
423 : :
424 [ + + ]: 25 : if( dimension > highest_dimension_of_element_blocks ) highest_dimension_of_element_blocks = dimension;
425 : :
426 [ + - ]: 50 : std::vector< EntityHandle > tmp_conn;
[ + - - ]
427 [ + - ][ + - ]: 25 : rval = mdbImpl->get_connectivity( &( block_data.elements.front() ), 1, tmp_conn );
428 [ - + ]: 25 : if( MB_SUCCESS != rval ) return rval;
429 [ + - ]: 25 : block_data.element_type = ExoIIUtil::get_element_type_from_num_verts( tmp_conn.size(), entity_type, dimension );
430 : :
431 [ - + ]: 25 : if( block_data.element_type == EXOII_MAX_ELEM_TYPE )
432 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Element type in block " << id << " didn't get set correctly" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
433 : :
434 [ - + ]: 25 : if( block_data.element_type == EXOII_POLYGON )
435 : : {
436 : : // get all poly connectivity
437 : 0 : int numconn = 0;
438 [ # # ][ # # ]: 0 : for( Range::iterator eit = block_data.elements.begin(); eit != block_data.elements.end(); eit++ )
[ # # ][ # # ]
[ # # ]
439 : : {
440 [ # # ]: 0 : EntityHandle polg = *eit;
441 : 0 : int nnodes = 0;
442 : 0 : const EntityHandle* conn = NULL;
443 [ # # ][ # # ]: 0 : rval = mdbImpl->get_connectivity( polg, conn, nnodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
444 : 0 : numconn += nnodes;
445 : : }
446 : 0 : block_data.number_nodes_per_element = numconn;
447 : : }
448 : : else
449 : 25 : block_data.number_nodes_per_element = ExoIIUtil::VerticesPerElement[block_data.element_type];
450 : :
451 : : // Number of nodes for this block
452 [ + - ]: 25 : block_data.number_elements = block_data.elements.size();
453 : :
454 : : // Total number of elements
455 : 25 : mesh_info.num_elements += block_data.number_elements;
456 : :
457 : : // Get the nodes for the elements
458 [ + - ]: 25 : rval = mWriteIface->gather_nodes_from_elements( block_data.elements, mEntityMark, mesh_info.nodes );
459 [ - + ]: 25 : if( MB_SUCCESS != rval ) return rval;
460 : :
461 : : // if polyhedra block
462 [ - + ]: 25 : if( EXOII_POLYHEDRON == block_data.element_type )
463 : : {
464 [ # # ][ # # ]: 0 : rval = mdbImpl->get_connectivity( block_data.elements, mesh_info.polyhedronFaces );MB_CHK_ERR( rval );
[ # # ][ # # ]
465 : 0 : mesh_info.num_polyhedra_blocks++;
466 : : }
467 : :
468 [ + + ]: 25 : if( !sidesets.empty() )
469 : : {
470 : : // If there are sidesets, keep track of which elements are being written out
471 [ + - ][ + - ]: 147 : for( Range::iterator iter = block_data.elements.begin(); iter != block_data.elements.end(); ++iter )
[ + - ][ + - ]
[ + + ]
472 : : {
473 : 132 : unsigned char bit = 0x1;
474 [ + - ][ + - ]: 132 : rval = mdbImpl->tag_set_data( mEntityMark, &( *iter ), 1, &bit );
475 [ - + ]: 132 : if( MB_SUCCESS != rval ) return rval;
476 : : }
477 : : }
478 : :
479 [ + - ]: 25 : block_info.push_back( block_data );
480 : :
481 : 25 : const void* data = NULL;
482 : 25 : int size = 0;
483 [ + - ][ + - ]: 25 : if( MB_SUCCESS == mdbImpl->tag_get_by_ptr( mQaRecordTag, &( *vector_iter ), 1, &data, &size ) && NULL != data )
[ - + ][ # # ]
[ - + ]
484 : : {
485 : : // There are qa records on this block - copy over to mesh qa records
486 : 0 : const char* qa_rec = static_cast< const char* >( data );
487 : 0 : int start = 0;
488 : 0 : int count = 0;
489 [ # # ]: 0 : for( int i = 0; i < size; i++ )
490 : : {
491 [ # # ]: 0 : if( qa_rec[i] == '\0' )
492 : : {
493 [ # # ]: 0 : std::string qa_string( &qa_rec[start], i - start );
494 [ # # ]: 0 : mesh_info.qaRecords.push_back( qa_string );
495 : 0 : start = i + 1;
496 : 0 : count++;
497 : : }
498 : : }
499 : :
500 : : // Constrained to multiples of 4 qa records
501 [ # # ][ # # ]: 25 : if( count > 0 ) assert( count % 4 == 0 );
[ + - ]
502 : : }
503 : 25 : }
504 : :
505 : 9 : mesh_info.num_elementblocks = block_info.size();
506 : :
507 [ + - ][ + - ]: 34 : for( std::vector< MaterialSetData >::iterator blit = block_info.begin(); blit != block_info.end(); blit++ )
[ + + ]
508 : : {
509 [ + - ]: 25 : MaterialSetData& block = *blit;
510 [ + - ]: 25 : if( block.element_type != EXOII_POLYHEDRON )
511 [ + - ][ + - ]: 25 : { mesh_info.polyhedronFaces = subtract( mesh_info.polyhedronFaces, block.elements ); }
512 : : }
513 : :
514 : : // If user hasn't entered dimension, we figure it out
515 [ - + ]: 9 : if( mesh_info.num_dim == 0 )
516 : : {
517 : : // Never want 1 or zero dimensions
518 [ # # ]: 0 : if( highest_dimension_of_element_blocks < 2 )
519 : 0 : mesh_info.num_dim = 3;
520 : : else
521 : 0 : mesh_info.num_dim = highest_dimension_of_element_blocks;
522 : : }
523 : :
524 [ + - ][ + - ]: 9 : Range::iterator range_iter, end_range_iter;
525 [ + - ]: 9 : range_iter = mesh_info.nodes.begin();
526 [ + - ]: 9 : end_range_iter = mesh_info.nodes.end();
527 : :
528 [ + - ]: 9 : mesh_info.num_nodes = mesh_info.nodes.size();
529 : :
530 : : //------nodesets--------
531 : :
532 : 9 : vector_iter = nodesets.begin();
533 : 9 : end_vector_iter = nodesets.end();
534 : :
535 [ + - ][ + - ]: 18 : for( ; vector_iter != end_vector_iter; ++vector_iter )
[ + + ]
536 : : {
537 [ + - ]: 9 : DirichletSetData nodeset_data;
538 : 9 : nodeset_data.id = 0;
539 : 9 : nodeset_data.number_nodes = 0;
540 : :
541 : : // Get the nodeset's id
542 [ + - ][ + - ]: 9 : if( mdbImpl->tag_get_data( mDirichletSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS )
[ - + ]
543 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Couldn't get id tag for nodeset " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
544 : :
545 : 9 : nodeset_data.id = id;
546 : :
547 [ + - ][ + - ]: 18 : std::vector< EntityHandle > node_vector;
548 : : // Get the nodes of the nodeset that are in mesh_info.nodes
549 [ + - ][ + - ]: 9 : if( mdbImpl->get_entities_by_handle( *vector_iter, node_vector, true ) != MB_SUCCESS )
[ - + ]
550 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Couldn't get nodes in nodeset " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
551 : :
552 : : // Get the tag for distribution factors
553 : : const double* dist_factor_vector;
554 : : int dist_factor_size;
555 : 9 : const void* ptr = 0;
556 : :
557 : 9 : int has_dist_factors = 0;
558 [ + - ][ + - ]: 9 : if( mdbImpl->tag_get_by_ptr( mDistFactorTag, &( *vector_iter ), 1, &ptr, &dist_factor_size ) == MB_SUCCESS &&
[ - + ][ # # ]
[ - + ]
559 : : dist_factor_size )
560 : 0 : has_dist_factors = 1;
561 : 9 : dist_factor_size /= sizeof( double );
562 : 9 : dist_factor_vector = reinterpret_cast< const double* >( ptr );
563 : 9 : std::vector< EntityHandle >::iterator iter, end_iter;
564 : 9 : iter = node_vector.begin();
565 : 9 : end_iter = node_vector.end();
566 : :
567 : 9 : int j = 0;
568 : 9 : unsigned char node_marked = 0;
569 : : ErrorCode result;
570 [ + - ][ + - ]: 111 : for( ; iter != end_iter; ++iter )
[ + + ]
571 : : {
572 [ + - ][ + - ]: 102 : if( TYPE_FROM_HANDLE( *iter ) != MBVERTEX ) continue;
[ - + ]
573 [ + - ][ + - ]: 102 : result = mdbImpl->tag_get_data( mEntityMark, &( *iter ), 1, &node_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
574 : :
575 [ + - ]: 102 : if( 0x1 == node_marked )
576 : : {
577 [ + - ][ + - ]: 102 : nodeset_data.nodes.push_back( *iter );
578 [ - + ]: 102 : if( 0 != has_dist_factors )
579 [ # # ]: 0 : nodeset_data.node_dist_factors.push_back( dist_factor_vector[j] );
580 : : else
581 [ + - ]: 102 : nodeset_data.node_dist_factors.push_back( 1.0 );
582 : : }
583 : 102 : j++;
584 : : }
585 : :
586 : 9 : nodeset_data.number_nodes = nodeset_data.nodes.size();
587 [ + - ][ + - ]: 9 : nodeset_info.push_back( nodeset_data );
588 : 9 : }
589 : :
590 : : //------sidesets--------
591 : 9 : vector_iter = sidesets.begin();
592 : 9 : end_vector_iter = sidesets.end();
593 : :
594 [ + - ][ + - ]: 21 : for( ; vector_iter != end_vector_iter; ++vector_iter )
[ + + ]
595 : : {
596 [ + - ]: 12 : NeumannSetData sideset_data;
597 : :
598 : : // Get the sideset's id
599 [ + - ][ + - ]: 12 : if( mdbImpl->tag_get_data( mNeumannSetTag, &( *vector_iter ), 1, &id ) != MB_SUCCESS ) return MB_FAILURE;
[ - + ]
600 : :
601 : 12 : sideset_data.id = id;
602 [ + - ]: 12 : sideset_data.mesh_set_handle = *vector_iter;
603 : :
604 : : // Get the sides in two lists, one forward the other reverse; starts with forward sense
605 : : // by convention
606 [ + - ][ + - ]: 24 : Range forward_elems, reverse_elems;
[ + - ][ + - ]
607 [ + - ][ + - ]: 12 : if( get_sideset_elems( *vector_iter, 0, forward_elems, reverse_elems ) == MB_FAILURE ) return MB_FAILURE;
[ - + ]
608 : :
609 [ + - ][ - + ]: 12 : ErrorCode result = get_valid_sides( forward_elems, mesh_info, 1, sideset_data );MB_CHK_SET_ERR( result, "Couldn't get valid sides data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
610 [ + - ][ - + ]: 12 : result = get_valid_sides( reverse_elems, mesh_info, -1, sideset_data );MB_CHK_SET_ERR( result, "Couldn't get valid sides data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
611 : :
612 : 12 : sideset_data.number_elements = sideset_data.elements.size();
613 [ + - ][ + - ]: 12 : sideset_info.push_back( sideset_data );
614 : 12 : }
615 : :
616 : 9 : return MB_SUCCESS;
617 : : }
618 : :
619 : 24 : ErrorCode WriteNCDF::get_valid_sides( Range& elems, ExodusMeshInfo& /*mesh_info*/, const int sense,
620 : : NeumannSetData& sideset_data )
621 : : {
622 : : // This is where we see if underlying element of side set element is included in output
623 : :
624 : : // Get the sideset-based info for distribution factors
625 : 24 : const double* dist_factor_vector = 0;
626 : 24 : int dist_factor_size = 0;
627 : :
628 : : // Initialize dist_fac_iter to get rid of compiler warning
629 : 24 : const double* dist_fac_iter = 0;
630 : 24 : const void* ptr = 0;
631 : 24 : bool has_dist_factors = false;
632 [ + - ][ + - ]: 48 : if( mdbImpl->tag_get_by_ptr( mDistFactorTag, &( sideset_data.mesh_set_handle ), 1, &ptr, &dist_factor_size ) ==
633 [ + - ][ + - ]: 24 : MB_SUCCESS &&
634 : : dist_factor_size )
635 : : {
636 : 24 : has_dist_factors = true;
637 : 24 : dist_factor_vector = reinterpret_cast< const double* >( ptr );
638 : 24 : dist_fac_iter = dist_factor_vector;
639 : 24 : dist_factor_size /= sizeof( double );
640 : : }
641 : :
642 : 24 : unsigned char element_marked = 0;
643 : : ErrorCode result;
644 [ + - ][ + - ]: 192 : for( Range::iterator iter = elems.begin(); iter != elems.end(); ++iter )
[ + - ][ + - ]
[ + + ]
645 : : {
646 : : // Should insert here if "side" is a quad/tri on a quad/tri mesh
647 [ + - ][ + - ]: 168 : result = mdbImpl->tag_get_data( mEntityMark, &( *iter ), 1, &element_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
648 : :
649 [ + + ]: 168 : if( 0x1 == element_marked )
650 : : {
651 [ + - ][ + - ]: 24 : sideset_data.elements.push_back( *iter );
652 : :
653 : : // TJT TODO: the sense should really be # edges + 1or2
654 [ + + ][ + - ]: 24 : sideset_data.side_numbers.push_back( ( sense == 1 ? 1 : 2 ) );
655 : : }
656 : : else
657 : : { // Then "side" is probably a quad/tri on a hex/tet mesh
658 [ + - ]: 144 : std::vector< EntityHandle > parents;
659 [ + - ][ + - ]: 144 : int dimension = CN::Dimension( TYPE_FROM_HANDLE( *iter ) );
[ + - ]
660 : :
661 : : // Get the adjacent parent element of "side"
662 [ + - ][ + - ]: 144 : if( mdbImpl->get_adjacencies( &( *iter ), 1, dimension + 1, false, parents ) != MB_SUCCESS )
663 : : {
664 : : #if 0
665 : : // This is not treated as an error, print warning messages for
666 : : // debugging only
667 : : fprintf(stderr, "[Warning]: Couldn't get adjacencies for sideset.\n");
668 : : #endif
669 : : }
670 : :
671 [ + - ]: 144 : if( !parents.empty() )
672 : : {
673 : : // Make sure the adjacent parent element will be output
674 [ + + ][ + - ]: 294 : for( unsigned int k = 0; k < parents.size(); k++ )
675 : : {
676 [ + - ][ + - ]: 150 : result = mdbImpl->tag_get_data( mEntityMark, &( parents[k] ), 1, &element_marked );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
677 : :
678 : : int side_no, this_sense, this_offset;
679 [ + - ][ + + ]: 294 : if( 0x1 == element_marked &&
680 [ + + ][ + - ]: 294 : mdbImpl->side_number( parents[k], *iter, side_no, this_sense, this_offset ) == MB_SUCCESS &&
[ + - ][ + - ]
[ + + ]
681 : 144 : this_sense == sense )
682 : : {
683 [ + - ][ + - ]: 72 : sideset_data.elements.push_back( parents[k] );
684 [ + - ]: 72 : sideset_data.side_numbers.push_back( side_no + 1 );
685 : 72 : break;
686 : : }
687 : : }
688 : : }
689 : : else
690 : : {
691 : : #if 0
692 : : // This is not treated as an error, print warning messages for
693 : : // debugging only
694 : : fprintf(stderr, "[Warning]: No parent element exists for element in sideset %i\n", sideset_data.id);
695 : : #endif
696 : 144 : }
697 : : }
698 : :
699 [ + - ]: 168 : if( sideset_data.elements.size() != 0 )
700 : : {
701 : : // Distribution factors
702 [ + - ][ + - ]: 168 : int num_nodes = CN::VerticesPerEntity( TYPE_FROM_HANDLE( *iter ) );
[ + - ]
703 : : // put some dummy dist factors for polygons; why do we need them?
704 [ + - ][ + - ]: 168 : if( TYPE_FROM_HANDLE( *iter ) == MBPOLYGON ) num_nodes = 1; // dummy
[ - + ]
705 [ + - ]: 168 : if( has_dist_factors )
706 : : {
707 : : std::copy( dist_fac_iter, dist_fac_iter + num_nodes,
708 [ + - ][ + - ]: 168 : std::back_inserter( sideset_data.ss_dist_factors ) );
709 : 168 : dist_fac_iter += num_nodes;
710 : : }
711 : : else
712 : : {
713 [ # # ]: 168 : for( int j = 0; j < num_nodes; j++ )
714 [ # # ]: 0 : sideset_data.ss_dist_factors.push_back( 1.0 );
715 : : }
716 : : }
717 : : }
718 : :
719 : 24 : return MB_SUCCESS;
720 : : }
721 : :
722 : 9 : ErrorCode WriteNCDF::write_qa_records( std::vector< std::string >& qa_record_list )
723 : : {
724 : 9 : int i = 0;
725 : :
726 [ + - ][ + + ]: 18 : for( std::vector< std::string >::iterator string_it = qa_record_list.begin(); string_it != qa_record_list.end(); )
727 : : {
728 [ + + ]: 45 : for( int j = 0; j < 4; j++ )
729 [ + - ][ + - ]: 36 : write_qa_string( ( *string_it++ ).c_str(), i, j );
[ + - ]
730 : 9 : i++;
731 : : }
732 : :
733 : 9 : return MB_SUCCESS;
734 : : }
735 : :
736 : 36 : ErrorCode WriteNCDF::write_qa_string( const char* string, int record_number, int record_position )
737 : : {
738 : : // Get the variable id in the exodus file
739 : :
740 [ + - ]: 36 : std::vector< int > dims;
741 : 36 : int temp_var = -1;
742 [ + - ][ + - ]: 36 : GET_VAR( "qa_records", temp_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
743 [ - + ][ # # ]: 36 : if( -1 == temp_var ) { MB_SET_ERR( MB_FAILURE, "WriteNCDF:: Problem getting qa record variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
744 : : size_t count[3], start[3];
745 : :
746 : : // Write out the record
747 : 36 : start[0] = record_number;
748 : 36 : start[1] = record_position;
749 : 36 : start[2] = 0;
750 : :
751 : 36 : count[0] = 1;
752 : 36 : count[1] = 1;
753 : 36 : count[2] = (long)strlen( string ) + 1;
754 [ + - ]: 36 : int fail = nc_put_vara_text( ncFile, temp_var, start, count, string );
755 [ - + ][ # # ]: 36 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed to position qa string variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
756 : :
757 : 36 : return MB_SUCCESS;
758 : : }
759 : :
760 : 9 : ErrorCode WriteNCDF::write_nodes( int num_nodes, Range& nodes, int dimension )
761 : : {
762 : : // Write coordinates names
763 : 9 : int nc_var = -1;
764 [ + - ]: 9 : std::vector< int > dims;
765 [ + - ][ + - ]: 9 : GET_VAR( "coor_names", nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
766 [ - + ][ # # ]: 9 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Trouble getting coordinate name variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
767 : :
768 : 9 : size_t start[2] = { 0, 0 }, count[2] = { 1, ExoIIInterface::MAX_STR_LENGTH };
769 : : char dum_str[ExoIIInterface::MAX_STR_LENGTH];
770 : 9 : strcpy( dum_str, "x" );
771 [ + - ]: 9 : int fail = nc_put_vara_text( ncFile, nc_var, start, count, dum_str );
772 [ - + ]: 9 : if( NC_NOERR != fail )
773 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Trouble adding x coordinate name; netcdf message: " << nc_strerror( fail ) ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
774 : :
775 : 9 : start[0] = 1;
776 : 9 : strcpy( dum_str, "y" );
777 [ + - ]: 9 : fail = nc_put_vara_text( ncFile, nc_var, start, count, dum_str );
778 [ - + ]: 9 : if( NC_NOERR != fail )
779 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Trouble adding y coordinate name; netcdf message: " << nc_strerror( fail ) ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
780 : :
781 : 9 : start[0] = 2;
782 : 9 : strcpy( dum_str, "z" );
783 [ + - ]: 9 : fail = nc_put_vara_text( ncFile, nc_var, start, count, dum_str );
784 [ - + ]: 9 : if( NC_NOERR != fail )
785 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Trouble adding z coordinate name; netcdf message: " << nc_strerror( fail ) ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
786 : :
787 : : // See if should transform coordinates
788 : : ErrorCode result;
789 : : Tag trans_tag;
790 [ + - ]: 9 : result = mdbImpl->tag_get_handle( MESH_TRANSFORM_TAG_NAME, 16, MB_TYPE_DOUBLE, trans_tag );
791 : 9 : bool transform_needed = true;
792 [ + - ]: 9 : if( result == MB_TAG_NOT_FOUND ) transform_needed = false;
793 : :
794 [ - + ]: 9 : int num_coords_to_fill = transform_needed ? 3 : dimension;
795 : :
796 [ + - ]: 18 : std::vector< double* > coord_arrays( 3 );
797 [ + - ][ + - ]: 9 : coord_arrays[0] = new double[num_nodes];
[ + - ]
798 [ + - ][ + - ]: 9 : coord_arrays[1] = new double[num_nodes];
[ + - ]
799 [ + - ]: 9 : coord_arrays[2] = NULL;
800 : :
801 [ + - ][ + - ]: 9 : if( num_coords_to_fill == 3 ) coord_arrays[2] = new double[num_nodes];
[ + - ][ + - ]
802 : :
803 [ + - ]: 9 : result = mWriteIface->get_node_coords( dimension, num_nodes, nodes, mGlobalIdTag, 1, coord_arrays );
804 [ - + ]: 9 : if( result != MB_SUCCESS )
805 : : {
806 [ # # ][ # # ]: 0 : delete[] coord_arrays[0];
807 [ # # ][ # # ]: 0 : delete[] coord_arrays[1];
808 [ # # ][ # # ]: 0 : if( coord_arrays[2] ) delete[] coord_arrays[2];
[ # # ][ # # ]
809 : 0 : return result;
810 : : }
811 : :
812 [ - + ]: 9 : if( transform_needed )
813 : : {
814 : : double trans_matrix[16];
815 : 0 : const EntityHandle mesh = 0;
816 [ # # ][ # # ]: 0 : result = mdbImpl->tag_get_data( trans_tag, &mesh, 0, trans_matrix );MB_CHK_SET_ERR( result, "Couldn't get transform data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
817 : :
818 [ # # ]: 0 : for( int i = 0; i < num_nodes; i++ )
819 : : {
820 : : double vec1[3];
821 : : double vec2[3];
822 : :
823 [ # # ]: 0 : vec2[0] = coord_arrays[0][i];
824 [ # # ]: 0 : vec2[1] = coord_arrays[1][i];
825 [ # # ]: 0 : vec2[2] = coord_arrays[2][i];
826 : :
827 [ # # ]: 0 : for( int row = 0; row < 3; row++ )
828 : : {
829 : 0 : vec1[row] = 0.0;
830 [ # # ]: 0 : for( int col = 0; col < 3; col++ )
831 : 0 : vec1[row] += ( trans_matrix[( row * 4 ) + col] * vec2[col] );
832 : : }
833 : :
834 [ # # ]: 0 : coord_arrays[0][i] = vec1[0];
835 [ # # ]: 0 : coord_arrays[1][i] = vec1[1];
836 [ # # ]: 0 : coord_arrays[2][i] = vec1[2];
837 : : }
838 : : }
839 : :
840 : : // Write the nodes
841 : 9 : nc_var = -1;
842 [ + - ][ + - ]: 9 : GET_VAR( "coord", nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
843 [ - + ][ # # ]: 9 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Trouble getting coordinate variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
844 : 9 : start[0] = 0;
845 : 9 : count[1] = num_nodes;
846 [ + - ][ + - ]: 9 : fail = nc_put_vara_double( ncFile, nc_var, start, count, &( coord_arrays[0][0] ) );
847 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Trouble writing x coordinate" ); }
[ # # ][ # # ]
[ # # ][ # # ]
848 : :
849 : 9 : start[0] = 1;
850 [ + - ][ + - ]: 9 : fail = nc_put_vara_double( ncFile, nc_var, start, count, &( coord_arrays[1][0] ) );
851 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Trouble writing y coordinate" ); }
[ # # ][ # # ]
[ # # ][ # # ]
852 : :
853 : 9 : start[0] = 2;
854 [ + - ][ + - ]: 9 : fail = nc_put_vara_double( ncFile, nc_var, start, count, &( coord_arrays[2][0] ) );
855 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Trouble writing z coordinate" ); }
[ # # ][ # # ]
[ # # ][ # # ]
856 : :
857 [ + - ][ + - ]: 9 : delete[] coord_arrays[0];
858 [ + - ][ + - ]: 9 : delete[] coord_arrays[1];
859 [ + - ][ + - ]: 9 : if( coord_arrays[2] ) delete[] coord_arrays[2];
[ + - ][ + - ]
860 : :
861 : 18 : return MB_SUCCESS;
862 : : }
863 : :
864 : 0 : ErrorCode WriteNCDF::write_poly_faces( ExodusMeshInfo& mesh_info )
865 : : {
866 : : // write all polygons that are not in another element block;
867 : : // usually they are nowhere else, but be sure, write in this block only ones that are not in the
868 : : // other blocks
869 [ # # ]: 0 : Range pfaces = mesh_info.polyhedronFaces;
870 : :
871 : : /*
872 : : * int fbconn1(num_nod_per_fa1) ;
873 : : fbconn1:elem_type = "nsided" ;
874 : : int fbepecnt1(num_fa_in_blk1) ;
875 : : fbepecnt1:entity_type1 = "NODE" ;
876 : : fbepecnt1:entity_type2 = "FACE" ;
877 : : */
878 [ # # ][ # # ]: 0 : if( pfaces.empty() ) return MB_SUCCESS;
879 : : char wname[80];
880 : 0 : int nc_var = -1;
881 [ # # ]: 0 : std::vector< int > dims;
882 : :
883 : : // write one for each element block, to make paraview and visit happy
884 [ # # ]: 0 : int num_faces_in_block = (int)pfaces.size();
885 [ # # ]: 0 : for( unsigned int bl = 0; bl < mesh_info.num_polyhedra_blocks; bl++ )
886 : : {
887 : 0 : INS_ID( wname, "fbconn%u", bl + 1 ); // it is the first block
888 [ # # ][ # # ]: 0 : GET_VAR( wname, nc_var, dims ); // fbconn# variable, 1 dimensional
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
889 : :
890 : 0 : INS_ID( wname, "num_nod_per_fa%u", bl + 1 );
891 : : int ncdim, num_nod_per_face;
892 [ # # ][ # # ]: 0 : GET_DIM( ncdim, wname, num_nod_per_face );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
893 [ # # ][ # # ]: 0 : int* connectivity = new int[num_nod_per_face];
894 : 0 : int ixcon = 0, j = 0;
895 [ # # ]: 0 : std::vector< int > fbepe( num_faces_in_block ); // fbepecnt1
896 [ # # ][ # # ]: 0 : for( Range::iterator eit = pfaces.begin(); eit != pfaces.end(); eit++ )
[ # # ][ # # ]
[ # # ]
897 : : {
898 [ # # ]: 0 : EntityHandle polyg = *eit;
899 : 0 : int nnodes = 0;
900 : 0 : const EntityHandle* conn = NULL;
901 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_connectivity( polyg, conn, nnodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
902 [ # # ]: 0 : for( int k = 0; k < nnodes; k++ )
903 : 0 : connectivity[ixcon++] = conn[k];
904 [ # # ]: 0 : fbepe[j++] = nnodes;
905 : : }
906 : 0 : size_t start[1] = { 0 }, count[1] = { 0 };
907 : 0 : count[0] = ixcon;
908 [ # # ]: 0 : int fail = nc_put_vara_int( ncFile, nc_var, start, count, connectivity );
909 [ # # ]: 0 : if( NC_NOERR != fail )
910 : : {
911 [ # # ]: 0 : delete[] connectivity;
912 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write fbconn variable" );
[ # # ][ # # ]
[ # # ]
913 : : }
914 : :
915 : 0 : INS_ID( wname, "fbepecnt%u", bl + 1 );
916 [ # # ][ # # ]: 0 : GET_VAR( wname, nc_var, dims ); // fbconn# variable, 1 dimensional
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
917 : 0 : count[0] = num_faces_in_block;
918 : :
919 [ # # ][ # # ]: 0 : fail = nc_put_vara_int( ncFile, nc_var, start, count, &fbepe[0] );
920 [ # # ]: 0 : if( NC_NOERR != fail )
921 : : {
922 [ # # ]: 0 : delete[] connectivity;
923 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write fbepecnt variable" );
[ # # ][ # # ]
[ # # ]
924 : : }
925 : :
926 : 0 : int id = bl + 1;
927 [ # # ][ # # ]: 0 : if( write_exodus_integer_variable( "fa_prop1", &id, bl, 1 ) != MB_SUCCESS )
928 [ # # ][ # # ]: 0 : { MB_SET_ERR_CONT( "Problem writing element block id " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
929 : :
930 : 0 : int status = 1;
931 [ # # ][ # # ]: 0 : if( write_exodus_integer_variable( "fa_status", &status, bl, 1 ) != MB_SUCCESS )
932 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Problem writing face block status" ); }
[ # # ][ # # ]
[ # # ]
933 : :
934 [ # # ]: 0 : delete[] connectivity;
935 [ # # ]: 0 : if( 0 == repeat_face_blocks ) break; // do not repeat face blocks
[ # # # ]
936 : 0 : }
937 : :
938 : 0 : return MB_SUCCESS;
939 : : }
940 : 9 : ErrorCode WriteNCDF::write_header( ExodusMeshInfo& mesh_info, std::vector< MaterialSetData >& block_info,
941 : : std::vector< NeumannSetData >& sideset_info,
942 : : std::vector< DirichletSetData >& nodeset_info, const char* filename )
943 : : {
944 : : // Get the date and time
945 : : char time[TIME_STR_LEN];
946 : : char date[TIME_STR_LEN];
947 [ + - ]: 9 : time_and_date( time, date );
948 : :
949 [ + - ]: 9 : std::string title_string = "MOAB";
950 [ + - ]: 9 : title_string.append( "(" );
951 [ + - ]: 9 : title_string.append( filename );
952 [ + - ]: 9 : title_string.append( "): " );
953 [ + - ]: 9 : title_string.append( date );
954 [ + - ]: 9 : title_string.append( ": " );
955 [ + - ]: 9 : title_string.append( "time " );
956 : :
957 [ - + ]: 9 : if( title_string.length() > ExoIIInterface::MAX_LINE_LENGTH )
958 [ # # ]: 0 : title_string.resize( ExoIIInterface::MAX_LINE_LENGTH );
959 : :
960 : : // Initialize the exodus file
961 : :
962 [ + - ]: 9 : int result = initialize_exodus_file( mesh_info, block_info, sideset_info, nodeset_info, title_string.c_str() );
963 : :
964 [ - + ]: 9 : if( result == MB_FAILURE ) return MB_FAILURE;
965 : :
966 : 9 : return MB_SUCCESS;
967 : : }
968 : :
969 : 9 : ErrorCode WriteNCDF::write_elementblocks( ExodusMeshInfo& mesh_info, std::vector< MaterialSetData >& block_data )
970 : : {
971 : : unsigned int i;
972 : 9 : int block_index = 0; // Index into block list, may != 1 if there are inactive blocks
973 : 9 : int exodus_id = 1;
974 : :
975 [ + + ]: 34 : for( i = 0; i < block_data.size(); i++ )
976 : : {
977 [ + - ]: 25 : MaterialSetData& block = block_data[i];
978 : :
979 : 25 : unsigned int num_nodes_per_elem = block.number_nodes_per_element;
980 : :
981 : : // Write out the id for the block
982 : :
983 : 25 : int id = block.id;
984 : 25 : int num_values = 1;
985 : :
986 [ + - ][ - + ]: 25 : if( write_exodus_integer_variable( "eb_prop1", &id, block_index, num_values ) != MB_SUCCESS )
987 [ # # ][ # # ]: 0 : { MB_SET_ERR_CONT( "Problem writing element block id " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
988 : :
989 : : // Write out the block status
990 : :
991 : 25 : int status = 1;
992 [ - + ][ # # ]: 25 : if( 0 == block.number_elements ) { MB_SET_ERR( MB_FAILURE, "No elements in block " << id ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
993 : :
994 [ + - ][ - + ]: 25 : if( write_exodus_integer_variable( "eb_status", &status, block_index, num_values ) != MB_SUCCESS )
995 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "Problem writing element block status" ); }
[ # # ][ # # ]
[ # # ]
996 : :
997 : : //
998 : : // Map the connectivity to the new nodes
999 : 25 : const unsigned int num_elem = block.number_elements;
1000 : 25 : unsigned int num_nodes = num_nodes_per_elem * num_elem;
1001 [ + - ][ - + ]: 25 : if( EXOII_POLYGON == block.element_type || EXOII_POLYHEDRON == block.element_type )
1002 : 0 : { num_nodes = num_nodes_per_elem; }
1003 [ + - ][ + - ]: 25 : int* connectivity = new int[num_nodes];
1004 : :
1005 : 25 : ErrorCode result = MB_SUCCESS;
1006 [ + - ]: 25 : if( block.element_type != EXOII_POLYHEDRON )
1007 : : mWriteIface->get_element_connect( num_elem, num_nodes_per_elem, mGlobalIdTag, block.elements, mGlobalIdTag,
1008 [ + - ]: 25 : exodus_id, connectivity );
1009 [ - + ]: 25 : if( result != MB_SUCCESS )
1010 : : {
1011 [ # # ]: 0 : delete[] connectivity;
1012 [ # # ][ # # ]: 0 : MB_SET_ERR( result, "Couldn't get element array to write from" );
[ # # ][ # # ]
[ # # ]
1013 : : }
1014 : :
1015 : : // If necessary, convert from EXODUS to CN node order
1016 : 25 : const EntityType elem_type = ExoIIUtil::ExoIIElementMBEntity[block.element_type];
1017 [ + - ][ - + ]: 25 : assert( block.elements.all_of_type( elem_type ) );
1018 : 25 : const int* reorder = 0;
1019 [ + - ][ + - ]: 25 : if( block.element_type != EXOII_POLYHEDRON && block.element_type != EXOII_POLYGON )
1020 : 25 : reorder = exodus_elem_order_map[elem_type][block.number_nodes_per_element];
1021 [ + + ]: 25 : if( reorder )
1022 [ + - ]: 4 : WriteUtilIface::reorder( reorder, connectivity, block.number_elements, block.number_nodes_per_element );
1023 : :
1024 : : char wname[80];
1025 : 25 : int nc_var = -1;
1026 [ + - ]: 25 : std::vector< int > dims;
1027 [ + - ]: 25 : if( block.element_type != EXOII_POLYHEDRON )
1028 : : {
1029 : 25 : exodus_id += num_elem;
1030 : 25 : INS_ID( wname, "connect%u", i + 1 );
1031 : :
1032 [ + - ][ + - ]: 25 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1033 [ - + ]: 25 : if( -1 == nc_var )
1034 : : {
1035 [ # # ]: 0 : delete[] connectivity;
1036 [ # # ][ # # ]: 25 : MB_SET_ERR( MB_FAILURE, "Couldn't get connectivity variable" );
[ # # ][ # # ]
[ # # ]
1037 : : }
1038 : : }
1039 : :
1040 [ - + ]: 25 : if( EXOII_POLYGON == block.element_type )
1041 : : {
1042 : 0 : size_t start[1] = { 0 }, count[1] = { num_nodes_per_elem };
1043 [ # # ]: 0 : int fail = nc_put_vara_int( ncFile, nc_var, start, count, connectivity );
1044 [ # # ]: 0 : if( NC_NOERR != fail )
1045 : : {
1046 [ # # ]: 0 : delete[] connectivity;
1047 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write connectivity variable" );
[ # # ][ # # ]
[ # # ]
1048 : : }
1049 : : // now put also number ebepecnt1
1050 : 0 : INS_ID( wname, "ebepecnt%u", i + 1 );
1051 [ # # ][ # # ]: 0 : GET_VAR( wname, nc_var, dims );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1052 : 0 : count[0] = block.number_elements;
1053 : 0 : start[0] = 0;
1054 : : // reuse connectivity array, to not allocate another one
1055 : 0 : int j = 0;
1056 [ # # ][ # # ]: 0 : for( Range::iterator eit = block.elements.begin(); eit != block.elements.end(); j++, eit++ )
[ # # ][ # # ]
[ # # ]
1057 : : {
1058 [ # # ]: 0 : EntityHandle polg = *eit;
1059 : 0 : int nnodes = 0;
1060 : 0 : const EntityHandle* conn = NULL;
1061 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_connectivity( polg, conn, nnodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
1062 : 0 : connectivity[j] = nnodes;
1063 : : }
1064 [ # # ]: 0 : fail = nc_put_vara_int( ncFile, nc_var, start, count, connectivity );
1065 [ # # ]: 0 : if( NC_NOERR != fail )
1066 : : {
1067 [ # # ]: 0 : delete[] connectivity;
1068 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write ebepecnt variable" );
[ # # ][ # # ]
[ # # ]
1069 : : }
1070 : : }
1071 [ + - ]: 25 : else if( block.element_type != EXOII_POLYHEDRON )
1072 : : {
1073 : 25 : size_t start[2] = { 0, 0 }, count[2] = { num_elem, num_nodes_per_elem };
1074 [ + - ]: 25 : int fail = nc_put_vara_int( ncFile, nc_var, start, count, connectivity );
1075 [ - + ]: 25 : if( NC_NOERR != fail )
1076 : : {
1077 [ # # ]: 0 : delete[] connectivity;
1078 [ # # ][ # # ]: 25 : MB_SET_ERR( MB_FAILURE, "Couldn't write connectivity variable" );
[ # # ][ # # ]
[ # # ]
1079 : : }
1080 : : }
1081 : : else // if (block.element_type == EXOII_POLYHEDRON)
1082 : : {
1083 : : /* write a lot of stuff // faconn
1084 : : num_fa_in_blk1 = 15 ;
1085 : : num_nod_per_fa1 = 58 ;
1086 : : num_el_in_blk1 = 3 ;
1087 : : num_fac_per_el1 = 17 ;
1088 : : int fbconn1(num_nod_per_fa1) ;
1089 : : fbconn1:elem_type = "nsided" ;
1090 : : int fbepecnt1(num_fa_in_blk1) ;
1091 : : fbepecnt1:entity_type1 = "NODE" ;
1092 : : fbepecnt1:entity_type2 = "FACE" ;
1093 : : int facconn1(num_fac_per_el1) ;
1094 : : facconn1:elem_type = "NFACED" ;
1095 : : int ebepecnt1(num_el_in_blk1) ;
1096 : : ebepecnt1:entity_type1 = "FACE" ;
1097 : : ebepecnt1:entity_type2 = "ELEM" ;
1098 : :
1099 : : */
1100 : 0 : Range& block_faces = mesh_info.polyhedronFaces;
1101 : : // ErrorCode rval = mdbImpl->get_connectivity(block.elements, block_faces);
1102 : : // MB_CHK_ERR(rval);
1103 : :
1104 : : // reuse now connectivity for facconn1
1105 : 0 : INS_ID( wname, "facconn%u", i + 1 );
1106 [ # # ][ # # ]: 0 : GET_VAR( wname, nc_var, dims ); // fbconn# variable, 1 dimensional
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1107 : :
1108 [ # # ][ # # ]: 0 : std::vector< int > ebepe( block.elements.size() ); // ebepecnt1
1109 : 0 : int ixcon = 0, j = 0;
1110 : 0 : size_t start[1] = { 0 }, count[1] = { 0 };
1111 : :
1112 [ # # ][ # # ]: 0 : for( Range::iterator eit = block.elements.begin(); eit != block.elements.end(); eit++ )
[ # # ][ # # ]
[ # # ]
1113 : : {
1114 [ # # ]: 0 : EntityHandle polyh = *eit;
1115 : 0 : int nfaces = 0;
1116 : 0 : const EntityHandle* conn = NULL;
1117 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_connectivity( polyh, conn, nfaces );MB_CHK_ERR( rval );
[ # # ][ # # ]
1118 [ # # ]: 0 : for( int k = 0; k < nfaces; k++ )
1119 : : {
1120 [ # # ]: 0 : int index = block_faces.index( conn[k] );
1121 [ # # ][ # # ]: 0 : if( index == -1 ) MB_SET_ERR( MB_FAILURE, "Couldn't find face in polyhedron" );
[ # # ][ # # ]
[ # # ][ # # ]
1122 : 0 : connectivity[ixcon++] = index + 1;
1123 : : }
1124 [ # # ]: 0 : ebepe[j++] = nfaces;
1125 : : // num_faces+=nfaces;
1126 : : }
1127 : 0 : count[0] = ixcon; // facconn1
1128 [ # # ]: 0 : int fail = nc_put_vara_int( ncFile, nc_var, start, count, connectivity );
1129 [ # # ]: 0 : if( NC_NOERR != fail )
1130 : : {
1131 [ # # ]: 0 : delete[] connectivity;
1132 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write fbconn variable" );
[ # # ][ # # ]
[ # # ]
1133 : : }
1134 : :
1135 : 0 : INS_ID( wname, "ebepecnt%u", i + 1 );
1136 [ # # ][ # # ]: 0 : GET_VAR( wname, nc_var, dims ); // ebepecnt# variable, 1 dimensional
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1137 [ # # ]: 0 : count[0] = block.elements.size();
1138 : :
1139 [ # # ][ # # ]: 0 : fail = nc_put_vara_int( ncFile, nc_var, start, count, &ebepe[0] );
1140 [ # # ]: 0 : if( NC_NOERR != fail )
1141 : : {
1142 [ # # ]: 0 : delete[] connectivity;
1143 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't write fbepecnt variable" );
[ # # ][ # # ]
[ # # ][ # # ]
1144 : 0 : }
1145 : : }
1146 : 25 : block_index++;
1147 [ + - ][ + - ]: 25 : delete[] connectivity;
1148 : 25 : }
1149 : :
1150 : 9 : return MB_SUCCESS;
1151 : : }
1152 : :
1153 : 9 : ErrorCode WriteNCDF::write_global_node_order_map( int num_nodes, Range& nodes )
1154 : : {
1155 : : // Note: this routine bypasses the standard exodusII interface for efficiency!
1156 : :
1157 : : // Node order map
1158 [ + - ][ + - ]: 9 : int* map = new int[num_nodes];
1159 : :
1160 : : // For now, output a dummy map!
1161 : :
1162 [ + - ][ + - ]: 9 : Range::iterator range_iter, end_iter;
1163 [ + - ]: 9 : range_iter = nodes.begin();
1164 [ + - ]: 9 : end_iter = nodes.end();
1165 : :
1166 : 9 : int i = 0;
1167 : :
1168 [ + - ][ + - ]: 2345551 : for( ; range_iter != end_iter; ++range_iter )
[ + + ]
1169 : : {
1170 : : // TODO -- do we really want to cast this to an int?
1171 [ + - ][ + - ]: 2345542 : map[i++] = (int)ID_FROM_HANDLE( *range_iter );
1172 : : }
1173 : :
1174 : : // Output array and cleanup
1175 : :
1176 [ + - ]: 9 : int error = write_exodus_integer_variable( "node_num_map", map, 0, num_nodes );
1177 : :
1178 [ + - ][ + - ]: 9 : if( map ) delete[] map;
1179 : :
1180 [ - + ][ # # ]: 9 : if( error < 0 ) { MB_SET_ERR( MB_FAILURE, "Failed writing global node order map" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1181 : :
1182 : 9 : return MB_SUCCESS;
1183 : : }
1184 : :
1185 : 9 : ErrorCode WriteNCDF::write_global_element_order_map( int num_elements )
1186 : : {
1187 : : // Allocate map array
1188 [ + - ]: 9 : int* map = new int[num_elements];
1189 : :
1190 : : // Many Sandia codes assume this map is unique, and CUBIT does not currently
1191 : : // have unique ids for all elements. Therefore, to make sure nothing crashes,
1192 : : // insert a dummy map...
1193 : :
1194 [ + + ]: 512249 : for( int i = 0; i < num_elements; i++ )
1195 : 512240 : map[i] = i + 1;
1196 : :
1197 : : // Output array and cleanup
1198 : :
1199 : 9 : int error = write_exodus_integer_variable( "elem_num_map", map, 0, num_elements );
1200 : :
1201 [ + - ][ + - ]: 9 : if( map ) delete[] map;
1202 : :
1203 [ - + ][ # # ]: 9 : if( error < 0 ) { MB_SET_ERR( MB_FAILURE, "Failed writing global element order map" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1204 : :
1205 : 9 : return MB_SUCCESS;
1206 : : }
1207 : :
1208 : 9 : ErrorCode WriteNCDF::write_element_order_map( int num_elements )
1209 : : {
1210 : : // Note: this routine bypasses the standard exodusII interface for efficiency!
1211 : :
1212 : : // Element order map
1213 [ + - ]: 9 : int* map = new int[num_elements];
1214 : :
1215 : : // For now, output a dummy map!
1216 : :
1217 [ + + ]: 512249 : for( int i = 0; i < num_elements; i++ )
1218 : : {
1219 : 512240 : map[i] = i + 1;
1220 : : }
1221 : :
1222 : : // Output array and cleanup
1223 : :
1224 : 9 : int error = write_exodus_integer_variable( "elem_map", map, 0, num_elements );
1225 : :
1226 [ + - ][ + - ]: 9 : if( map ) delete[] map;
1227 : :
1228 [ - + ][ # # ]: 9 : if( error < 0 ) { MB_SET_ERR( MB_FAILURE, "Failed writing element map" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1229 : :
1230 : 9 : return MB_SUCCESS;
1231 : : }
1232 : :
1233 : 119 : ErrorCode WriteNCDF::write_exodus_integer_variable( const char* variable_name, int* variable_array, int start_position,
1234 : : int number_values )
1235 : : {
1236 : : // Note: this routine bypasses the standard exodusII interface for efficiency!
1237 : :
1238 : : // Write directly to netcdf interface for efficiency
1239 : :
1240 : : // Get the variable id of the element map
1241 : 119 : int nc_var = -1;
1242 [ + - ]: 119 : std::vector< int > dims;
1243 [ + - ][ + - ]: 119 : GET_VAR( variable_name, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1244 [ - + ]: 119 : if( -1 == nc_var )
1245 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to locate variable " << variable_name << " in file" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1246 : : // This contortion is necessary because netCDF is expecting nclongs;
1247 : : // fortunately it's necessary only when ints and nclongs aren't the same size
1248 : :
1249 : : size_t start[1], count[1];
1250 : 119 : start[0] = start_position;
1251 : 119 : count[0] = number_values;
1252 : :
1253 : 119 : int fail = NC_NOERR;
1254 : : if( sizeof( int ) == sizeof( long ) ) { fail = nc_put_vara_int( ncFile, nc_var, start, count, variable_array ); }
1255 : : else
1256 : : {
1257 [ + - ][ + - ]: 119 : long* lptr = new long[number_values];
1258 [ + + ]: 3370233 : for( int jj = 0; jj < number_values; jj++ )
1259 : 3370114 : lptr[jj] = variable_array[jj];
1260 [ + - ]: 119 : fail = nc_put_vara_long( ncFile, nc_var, start, count, lptr );
1261 [ + - ]: 119 : delete[] lptr;
1262 : : }
1263 : :
1264 [ - + ][ # # ]: 119 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed to store variable " << variable_name ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1265 : :
1266 : 119 : return MB_SUCCESS;
1267 : : }
1268 : :
1269 : 9 : ErrorCode WriteNCDF::write_BCs( std::vector< NeumannSetData >& sidesets, std::vector< DirichletSetData >& nodesets )
1270 : : {
1271 : : unsigned int i, j;
1272 : : int id;
1273 : 9 : int ns_index = -1;
1274 : :
1275 [ + - ][ + - ]: 18 : for( std::vector< DirichletSetData >::iterator ns_it = nodesets.begin(); ns_it != nodesets.end(); ++ns_it )
[ + + ]
1276 : : {
1277 : : // Get number of nodes in set
1278 [ + - ]: 9 : int number_nodes = ( *ns_it ).number_nodes;
1279 [ - + ]: 9 : if( 0 == number_nodes ) continue;
1280 : :
1281 : : // If we're here, we have a non-empty nodeset; increment the index
1282 : 9 : ns_index++;
1283 : :
1284 : : // Get the node set id
1285 [ + - ]: 9 : id = ( *ns_it ).id;
1286 : :
1287 : : // Build new array to old exodus ids
1288 [ + - ][ + - ]: 9 : int* exodus_id_array = new int[number_nodes];
1289 [ + - ][ + - ]: 9 : double* dist_factor_array = new double[number_nodes];
1290 : :
1291 : 9 : std::vector< EntityHandle >::iterator begin_iter, end_iter;
1292 : 9 : std::vector< double >::iterator other_iter;
1293 [ + - ]: 9 : begin_iter = ( *ns_it ).nodes.begin();
1294 [ + - ]: 9 : end_iter = ( *ns_it ).nodes.end();
1295 [ + - ]: 9 : other_iter = ( *ns_it ).node_dist_factors.begin();
1296 : :
1297 : 9 : j = 0;
1298 : : int exodus_id;
1299 : : ErrorCode result;
1300 : : // Fill up node array and dist. factor array at the same time
1301 [ + - ][ + - ]: 111 : for( ; begin_iter != end_iter; ++begin_iter )
[ + + ]
1302 : : {
1303 [ + - ][ + - ]: 102 : result = mdbImpl->tag_get_data( mGlobalIdTag, &( *begin_iter ), 1, &exodus_id );MB_CHK_SET_ERR( result, "Problem getting id tag data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1304 : :
1305 : 102 : exodus_id_array[j] = exodus_id;
1306 [ + - ]: 102 : dist_factor_array[j] = *( other_iter );
1307 [ + - ]: 102 : ++other_iter;
1308 : 102 : j++;
1309 : : }
1310 : :
1311 : : // Write out the id for the nodeset
1312 : :
1313 : 9 : int num_values = 1;
1314 : :
1315 [ + - ][ - + ]: 9 : result = write_exodus_integer_variable( "ns_prop1", &id, ns_index, num_values );MB_CHK_SET_ERR_RET_VAL( result, "Problem writing node set id " << id, MB_FAILURE );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1316 : :
1317 : : // Write out the nodeset status
1318 : :
1319 : 9 : int status = 1;
1320 [ - + ]: 9 : if( !number_nodes ) status = 0;
1321 : :
1322 [ + - ][ - + ]: 9 : result = write_exodus_integer_variable( "ns_status", &status, ns_index, num_values );MB_CHK_SET_ERR_RET_VAL( result, "Problem writing node set status", MB_FAILURE );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1323 : :
1324 : : // Write it out
1325 : : char wname[80];
1326 : 9 : int nc_var = -1;
1327 [ + - ]: 9 : std::vector< int > dims;
1328 : 9 : INS_ID( wname, "node_ns%d", ns_index + 1 );
1329 [ + - ][ + - ]: 9 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1330 [ - + ][ # # ]: 9 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Failed to get node_ns variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1331 : :
1332 : 9 : size_t start = 0, count = number_nodes;
1333 [ + - ]: 9 : int fail = nc_put_vara_int( ncFile, nc_var, &start, &count, exodus_id_array );
1334 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing exodus id array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1335 : :
1336 : : // Write out nodeset distribution factors
1337 : 9 : INS_ID( wname, "dist_fact_ns%d", ns_index + 1 );
1338 : 9 : nc_var = -1;
1339 [ + - ][ + - ]: 9 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1340 [ - + ][ # # ]: 9 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Failed to get dist_fact variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1341 [ + - ]: 9 : fail = nc_put_vara_double( ncFile, nc_var, &start, &count, dist_factor_array );
1342 [ - + ][ # # ]: 9 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing dist factor array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1343 : :
1344 [ + - ]: 9 : delete[] dist_factor_array;
1345 [ + - ][ + - ]: 9 : delete[] exodus_id_array;
1346 : 9 : }
1347 : :
1348 : : // Now do sidesets
1349 : 9 : int ss_index = 0; // Index of sideset - not the same as 'i' because
1350 : : // only writing non-empty side sets
1351 [ + + ]: 21 : for( i = 0; i < sidesets.size(); i++ )
1352 : : {
1353 [ + - ][ + - ]: 12 : NeumannSetData sideset_data = sidesets[i];
1354 : :
1355 : : // Get the side set id
1356 : 12 : int side_set_id = sideset_data.id;
1357 : :
1358 : : // Get number of elements in set
1359 : 12 : int number_elements = sideset_data.number_elements;
1360 [ - + ]: 12 : if( 0 == number_elements ) continue;
1361 : :
1362 : : // Build new array to old exodus ids
1363 [ + - ][ + - ]: 12 : int* output_element_ids = new int[number_elements];
1364 [ + - ][ + - ]: 12 : int* output_element_side_numbers = new int[number_elements];
1365 : :
1366 : 12 : std::vector< EntityHandle >::iterator begin_iter, end_iter;
1367 : 12 : begin_iter = sideset_data.elements.begin();
1368 : 12 : end_iter = sideset_data.elements.end();
1369 : 12 : std::vector< int >::iterator side_iter = sideset_data.side_numbers.begin();
1370 : :
1371 : : // Get the tag handle
1372 : 12 : j = 0;
1373 : : int exodus_id;
1374 : :
1375 : : // For each "side"
1376 [ + - ][ + - ]: 108 : for( ; begin_iter != end_iter; ++begin_iter, ++side_iter )
[ + - ][ + + ]
1377 : : {
1378 [ + - ][ + - ]: 96 : ErrorCode result = mdbImpl->tag_get_data( mGlobalIdTag, &( *begin_iter ), 1, &exodus_id );MB_CHK_SET_ERR( result, "Problem getting exodus id for sideset element "
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1379 : : << (long unsigned int)ID_FROM_HANDLE( *begin_iter ) );
1380 : :
1381 : 96 : output_element_ids[j] = exodus_id;
1382 [ + - ]: 96 : output_element_side_numbers[j++] = *side_iter;
1383 : : }
1384 : :
1385 [ + - ]: 12 : if( 0 != number_elements )
1386 : : {
1387 : : // Write out the id for the nodeset
1388 : :
1389 : 12 : int num_values = 1;
1390 : :
1391 : : // ss_prop1[ss_index] = side_set_id
1392 [ + - ][ - + ]: 12 : ErrorCode result = write_exodus_integer_variable( "ss_prop1", &side_set_id, ss_index, num_values );MB_CHK_SET_ERR_RET_VAL( result, "Problem writing node set id " << id, MB_FAILURE );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1393 : :
1394 : : // FIXME : Something seems wrong here. The we are within a block
1395 : : // started with if (0 != number_elements), so this condition is always
1396 : : // false. This code seems to indicate that we want to write all
1397 : : // sidesets, not just empty ones. But the code both here and in
1398 : : // initialize_exodus_file() skip empty side sets.
1399 : : // - j.k. 2007-03-09
1400 : 12 : int status = 1;
1401 [ - + ]: 12 : if( 0 == number_elements ) status = 0;
1402 : :
1403 : : // ss_status[ss_index] = status
1404 [ + - ][ - + ]: 12 : result = write_exodus_integer_variable( "ss_status", &status, ss_index, num_values );MB_CHK_SET_ERR_RET_VAL( result, "Problem writing side set status", MB_FAILURE );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1405 : :
1406 : : // Increment ss_index now because we want a) we need to
1407 : : // increment it somewhere within the if (0 != number_elements)
1408 : : // block and b) the above calls need a zero-based index
1409 : : // while the following use a one-based index.
1410 : 12 : ++ss_index;
1411 : :
1412 : : char wname[80];
1413 : : int nc_var;
1414 [ + - ]: 12 : std::vector< int > dims;
1415 : 12 : INS_ID( wname, "elem_ss%d", ss_index );
1416 [ + - ][ + - ]: 12 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1417 [ - + ][ # # ]: 12 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Failed to get elem_ss variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1418 : 12 : size_t start = 0, count = number_elements;
1419 [ + - ]: 12 : int fail = nc_put_vara_int( ncFile, nc_var, &start, &count, output_element_ids );
1420 [ - + ][ # # ]: 12 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing sideset element array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1421 : :
1422 : 12 : INS_ID( wname, "side_ss%d", ss_index );
1423 : 12 : nc_var = -1;
1424 [ + - ][ + - ]: 12 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1425 [ - + ][ # # ]: 12 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Failed to get side_ss variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1426 [ + - ]: 12 : fail = nc_put_vara_int( ncFile, nc_var, &start, &count, output_element_side_numbers );
1427 [ - + ][ # # ]: 12 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing sideset side array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1428 : :
1429 : 12 : INS_ID( wname, "dist_fact_ss%d", ss_index );
1430 : 12 : nc_var = -1;
1431 [ + - ][ + - ]: 12 : GET_VAR( wname, nc_var, dims );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1432 [ - + ][ # # ]: 12 : if( -1 == nc_var ) { MB_SET_ERR( MB_FAILURE, "Failed to get sideset dist factors variable" ); }
[ # # ][ # # ]
[ # # ][ # # ]
1433 : 12 : count = sideset_data.ss_dist_factors.size();
1434 [ + - ][ + - ]: 12 : fail = nc_put_vara_double( ncFile, nc_var, &start, &count, &( sideset_data.ss_dist_factors[0] ) );
1435 [ - + ][ # # ]: 12 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Failed writing sideset dist factors array" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1436 : : }
1437 : :
1438 [ + - ]: 12 : delete[] output_element_ids;
1439 [ + - ]: 12 : delete[] output_element_side_numbers;
[ + - - ]
1440 : 12 : }
1441 : :
1442 : 9 : return MB_SUCCESS;
1443 : : }
1444 : :
1445 : 9 : ErrorCode WriteNCDF::initialize_exodus_file( ExodusMeshInfo& mesh_info, std::vector< MaterialSetData >& block_data,
1446 : : std::vector< NeumannSetData >& sideset_data,
1447 : : std::vector< DirichletSetData >& nodeset_data, const char* title_string,
1448 : : bool write_maps, bool /* write_sideset_distribution_factors */ )
1449 : : {
1450 : : // This routine takes the place of the exodusii routine ex_put_init,
1451 : : // and additionally pre-defines variables such as qa, element blocks,
1452 : : // sidesets and nodesets in a single pass.
1453 : : //
1454 : : // This is necessary because of the way exodusII works. Each time the
1455 : : // netcdf routine endef is called to take the file out of define mode,
1456 : : // the entire file is copied before the new information is added.
1457 : : //
1458 : : // With very large files, this is simply not workable. This routine takes
1459 : : // the definition portions of all applicable exodus routines and puts them
1460 : : // in a single definition, preventing repeated copying of the file.
1461 : : //
1462 : : // Most of the code is copied directly from the applicable exodus routine,
1463 : : // and thus this routine may not seem very consistent in usage or variable
1464 : : // naming, etc.
1465 : :
1466 : : // Perform the initializations
1467 : :
1468 : : int element_block_index;
1469 : :
1470 : : // Inquire on defined string dimension and general dimension for qa
1471 : :
1472 : : int dim_str, dim_four, dim_line, dim_time;
1473 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "len_string", ExoIIInterface::MAX_STR_LENGTH, &dim_str ) != NC_NOERR )
1474 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to get string length in file" ); }
[ # # ][ # # ]
[ # # ]
1475 : :
1476 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "len_line", ExoIIInterface::MAX_STR_LENGTH, &dim_line ) != NC_NOERR )
1477 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to get line length in file" ); }
[ # # ][ # # ]
[ # # ]
1478 : :
1479 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "four", 4, &dim_four ) != NC_NOERR )
1480 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to locate four in file" ); }
[ # # ][ # # ]
[ # # ]
1481 : :
1482 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "time_step", 1, &dim_time ) != NC_NOERR )
1483 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to locate time step in file" ); }
[ # # ][ # # ]
[ # # ]
1484 : : // some whole_time dummy :(
1485 : : int dtime;
1486 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "time_whole", NC_DOUBLE, 1, &dim_time, &dtime ) )
1487 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define time whole array" ); }
[ # # ][ # # ]
[ # # ]
1488 : :
1489 : : /* Put file into define mode */
1490 : :
1491 : : // It is possible that an NT filename using backslashes is in the title string
1492 : : // this can give fits to unix codes where the backslash is assumed to be an escape
1493 : : // sequence. For the exodus file, just flip the backslash to a slash to prevent
1494 : : // this problem
1495 : :
1496 : : // Get a working copy of the title_string;
1497 : :
1498 : : char working_title[80];
1499 : 9 : strncpy( working_title, title_string, 79 );
1500 : :
1501 : 9 : int length = strlen( working_title );
1502 [ + + ]: 422 : for( int pos = 0; pos < length; pos++ )
1503 : : {
1504 [ - + ]: 413 : if( working_title[pos] == '\\' ) strncpy( &working_title[pos], "/", 1 );
1505 : : }
1506 : :
1507 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_put_att_text( ncFile, NC_GLOBAL, "title", length, working_title ) )
1508 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define title attribute" ); }
[ # # ][ # # ]
[ # # ]
1509 : :
1510 : : // Add other attributes while we're at it
1511 : 9 : float dum_vers = 6.28F;
1512 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_put_att_float( ncFile, NC_GLOBAL, "api_version", NC_FLOAT, 1, &dum_vers ) )
1513 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define api_version attribute" ); }
[ # # ][ # # ]
[ # # ]
1514 : 9 : dum_vers = 6.28F;
1515 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_put_att_float( ncFile, NC_GLOBAL, "version", NC_FLOAT, 1, &dum_vers ) )
1516 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define version attribute" ); }
[ # # ][ # # ]
[ # # ]
1517 : 9 : int dum_siz = sizeof( double );
1518 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_put_att_int( ncFile, NC_GLOBAL, "floating_point_word_size", NC_INT, 1, &dum_siz ) )
1519 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define floating pt word size attribute" ); }
[ # # ][ # # ]
[ # # ]
1520 : :
1521 : : // Set up number of dimensions
1522 : :
1523 : : int num_el_blk, num_elem, num_nodes, num_dim, num_fa_blk, num_faces;
1524 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "num_dim", (size_t)mesh_info.num_dim, &num_dim ) != NC_NOERR )
1525 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of dimensions" ); }
[ # # ][ # # ]
[ # # ]
1526 : :
1527 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "num_nodes", mesh_info.num_nodes, &num_nodes ) != NC_NOERR )
1528 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes" ); }
[ # # ][ # # ]
[ # # ]
1529 : :
1530 : : int num_nod_per_fa; // it is needed for polyhedron only; need to compute it (connectivity of
1531 : : // faces of polyhedra)
1532 [ + - ][ - + ]: 9 : if( mesh_info.polyhedronFaces.size() > 0 )
1533 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, "num_faces", (int)mesh_info.polyhedronFaces.size(), &num_faces ) != NC_NOERR )
[ # # ]
1534 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes" ); }
[ # # ][ # # ]
[ # # ]
1535 : :
1536 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "num_elem", mesh_info.num_elements, &num_elem ) != NC_NOERR )
1537 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of elements" ); }
[ # # ][ # # ]
[ # # ]
1538 : :
1539 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "num_el_blk", mesh_info.num_elementblocks, &num_el_blk ) != NC_NOERR )
1540 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of element blocks" ); }
[ # # ][ # # ]
[ # # ]
1541 : :
1542 : : /* ...and some variables */
1543 : :
1544 : : /* Element block id status array */
1545 : 9 : int idstat = -1;
1546 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "eb_status", NC_LONG, 1, &num_el_blk, &idstat ) )
1547 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define element block status array" ); }
[ # # ][ # # ]
[ # # ]
1548 : :
1549 : : /* Element block id array */
1550 : :
1551 : 9 : int idarr = -1;
1552 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "eb_prop1", NC_LONG, 1, &num_el_blk, &idarr ) )
1553 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define element block id array" ); }
[ # # ][ # # ]
[ # # ]
1554 : :
1555 : : /* store property name as attribute of property array variable */
1556 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_put_att_text( ncFile, idarr, "name", strlen( "ID" ), "ID" ) )
1557 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store element block property name ID" ); }
[ # # ][ # # ]
[ # # ]
1558 : :
1559 : : // count how many are polyhedron blocks
1560 : 9 : int num_fa_blocks = 0, num_polyh_blocks = 0;
1561 [ + + ]: 34 : for( unsigned int i = 0; i < block_data.size(); i++ )
1562 : : {
1563 [ + - ]: 25 : MaterialSetData& block = block_data[i];
1564 [ - + ]: 25 : if( EXOII_POLYHEDRON == block.element_type )
1565 : : {
1566 : 0 : num_fa_blocks++;
1567 : 0 : num_polyh_blocks++;
1568 : : }
1569 : : }
1570 [ + - ][ - + ]: 9 : if( 0 == this->repeat_face_blocks && num_fa_blocks > 1 ) num_fa_blocks = 1;
1571 : : char wname[80];
1572 : :
1573 [ - + ]: 9 : if( num_fa_blocks > 0 )
1574 : : {
1575 : : /* face block id status array */
1576 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, "num_fa_blk", num_fa_blocks, &num_fa_blk ) != NC_NOERR )
1577 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of face blocks" ); }
[ # # ][ # # ]
[ # # ]
1578 : :
1579 : 0 : int idstatf = -1;
1580 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, "fa_status", NC_LONG, 1, &num_fa_blk, &idstatf ) )
1581 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define face block status array" ); }
[ # # ][ # # ]
[ # # ]
1582 : :
1583 : : /* Element block id array */
1584 : :
1585 : 0 : int idarrf = -1;
1586 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, "fa_prop1", NC_LONG, 1, &num_fa_blk, &idarrf ) )
1587 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define face block id array" ); }
[ # # ][ # # ]
[ # # ]
1588 : :
1589 : : /* store property name as attribute of property array variable */
1590 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, idarrf, "name", strlen( "ID" ), "ID" ) )
1591 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store face block property name ID" ); }
[ # # ][ # # ]
[ # # ]
1592 : : // determine the number of num_nod_per_face
1593 : : /*
1594 : : num_fa_in_blk1 = 15 ;
1595 : : num_nod_per_fa1 = 58 ;
1596 : :
1597 : : int fbconn1(num_nod_per_fa1) ;
1598 : : fbconn1:elem_type = "nsided" ;
1599 : : int fbepecnt1(num_fa_in_blk1) ;
1600 : : fbepecnt1:entity_type1 = "NODE" ;
1601 : : fbepecnt1:entity_type2 = "FACE" ;
1602 : : */
1603 : :
1604 : 0 : int num_nodes_per_face = 0;
1605 : :
1606 : : int dims[1]; // maybe 1 is enough here
1607 [ # # ][ # # ]: 0 : for( Range::iterator eit = mesh_info.polyhedronFaces.begin(); eit != mesh_info.polyhedronFaces.end(); eit++ )
[ # # ][ # # ]
[ # # ]
1608 : : {
1609 [ # # ]: 0 : EntityHandle polyg = *eit;
1610 : 0 : int nnodes = 0;
1611 : 0 : const EntityHandle* conn = NULL;
1612 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_connectivity( polyg, conn, nnodes );MB_CHK_ERR( rval );
[ # # ][ # # ]
1613 : 0 : num_nodes_per_face += nnodes;
1614 : : }
1615 : :
1616 : : // duplicate if needed; default is not duplicate
1617 [ # # ]: 0 : for( int j = 1; j <= num_fa_blocks; j++ )
1618 : : {
1619 : 0 : INS_ID( wname, "num_nod_per_fa%d", j );
1620 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, wname, (size_t)num_nodes_per_face, &num_nod_per_fa ) != NC_NOERR )
1621 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes for face block " ); }
[ # # ][ # # ]
[ # # ]
1622 : 0 : dims[0] = num_nod_per_fa;
1623 : 0 : INS_ID( wname, "fbconn%d", j ); // first one, or more
1624 : : int fbconn;
1625 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &fbconn ) )
1626 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create connectivity array for face block " << 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1627 [ # # ]: 0 : std::string element_type_string( "nsided" );
1628 [ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, fbconn, "elem_type", element_type_string.length(),
1629 [ # # ]: 0 : element_type_string.c_str() ) )
1630 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store element type nsided " ); }
[ # # ][ # # ]
[ # # ]
1631 : :
1632 : 0 : INS_ID( wname, "num_fa_in_blk%d", j ); // first one, or more
1633 : : int num_fa_in_blk;
1634 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, wname, (size_t)mesh_info.polyhedronFaces.size(), &num_fa_in_blk ) != NC_NOERR )
[ # # ]
1635 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes for face block " ); }
[ # # ][ # # ]
[ # # ]
1636 : :
1637 : : // fbepecnt
1638 : 0 : INS_ID( wname, "fbepecnt%d", j ); // first one, or more
1639 : : int fbepecnt;
1640 : 0 : dims[0] = num_fa_in_blk;
1641 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &fbepecnt ) )
1642 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create fbepecnt array for block " << 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1643 [ # # ][ # # ]: 0 : std::string enttype1( "NODE" );
1644 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, fbepecnt, "entity_type1", enttype1.length(), enttype1.c_str() ) )
1645 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type 1 " ); }
[ # # ][ # # ]
[ # # ]
1646 [ # # ][ # # ]: 0 : std::string enttype2( "FACE" );
1647 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, fbepecnt, "entity_type2", enttype2.length(), enttype2.c_str() ) )
1648 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type 2 " ); }
[ # # ][ # # ]
[ # # ][ # # ]
1649 : 0 : }
1650 : : }
1651 : :
1652 : : // Define element blocks
1653 : :
1654 [ + + ]: 34 : for( unsigned int i = 0; i < block_data.size(); i++ )
1655 : : {
1656 [ + - ]: 25 : MaterialSetData& block = block_data[i];
1657 : :
1658 : 25 : element_block_index = i + 1;
1659 : 25 : int num_el_in_blk = -1, num_att_in_blk = -1;
1660 : : int blk_attrib, connect;
1661 : :
1662 : : /* Define number of elements in this block */
1663 : :
1664 : 25 : INS_ID( wname, "num_el_in_blk%d", element_block_index );
1665 [ + - ][ - + ]: 25 : if( nc_def_dim( ncFile, wname, (size_t)block.number_elements, &num_el_in_blk ) != NC_NOERR )
1666 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of elements/block for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1667 : :
1668 : : /* Define number of nodes per element for this block */
1669 : 25 : INS_ID( wname, "num_nod_per_el%d", element_block_index );
1670 : 25 : int num_nod_per_el = -1;
1671 [ + - ]: 25 : if( EXOII_POLYHEDRON != block.element_type )
1672 [ + - ][ - + ]: 25 : if( nc_def_dim( ncFile, wname, (size_t)block.number_nodes_per_element, &num_nod_per_el ) != NC_NOERR )
1673 : : {
1674 [ # # ][ # # ]: 25 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes/element for block " << block.id );
[ # # ][ # # ]
[ # # ][ # # ]
1675 : : }
1676 : :
1677 : : /* Define element attribute array for this block */
1678 : : int dims[3];
1679 [ - + ]: 25 : if( block.number_attributes > 0 )
1680 : : {
1681 : 0 : INS_ID( wname, "num_att_in_blk%d", element_block_index );
1682 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, wname, (size_t)block.number_attributes, &num_att_in_blk ) != NC_NOERR )
1683 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of attributes in block " << block.id ); }
[ # # ][ # # ]
[ # # ][ # # ]
1684 : :
1685 : 0 : INS_ID( wname, "attrib%d", element_block_index );
1686 : 0 : dims[0] = num_el_in_blk;
1687 : 0 : dims[1] = num_att_in_blk;
1688 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_DOUBLE, 2, dims, &blk_attrib ) )
1689 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define attributes for element block " << block.id ); }
[ # # ][ # # ]
[ # # ][ # # ]
1690 : : }
1691 : :
1692 : : /* Define element connectivity array for this block */
1693 : :
1694 [ + - ][ + - ]: 25 : if( EXOII_POLYGON != block.element_type && EXOII_POLYHEDRON != block.element_type )
1695 : : {
1696 : 25 : INS_ID( wname, "connect%d", element_block_index );
1697 : 25 : dims[0] = num_el_in_blk;
1698 : 25 : dims[1] = num_nod_per_el;
1699 [ + - ][ - + ]: 25 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 2, dims, &connect ) )
1700 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create connectivity array for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1701 : :
1702 : : /* Store element type as attribute of connectivity variable */
1703 : :
1704 [ + - ]: 25 : std::string element_type_string( ExoIIUtil::ElementTypeNames[block.element_type] );
1705 [ - + ]: 25 : if( NC_NOERR != nc_put_att_text( ncFile, connect, "elem_type", element_type_string.length(),
1706 [ + - ]: 25 : element_type_string.c_str() ) )
1707 [ # # ][ # # ]: 25 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store element type name " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1708 : : }
1709 [ # # ]: 0 : else if( EXOII_POLYGON == block.element_type )
1710 : : {
1711 : 0 : INS_ID( wname, "connect%d", element_block_index );
1712 : : // need to define num_nod_per_el as total number of nodes
1713 : : // ebepecnt1 as number of nodes per polygon
1714 : : /*
1715 : : * int connect1(num_nod_per_el1) ;
1716 : : connect1:elem_type = "nsided" ;
1717 : : int ebepecnt1(num_el_in_blk1) ;
1718 : : ebepecnt1:entity_type1 = "NODE" ;
1719 : : ebepecnt1:entity_type2 = "ELEM" ;*/
1720 : 0 : dims[0] = num_nod_per_el;
1721 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &connect ) )
1722 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create connectivity array for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1723 [ # # ]: 0 : std::string element_type_string( "nsided" );
1724 [ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, connect, "elem_type", element_type_string.length(),
1725 [ # # ]: 0 : element_type_string.c_str() ) )
1726 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store element type name " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
1727 : 0 : INS_ID( wname, "ebepecnt%d", element_block_index );
1728 : : int ebepecnt;
1729 : 0 : dims[0] = num_el_in_blk;
1730 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &ebepecnt ) )
1731 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create ebepecnt array for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1732 [ # # ][ # # ]: 0 : std::string etype1( "NODE" );
1733 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, ebepecnt, "entity_type1", etype1.length(), etype1.c_str() ) )
1734 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type1 " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
1735 [ # # ][ # # ]: 0 : std::string etype2( "ELEM" );
1736 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, ebepecnt, "entity_type2", etype2.length(), etype2.c_str() ) )
1737 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type2 " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1738 : : }
1739 [ # # ]: 0 : else if( EXOII_POLYHEDRON == block.element_type )
1740 : : {
1741 : : // INS_ID(wname, "connect%d", element_block_index);
1742 : : /*
1743 : : testn face example: 3 polyh, 15 total faces, 2 shared; 15+2 = 17
1744 : : num_elem = 3 ;
1745 : : num_face = 15 ; // not needed?
1746 : : num_el_blk = 1 ;
1747 : :
1748 : : num_el_in_blk1 = 3 ;
1749 : : num_fac_per_el1 = 17 ;
1750 : :
1751 : : * num faces will be total face conn
1752 : : * num_faces_in_block will be number of faces (non repeated)
1753 : : * num_nodes_per_face will have total face connectivity
1754 : : */
1755 : 0 : int num_faces2 = 0;
1756 : :
1757 [ # # ][ # # ]: 0 : for( Range::iterator eit = block.elements.begin(); eit != block.elements.end(); eit++ )
[ # # ][ # # ]
[ # # ]
1758 : : {
1759 [ # # ]: 0 : EntityHandle polyh = *eit;
1760 : 0 : int nfaces = 0;
1761 : 0 : const EntityHandle* conn = NULL;
1762 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_connectivity( polyh, conn, nfaces );MB_CHK_ERR( rval );
[ # # ][ # # ]
1763 : 0 : num_faces2 += nfaces;
1764 : : }
1765 : :
1766 : : int num_fac_per_el;
1767 : :
1768 : 0 : INS_ID( wname, "num_fac_per_el%d", element_block_index );
1769 [ # # ][ # # ]: 0 : if( nc_def_dim( ncFile, wname, (size_t)num_faces2, &num_fac_per_el ) != NC_NOERR )
1770 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of faces per block " << block.id ); }
[ # # ][ # # ]
[ # # ][ # # ]
1771 : :
1772 : : /*
1773 : : int facconn1(num_fac_per_el1) ;
1774 : : facconn1:elem_type = "NFACED" ;
1775 : : int ebepecnt1(num_el_in_blk1) ;
1776 : : ebepecnt1:entity_type1 = "FACE" ;
1777 : : ebepecnt1:entity_type2 = "ELEM" ;
1778 : : */
1779 : :
1780 : : // facconn
1781 : 0 : INS_ID( wname, "facconn%d", element_block_index );
1782 : : int facconn;
1783 : 0 : dims[0] = num_fac_per_el;
1784 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &facconn ) )
1785 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create facconn array for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1786 [ # # ]: 0 : std::string etype( "NFACED" );
1787 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, facconn, "elem_type", etype.length(), etype.c_str() ) )
1788 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store elem type " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
1789 : :
1790 : : // ebepecnt
1791 : 0 : INS_ID( wname, "ebepecnt%d", element_block_index );
1792 : : int ebepecnt;
1793 : 0 : dims[0] = num_el_in_blk;
1794 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, dims, &ebepecnt ) )
1795 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create ebepecnt array for block " << i + 1 ); }
[ # # ][ # # ]
[ # # ][ # # ]
1796 [ # # ][ # # ]: 0 : std::string etype1( "FACE" );
1797 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, ebepecnt, "entity_type1", etype1.length(), etype1.c_str() ) )
1798 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type1 " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
1799 [ # # ][ # # ]: 0 : std::string etype2( "ELEM" );
1800 [ # # ][ # # ]: 0 : if( NC_NOERR != nc_put_att_text( ncFile, ebepecnt, "entity_type2", etype2.length(), etype2.c_str() ) )
1801 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store entity type2 " << (int)block.element_type ); }
[ # # ][ # # ]
[ # # ][ # # ]
1802 : :
1803 [ # # ]: 0 : block.number_nodes_per_element = num_faces2; // connectivity for all polyhedra in block
1804 : : }
1805 : : }
1806 : :
1807 : : /* Node set id array: */
1808 : :
1809 : 9 : int non_empty_nss = 0;
1810 : : // Need to go through nodesets to compute # nodesets, some might be empty
1811 : 9 : std::vector< DirichletSetData >::iterator ns_it;
1812 [ + - ][ + - ]: 18 : for( ns_it = nodeset_data.begin(); ns_it != nodeset_data.end(); ++ns_it )
[ + + ]
1813 : : {
1814 [ + - ][ + - ]: 9 : if( 0 != ( *ns_it ).number_nodes ) non_empty_nss++;
1815 : : }
1816 : :
1817 : 9 : int num_ns = -1;
1818 : 9 : int ns_idstat = -1, ns_idarr = -1;
1819 [ + + ]: 9 : if( non_empty_nss > 0 )
1820 : : {
1821 [ + - ][ - + ]: 3 : if( nc_def_dim( ncFile, "num_node_sets", ( size_t )( non_empty_nss ), &num_ns ) != NC_NOERR )
1822 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of node sets" ); }
[ # # ][ # # ]
[ # # ]
1823 : :
1824 : : /* Node set id status array: */
1825 : :
1826 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_def_var( ncFile, "ns_status", NC_LONG, 1, &num_ns, &ns_idstat ) )
1827 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create node sets status array" ); }
[ # # ][ # # ]
[ # # ]
1828 : :
1829 : : /* Node set id array: */
1830 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_def_var( ncFile, "ns_prop1", NC_LONG, 1, &num_ns, &ns_idarr ) )
1831 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create node sets property array" ); }
[ # # ][ # # ]
[ # # ]
1832 : :
1833 : : /* Store property name as attribute of property array variable */
1834 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_put_att_text( ncFile, NC_GLOBAL, "name", strlen( "ID" ), "ID" ) )
1835 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store node set property name ID" ); }
[ # # ][ # # ]
[ # # ]
1836 : :
1837 : : // Now, define the arrays needed for each node set
1838 : :
1839 : 3 : int index = 0;
1840 : :
1841 [ + + ]: 12 : for( unsigned i = 0; i < nodeset_data.size(); i++ )
1842 : : {
1843 [ + - ][ + - ]: 9 : DirichletSetData node_set = nodeset_data[i];
1844 : :
1845 [ - + ]: 9 : if( 0 == node_set.number_nodes )
1846 : : {
1847 [ # # ][ # # ]: 0 : MB_SET_ERR_CONT( "WriteNCDF: empty nodeset " << node_set.id );
[ # # ][ # # ]
[ # # ][ # # ]
1848 : 0 : continue;
1849 : : }
1850 : 9 : index++;
1851 : :
1852 : 9 : int num_nod_ns = -1;
1853 : 9 : INS_ID( wname, "num_nod_ns%d", index );
1854 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, wname, (size_t)node_set.number_nodes, &num_nod_ns ) != NC_NOERR )
1855 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of nodes for set " << node_set.id ); }
[ # # ][ # # ]
[ # # ][ # # ]
1856 : :
1857 : : /* Create variable array in which to store the node set node list */
1858 : 9 : int node_ns = -1;
1859 : 9 : INS_ID( wname, "node_ns%d", index );
1860 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, &num_nod_ns, &node_ns ) )
1861 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create node set " << node_set.id << " node list" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1862 : :
1863 : : // Create distribution factor array
1864 : 9 : int fact_ns = -1;
1865 : 9 : INS_ID( wname, "dist_fact_ns%d", index );
1866 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_DOUBLE, 1, &num_nod_ns, &fact_ns ) )
1867 : : {
1868 [ # # ][ # # ]: 9 : MB_SET_ERR( MB_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ + - - ]
1869 : : "WriteNCDF: failed to create node set " << node_set.id << " distribution factor list" );
1870 : : }
1871 : 9 : }
1872 : : }
1873 : :
1874 : : /* Side set id array: */
1875 : :
1876 : 9 : long non_empty_ss = 0;
1877 : : // Need to go through nodesets to compute # nodesets, some might be empty
1878 : 9 : std::vector< NeumannSetData >::iterator ss_it;
1879 [ + - ][ + - ]: 21 : for( ss_it = sideset_data.begin(); ss_it != sideset_data.end(); ++ss_it )
[ + + ]
1880 : : {
1881 [ + - ][ + - ]: 12 : if( 0 != ( *ss_it ).number_elements ) non_empty_ss++;
1882 : : }
1883 : :
1884 [ + + ]: 9 : if( non_empty_ss > 0 )
1885 : : {
1886 : 3 : int num_ss = -1;
1887 [ + - ][ - + ]: 3 : if( nc_def_dim( ncFile, "num_side_sets", non_empty_ss, &num_ss ) != NC_NOERR )
1888 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of side sets" ); }
[ # # ][ # # ]
[ # # ]
1889 : :
1890 : : /* Side set id status array: */
1891 : 3 : int ss_idstat = -1, ss_idarr = -1;
1892 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_def_var( ncFile, "ss_status", NC_LONG, 1, &num_ss, &ss_idstat ) )
1893 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define side set status" ); }
[ # # ][ # # ]
[ # # ]
1894 : :
1895 : : /* Side set id array: */
1896 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_def_var( ncFile, "ss_prop1", NC_LONG, 1, &num_ss, &ss_idarr ) )
1897 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define side set property" ); }
[ # # ][ # # ]
[ # # ]
1898 : :
1899 : : /* Store property name as attribute of property array variable */
1900 [ + - ][ - + ]: 3 : if( NC_NOERR != nc_put_att_text( ncFile, ss_idarr, "name", strlen( "ID" ), "ID" ) )
1901 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to store side set property name ID" ); }
[ # # ][ # # ]
[ # # ]
1902 : :
1903 : : // Now, define the arrays needed for each side set
1904 : :
1905 : 3 : int index = 0;
1906 [ + + ]: 15 : for( unsigned int i = 0; i < sideset_data.size(); i++ )
1907 : : {
1908 [ + - ][ + - ]: 12 : NeumannSetData side_set = sideset_data[i];
1909 : :
1910 : : // Don't define an empty set
1911 [ - + ]: 12 : if( 0 == side_set.number_elements ) continue;
1912 : :
1913 : 12 : index++;
1914 : :
1915 : 12 : int num_side_ss = -1;
1916 : 12 : int elem_ss = -1, side_ss = -1;
1917 : 12 : INS_ID( wname, "num_side_ss%d", index );
1918 [ + - ][ - + ]: 12 : if( nc_def_dim( ncFile, wname, (size_t)side_set.number_elements, &num_side_ss ) != NC_NOERR )
1919 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of sides in side set " << side_set.id ); }
[ # # ][ # # ]
[ # # ][ # # ]
1920 : :
1921 : 12 : INS_ID( wname, "elem_ss%d", index );
1922 [ + - ][ - + ]: 12 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, &num_side_ss, &elem_ss ) )
1923 : : {
1924 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create element list for side set "
[ # # ][ # # ]
[ # # ][ # # ]
1925 : : << side_set.id ); /* Exit define mode and return */
1926 : : }
1927 : 12 : INS_ID( wname, "side_ss%d", index );
1928 [ + - ][ - + ]: 12 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, &num_side_ss, &side_ss ) )
1929 : : {
1930 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create side list for side set "
[ # # ][ # # ]
[ # # ][ # # ]
1931 : : << side_set.id ); /* Exit define mode and return */
1932 : : }
1933 : :
1934 : : // sideset distribution factors
1935 : 12 : int num_df_ss = -1;
1936 : 12 : INS_ID( wname, "num_df_ss%d", index );
1937 [ + - ][ - + ]: 12 : if( nc_def_dim( ncFile, wname, (size_t)side_set.ss_dist_factors.size(), &num_df_ss ) != NC_NOERR )
1938 : : {
1939 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define number of dist factors in side set "
[ # # ][ # # ]
[ # # ][ # # ]
1940 : : << side_set.id ); /* Exit define mode and return */
1941 : : }
1942 : :
1943 : : /* Create variable array in which to store the side set distribution factors */
1944 : :
1945 : 12 : int fact_ss = -1;
1946 : 12 : INS_ID( wname, "dist_fact_ss%d", index );
1947 [ + - ][ - + ]: 12 : if( NC_NOERR != nc_def_var( ncFile, wname, NC_LONG, 1, &num_df_ss, &fact_ss ) )
1948 : : {
1949 [ # # ][ # # ]: 12 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create dist factors list for side set "
[ # # ][ # # ]
[ # # ][ # # ]
[ + - - ]
1950 : : << side_set.id ); /* Exit define mode and return */
1951 : : }
1952 : 12 : }
1953 : : }
1954 : :
1955 : : /* Node coordinate arrays: */
1956 : :
1957 : : int coord, name_coord, dims[3];
1958 : 9 : dims[0] = num_dim;
1959 : 9 : dims[1] = num_nodes;
1960 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "coord", NC_DOUBLE, 2, dims, &coord ) )
1961 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define node coordinate array" ); }
[ # # ][ # # ]
[ # # ]
1962 : :
1963 : : /* Coordinate names array */
1964 : :
1965 : 9 : dims[0] = num_dim;
1966 : 9 : dims[1] = dim_str;
1967 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "coor_names", NC_CHAR, 2, dims, &name_coord ) )
1968 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define coordinate name array" ); }
[ # # ][ # # ]
[ # # ]
1969 : :
1970 : : // Define genesis maps if required
1971 : :
1972 [ + - ]: 9 : if( write_maps )
1973 : : {
1974 : : // Element map
1975 : 9 : int elem_map = -1, elem_map2 = -1, node_map = -1;
1976 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "elem_map", NC_LONG, 1, &num_elem, &elem_map ) )
1977 : : {
1978 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create element map array" ); /* Exit define mode and return */
[ # # ][ # # ]
[ # # ]
1979 : : }
1980 : :
1981 : : // Create the element number map
1982 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "elem_num_map", NC_LONG, 1, &num_elem, &elem_map2 ) )
1983 : : {
1984 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create element numbering map" ); /* Exit define mode
[ # # ][ # # ]
[ # # ]
1985 : : and return */
1986 : : }
1987 : :
1988 : : // Create node number map
1989 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "node_num_map", NC_LONG, 1, &num_nodes, &node_map ) )
1990 : : {
1991 [ # # ][ # # ]: 9 : MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to create node numbering map array" ); /* Exit define mode and
[ # # ][ # # ]
[ # # ]
1992 : : return */
1993 : : }
1994 : : }
1995 : :
1996 : : // Define qa records to be used
1997 : :
1998 : 9 : int num_qa_rec = mesh_info.qaRecords.size() / 4;
1999 : 9 : int num_qa = -1;
2000 : :
2001 [ + - ][ - + ]: 9 : if( nc_def_dim( ncFile, "num_qa_rec", (long)num_qa_rec, &num_qa ) != NC_NOERR )
2002 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define qa record array size" ); }
[ # # ][ # # ]
[ # # ]
2003 : :
2004 : : // Define qa array
2005 : : int qa_title;
2006 : 9 : dims[0] = num_qa;
2007 : 9 : dims[1] = dim_four;
2008 : 9 : dims[2] = dim_str;
2009 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_def_var( ncFile, "qa_records", NC_CHAR, 3, dims, &qa_title ) )
2010 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_FAILURE, "WriteNCDF: failed to define qa record array" ); }
[ # # ][ # # ]
[ # # ]
2011 : :
2012 : : // Take it out of define mode
2013 [ + - ][ - + ]: 9 : if( NC_NOERR != nc_enddef( ncFile ) ) { MB_SET_ERR( MB_FAILURE, "WriteNCDF: Trouble leaving define mode" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2014 : :
2015 : 9 : return MB_SUCCESS;
2016 : : }
2017 : :
2018 : 0 : ErrorCode WriteNCDF::open_file( const char* filename )
2019 : : {
2020 : : // Not a valid filename
2021 [ # # ][ # # ]: 0 : if( strlen( (const char*)filename ) == 0 ) { MB_SET_ERR( MB_FAILURE, "Output Exodus filename not specified" ); }
[ # # ][ # # ]
[ # # ][ # # ]
2022 : :
2023 : 0 : int fail = nc_create( filename, NC_CLOBBER, &ncFile );
2024 : :
2025 : : // File couldn't be opened
2026 [ # # ][ # # ]: 0 : if( NC_NOERR != fail ) { MB_SET_ERR( MB_FAILURE, "Cannot open " << filename ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2027 : :
2028 : 0 : return MB_SUCCESS;
2029 : : }
2030 : :
2031 : 12 : ErrorCode WriteNCDF::get_sideset_elems( EntityHandle sideset, int current_sense, Range& forward_elems,
2032 : : Range& reverse_elems )
2033 : : {
2034 [ + - ][ + - ]: 24 : Range ss_elems, ss_meshsets;
2035 : :
2036 : : // Get the sense tag; don't need to check return, might be an error if the tag
2037 : : // hasn't been created yet
2038 : 12 : Tag sense_tag = 0;
2039 [ + - ]: 12 : mdbImpl->tag_get_handle( "SENSE", 1, MB_TYPE_INTEGER, sense_tag );
2040 : :
2041 : : // Get the entities in this set
2042 [ + - ]: 12 : ErrorCode result = mdbImpl->get_entities_by_handle( sideset, ss_elems, true );
2043 [ - + ]: 12 : if( MB_FAILURE == result ) return result;
2044 : :
2045 : : // Now remove the meshsets into the ss_meshsets; first find the first meshset,
2046 [ + - ]: 12 : Range::iterator range_iter = ss_elems.begin();
2047 [ + - ][ + - ]: 96 : while( TYPE_FROM_HANDLE( *range_iter ) != MBENTITYSET && range_iter != ss_elems.end() )
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ]
[ + + # # ]
2048 [ + - ]: 84 : ++range_iter;
2049 : :
2050 : : // Then, if there are some, copy them into ss_meshsets and erase from ss_elems
2051 [ + - ][ + - ]: 12 : if( range_iter != ss_elems.end() )
[ - + ]
2052 : : {
2053 [ # # ][ # # ]: 0 : std::copy( range_iter, ss_elems.end(), range_inserter( ss_meshsets ) );
[ # # ]
2054 [ # # ][ # # ]: 0 : ss_elems.erase( range_iter, ss_elems.end() );
2055 : : }
2056 : :
2057 : : // OK, for the elements, check the sense of this set and copy into the right range
2058 : : // (if the sense is 0, copy into both ranges)
2059 : :
2060 : : // Need to step forward on list until we reach the right dimension
2061 [ + - ]: 12 : Range::iterator dum_it = ss_elems.end();
2062 [ + - ]: 12 : --dum_it;
2063 [ + - ][ + - ]: 12 : int target_dim = CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) );
[ + - ]
2064 [ + - ]: 12 : dum_it = ss_elems.begin();
2065 [ + - ][ + - ]: 12 : while( target_dim != CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) ) && dum_it != ss_elems.end() )
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ - + ]
[ - + # # ]
2066 [ # # ]: 0 : ++dum_it;
2067 : :
2068 [ + - ][ + - ]: 12 : if( current_sense == 1 || current_sense == 0 ) std::copy( dum_it, ss_elems.end(), range_inserter( forward_elems ) );
[ + - ][ + - ]
[ + - ]
2069 [ + - ][ + - ]: 12 : if( current_sense == -1 || current_sense == 0 )
2070 [ + - ][ + - ]: 12 : std::copy( dum_it, ss_elems.end(), range_inserter( reverse_elems ) );
[ + - ]
2071 : :
2072 : : // Now loop over the contained meshsets, getting the sense of those and calling this
2073 : : // function recursively
2074 [ + - ][ # # ]: 12 : for( range_iter = ss_meshsets.begin(); range_iter != ss_meshsets.end(); ++range_iter )
[ + - ][ + - ]
[ - + ]
2075 : : {
2076 : : // First get the sense; if it's not there, by convention it's forward
2077 : : int this_sense;
2078 [ # # ][ # # ]: 0 : if( 0 == sense_tag || MB_FAILURE == mdbImpl->tag_get_data( sense_tag, &( *range_iter ), 1, &this_sense ) )
[ # # ][ # # ]
[ # # ]
2079 : 0 : this_sense = 1;
2080 : :
2081 : : // Now get all the entities on this meshset, with the proper (possibly reversed) sense
2082 [ # # ][ # # ]: 0 : get_sideset_elems( *range_iter, this_sense * current_sense, forward_elems, reverse_elems );
2083 : : }
2084 : :
2085 : 24 : return result;
2086 : : }
2087 : :
2088 [ + - ][ + - ]: 228 : } // namespace moab
|