Branch data Line data Source code
1 : : #include "NCHelperGCRM.hpp"
2 : : #include "moab/ReadUtilIface.hpp"
3 : : #include "moab/FileOptions.hpp"
4 : : #include "moab/SpectralMeshTool.hpp"
5 : : #include "MBTagConventions.hpp"
6 : :
7 : : #ifdef MOAB_HAVE_ZOLTAN
8 : : #include "moab/ZoltanPartitioner.hpp"
9 : : #endif
10 : :
11 : : #include <cmath>
12 : :
13 : : namespace moab
14 : : {
15 : :
16 : : // GCRM cells are either pentagons or hexagons, and pentagons are always padded to hexagons
17 : : const int EDGES_PER_CELL = 6;
18 : :
19 : 0 : NCHelperGCRM::NCHelperGCRM( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
20 [ # # ]: 0 : : UcdNCHelper( readNC, fileId, opts, fileSet ), createGatherSet( false )
21 : : {
22 : : // Ignore variables containing topological information
23 [ # # ][ # # ]: 0 : ignoredVarNames.insert( "grid" );
24 [ # # ][ # # ]: 0 : ignoredVarNames.insert( "cell_corners" );
25 [ # # ][ # # ]: 0 : ignoredVarNames.insert( "cell_edges" );
26 [ # # ][ # # ]: 0 : ignoredVarNames.insert( "edge_corners" );
27 [ # # ][ # # ]: 0 : ignoredVarNames.insert( "cell_neighbors" );
28 : 0 : }
29 : :
30 : 0 : bool NCHelperGCRM::can_read_file( ReadNC* readNC )
31 : : {
32 : 0 : std::vector< std::string >& dimNames = readNC->dimNames;
33 : :
34 : : // If dimension name "cells" exists then it should be the GCRM grid
35 [ # # ][ # # ]: 0 : if( std::find( dimNames.begin(), dimNames.end(), std::string( "cells" ) ) != dimNames.end() ) return true;
[ # # ][ # # ]
36 : :
37 : 0 : return false;
38 : : }
39 : :
40 : 0 : ErrorCode NCHelperGCRM::init_mesh_vals()
41 : : {
42 : 0 : std::vector< std::string >& dimNames = _readNC->dimNames;
43 : 0 : std::vector< int >& dimLens = _readNC->dimLens;
44 : 0 : std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
45 : :
46 : : ErrorCode rval;
47 : : unsigned int idx;
48 : 0 : std::vector< std::string >::iterator vit;
49 : :
50 : : // Look for time dimension
51 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "Time" ) ) != dimNames.end() )
[ # # ]
52 [ # # ]: 0 : idx = vit - dimNames.begin();
53 [ # # ][ # # ]: 0 : else if( ( vit = std::find( dimNames.begin(), dimNames.end(), "time" ) ) != dimNames.end() )
[ # # ]
54 [ # # ]: 0 : idx = vit - dimNames.begin();
55 : : else
56 : : {
57 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'Time' or 'time' dimension" );
[ # # ][ # # ]
[ # # ]
58 : : }
59 : 0 : tDim = idx;
60 [ # # ]: 0 : nTimeSteps = dimLens[idx];
61 : :
62 : : // Get number of cells
63 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "cells" ) ) != dimNames.end() )
[ # # ]
64 [ # # ]: 0 : idx = vit - dimNames.begin();
65 : : else
66 : : {
67 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'cells' dimension" );
[ # # ][ # # ]
[ # # ]
68 : : }
69 : 0 : cDim = idx;
70 [ # # ]: 0 : nCells = dimLens[idx];
71 : :
72 : : // Get number of edges
73 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "edges" ) ) != dimNames.end() )
[ # # ]
74 [ # # ]: 0 : idx = vit - dimNames.begin();
75 : : else
76 : : {
77 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'edges' dimension" );
[ # # ][ # # ]
[ # # ]
78 : : }
79 : 0 : eDim = idx;
80 [ # # ]: 0 : nEdges = dimLens[idx];
81 : :
82 : : // Get number of vertices
83 : 0 : vDim = -1;
84 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "corners" ) ) != dimNames.end() )
[ # # ]
85 [ # # ]: 0 : idx = vit - dimNames.begin();
86 : : else
87 : : {
88 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'corners' dimension" );
[ # # ][ # # ]
[ # # ]
89 : : }
90 : 0 : vDim = idx;
91 [ # # ]: 0 : nVertices = dimLens[idx];
92 : :
93 : : // Get number of layers
94 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "layers" ) ) != dimNames.end() )
[ # # ]
95 [ # # ]: 0 : idx = vit - dimNames.begin();
96 : : else
97 : : {
98 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'layers' dimension" );
[ # # ][ # # ]
[ # # ]
99 : : }
100 : 0 : levDim = idx;
101 [ # # ]: 0 : nLevels = dimLens[idx];
102 : :
103 : : // Dimension indices for other optional levels
104 [ # # ]: 0 : std::vector< unsigned int > opt_lev_dims;
105 : :
106 : : // Get index of interface levels
107 [ # # ][ # # ]: 0 : if( ( vit = std::find( dimNames.begin(), dimNames.end(), "interfaces" ) ) != dimNames.end() )
[ # # ]
108 : : {
109 [ # # ]: 0 : idx = vit - dimNames.begin();
110 [ # # ]: 0 : opt_lev_dims.push_back( idx );
111 : : }
112 : :
113 [ # # ]: 0 : std::map< std::string, ReadNC::VarData >::iterator vmit;
114 : :
115 : : // Store time coordinate values in tVals
116 [ # # ]: 0 : if( nTimeSteps > 0 )
117 : : {
118 [ # # ][ # # ]: 0 : if( ( vmit = varInfo.find( "time" ) ) != varInfo.end() )
[ # # ][ # # ]
119 : : {
120 [ # # ][ # # ]: 0 : rval = read_coordinate( "time", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 'time' variable" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
121 : : }
122 [ # # ][ # # ]: 0 : else if( ( vmit = varInfo.find( "t" ) ) != varInfo.end() )
[ # # ][ # # ]
123 : : {
124 [ # # ][ # # ]: 0 : rval = read_coordinate( "t", 0, nTimeSteps - 1, tVals );MB_CHK_SET_ERR( rval, "Trouble reading 't' variable" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
125 : : }
126 : : else
127 : : {
128 : : // If expected time variable is not available, set dummy time coordinate values to tVals
129 [ # # ]: 0 : for( int t = 0; t < nTimeSteps; t++ )
130 [ # # ]: 0 : tVals.push_back( (double)t );
131 : : }
132 : : }
133 : :
134 : : // For each variable, determine the entity location type and number of levels
135 [ # # ][ # # ]: 0 : for( vmit = varInfo.begin(); vmit != varInfo.end(); ++vmit )
[ # # ]
136 : : {
137 [ # # ]: 0 : ReadNC::VarData& vd = ( *vmit ).second;
138 : :
139 : : // Default entLoc is ENTLOCSET
140 [ # # ][ # # ]: 0 : if( std::find( vd.varDims.begin(), vd.varDims.end(), tDim ) != vd.varDims.end() )
[ # # ]
141 : : {
142 [ # # ][ # # ]: 0 : if( std::find( vd.varDims.begin(), vd.varDims.end(), vDim ) != vd.varDims.end() )
[ # # ]
143 : 0 : vd.entLoc = ReadNC::ENTLOCVERT;
144 [ # # ][ # # ]: 0 : else if( std::find( vd.varDims.begin(), vd.varDims.end(), eDim ) != vd.varDims.end() )
[ # # ]
145 : 0 : vd.entLoc = ReadNC::ENTLOCEDGE;
146 [ # # ][ # # ]: 0 : else if( std::find( vd.varDims.begin(), vd.varDims.end(), cDim ) != vd.varDims.end() )
[ # # ]
147 : 0 : vd.entLoc = ReadNC::ENTLOCFACE;
148 : : }
149 : :
150 : : // Default numLev is 0
151 [ # # ][ # # ]: 0 : if( std::find( vd.varDims.begin(), vd.varDims.end(), levDim ) != vd.varDims.end() )
[ # # ]
152 : 0 : vd.numLev = nLevels;
153 : : else
154 : : {
155 : : // If layers dimension is not found, try other optional levels such as interfaces
156 [ # # ]: 0 : for( unsigned int i = 0; i < opt_lev_dims.size(); i++ )
157 : : {
158 [ # # ][ # # ]: 0 : if( std::find( vd.varDims.begin(), vd.varDims.end(), opt_lev_dims[i] ) != vd.varDims.end() )
[ # # ][ # # ]
159 : : {
160 [ # # ][ # # ]: 0 : vd.numLev = dimLens[opt_lev_dims[i]];
161 : 0 : break;
162 : : }
163 : : }
164 : : }
165 : : }
166 : :
167 : : // Hack: create dummy variables for dimensions (like cells) with no corresponding coordinate
168 : : // variables
169 [ # # ][ # # ]: 0 : rval = create_dummy_variables();MB_CHK_SET_ERR( rval, "Failed to create dummy variables" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
170 : :
171 : 0 : return MB_SUCCESS;
172 : : }
173 : :
174 : : // When noMesh option is used on this read, the old ReadNC class instance for last read can get out
175 : : // of scope (and deleted). The old instance initialized some variables properly when the mesh was
176 : : // created, but they are now lost. The new instance (will not create the mesh with noMesh option)
177 : : // has to restore them based on the existing mesh from last read
178 : 0 : ErrorCode NCHelperGCRM::check_existing_mesh()
179 : : {
180 : 0 : Interface*& mbImpl = _readNC->mbImpl;
181 : 0 : Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
182 : 0 : bool& noMesh = _readNC->noMesh;
183 : :
184 [ # # ]: 0 : if( noMesh )
185 : : {
186 : : ErrorCode rval;
187 : :
188 [ # # ]: 0 : if( localGidVerts.empty() )
189 : : {
190 : : // Get all vertices from current file set (it is the input set in no_mesh scenario)
191 [ # # ]: 0 : Range local_verts;
192 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 0, local_verts );MB_CHK_SET_ERR( rval, "Trouble getting local vertices in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
193 : :
194 [ # # ][ # # ]: 0 : if( !local_verts.empty() )
195 : : {
196 [ # # ][ # # ]: 0 : std::vector< int > gids( local_verts.size() );
197 : :
198 : : // !IMPORTANT : this has to be the GLOBAL_ID tag
199 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( mGlobalIdTag, local_verts, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
200 : :
201 : : // Restore localGidVerts
202 [ # # ][ # # ]: 0 : std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidVerts ) );
203 [ # # ][ # # ]: 0 : nLocalVertices = localGidVerts.size();
[ # # ]
204 : 0 : }
205 : : }
206 : :
207 [ # # ]: 0 : if( localGidEdges.empty() )
208 : : {
209 : : // Get all edges from current file set (it is the input set in no_mesh scenario)
210 [ # # ]: 0 : Range local_edges;
211 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 1, local_edges );MB_CHK_SET_ERR( rval, "Trouble getting local edges in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
212 : :
213 [ # # ][ # # ]: 0 : if( !local_edges.empty() )
214 : : {
215 [ # # ][ # # ]: 0 : std::vector< int > gids( local_edges.size() );
216 : :
217 : : // !IMPORTANT : this has to be the GLOBAL_ID tag
218 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( mGlobalIdTag, local_edges, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of edges" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
219 : :
220 : : // Restore localGidEdges
221 [ # # ][ # # ]: 0 : std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidEdges ) );
222 [ # # ][ # # ]: 0 : nLocalEdges = localGidEdges.size();
[ # # ]
223 : 0 : }
224 : : }
225 : :
226 [ # # ]: 0 : if( localGidCells.empty() )
227 : : {
228 : : // Get all cells from current file set (it is the input set in no_mesh scenario)
229 [ # # ]: 0 : Range local_cells;
230 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 2, local_cells );MB_CHK_SET_ERR( rval, "Trouble getting local cells in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
231 : :
232 [ # # ][ # # ]: 0 : if( !local_cells.empty() )
233 : : {
234 [ # # ][ # # ]: 0 : std::vector< int > gids( local_cells.size() );
235 : :
236 : : // !IMPORTANT : this has to be the GLOBAL_ID tag
237 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_data( mGlobalIdTag, local_cells, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of cells" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
238 : :
239 : : // Restore localGidCells
240 [ # # ][ # # ]: 0 : std::copy( gids.rbegin(), gids.rend(), range_inserter( localGidCells ) );
241 [ # # ][ # # ]: 0 : nLocalCells = localGidCells.size();
[ # # ]
242 : 0 : }
243 : : }
244 : : }
245 : :
246 : 0 : return MB_SUCCESS;
247 : : }
248 : :
249 : 0 : ErrorCode NCHelperGCRM::create_mesh( Range& faces )
250 : : {
251 : 0 : bool& noEdges = _readNC->noEdges;
252 : 0 : DebugOutput& dbgOut = _readNC->dbgOut;
253 : :
254 : : #ifdef MOAB_HAVE_MPI
255 : 0 : int rank = 0;
256 : 0 : int procs = 1;
257 : 0 : bool& isParallel = _readNC->isParallel;
258 [ # # ]: 0 : if( isParallel )
259 : : {
260 : 0 : ParallelComm*& myPcomm = _readNC->myPcomm;
261 [ # # ][ # # ]: 0 : rank = myPcomm->proc_config().proc_rank();
262 [ # # ][ # # ]: 0 : procs = myPcomm->proc_config().proc_size();
263 : : }
264 : :
265 : : // Need to know whether we'll be creating gather mesh
266 [ # # ]: 0 : if( rank == _readNC->gatherSetRank ) createGatherSet = true;
267 : :
268 [ # # ]: 0 : if( procs >= 2 )
269 : : {
270 : : // Shift rank to obtain a rotated trivial partition
271 : 0 : int shifted_rank = rank;
272 : 0 : int& trivialPartitionShift = _readNC->trivialPartitionShift;
273 [ # # ]: 0 : if( trivialPartitionShift > 0 ) shifted_rank = ( rank + trivialPartitionShift ) % procs;
274 : :
275 : : // Compute the number of local cells on this proc
276 : 0 : nLocalCells = int( std::floor( 1.0 * nCells / procs ) );
277 : :
278 : : // The starting global cell index in the GCRM file for this proc
279 : 0 : int start_cell_idx = shifted_rank * nLocalCells;
280 : :
281 : : // Number of extra cells after equal split over procs
282 : 0 : int iextra = nCells % procs;
283 : :
284 : : // Allocate extra cells over procs
285 [ # # ]: 0 : if( shifted_rank < iextra ) nLocalCells++;
286 [ # # ]: 0 : start_cell_idx += std::min( shifted_rank, iextra );
287 : :
288 : 0 : start_cell_idx++; // 0 based -> 1 based
289 : :
290 : : // Redistribute local cells after trivial partition (e.g. apply Zoltan partition)
291 [ # # ][ # # ]: 0 : ErrorCode rval = redistribute_local_cells( start_cell_idx );MB_CHK_SET_ERR( rval, "Failed to redistribute local cells after trivial partition" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
292 : : }
293 : : else
294 : : {
295 : 0 : nLocalCells = nCells;
296 [ # # ]: 0 : localGidCells.insert( 1, nLocalCells );
297 : : }
298 : : #else
299 : : nLocalCells = nCells;
300 : : localGidCells.insert( 1, nLocalCells );
301 : : #endif
302 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidCells.psize() = %d\n", (int)localGidCells.psize() );
303 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidCells.size() = %d\n", (int)localGidCells.size() );
304 : :
305 : : // Read vertices on each local cell, to get localGidVerts and cell connectivity later
306 : : int verticesOnCellVarId;
307 [ # # ]: 0 : int success = NCFUNC( inq_varid )( _fileId, "cell_corners", &verticesOnCellVarId );
308 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of cell_corners" );
[ # # ][ # # ]
[ # # ][ # # ]
309 [ # # ]: 0 : std::vector< int > vertices_on_local_cells( nLocalCells * EDGES_PER_CELL );
310 [ # # ]: 0 : dbgOut.tprintf( 1, " nLocalCells = %d\n", (int)nLocalCells );
311 [ # # ]: 0 : dbgOut.tprintf( 1, " vertices_on_local_cells.size() = %d\n", (int)vertices_on_local_cells.size() );
312 : : #ifdef MOAB_HAVE_PNETCDF
313 : : size_t nb_reads = localGidCells.psize();
314 : : std::vector< int > requests( nb_reads );
315 : : std::vector< int > statuss( nb_reads );
316 : : size_t idxReq = 0;
317 : : #endif
318 : 0 : size_t indexInArray = 0;
319 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = localGidCells.pair_begin(); pair_iter != localGidCells.pair_end();
[ # # ][ # # ]
[ # # ]
320 : : ++pair_iter )
321 : : {
322 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
323 [ # # ]: 0 : EntityHandle endh = pair_iter->second;
324 [ # # ]: 0 : dbgOut.tprintf( 1, " cell_corners starth = %d\n", (int)starth );
325 [ # # ]: 0 : dbgOut.tprintf( 1, " cell_corners endh = %d\n", (int)endh );
326 : 0 : NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
327 : 0 : NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ),
328 : 0 : static_cast< NCDF_SIZE >( EDGES_PER_CELL ) };
329 : :
330 : : // Do a partial read in each subrange
331 : : #ifdef MOAB_HAVE_PNETCDF
332 : : success = NCFUNCREQG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
333 : : &( vertices_on_local_cells[indexInArray] ), &requests[idxReq++] );
334 : : #else
335 : : success = NCFUNCAG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts,
336 [ # # ][ # # ]: 0 : &( vertices_on_local_cells[indexInArray] ) );
337 : : #endif
338 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read cell_corners data in a loop" );
[ # # ][ # # ]
[ # # ][ # # ]
339 : :
340 : : // Increment the index for next subrange
341 : 0 : indexInArray += ( endh - starth + 1 ) * EDGES_PER_CELL;
342 : : }
343 : :
344 : : #ifdef MOAB_HAVE_PNETCDF
345 : : // Wait outside the loop
346 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
347 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
348 : : #endif
349 : :
350 : : // Correct vertices_on_local_cells array. Pentagons as hexagons should have
351 : : // a connectivity like 123455 and not 122345
352 [ # # ]: 0 : for( int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++ )
353 : : {
354 [ # # ]: 0 : int* pvertex = &vertices_on_local_cells[local_cell_idx * EDGES_PER_CELL];
355 [ # # ]: 0 : for( int k = 0; k < EDGES_PER_CELL - 2; k++ )
356 : : {
357 [ # # ]: 0 : if( *( pvertex + k ) == *( pvertex + k + 1 ) )
358 : : {
359 : : // Shift the connectivity
360 [ # # ]: 0 : for( int kk = k + 1; kk < EDGES_PER_CELL - 1; kk++ )
361 : 0 : *( pvertex + kk ) = *( pvertex + kk + 1 );
362 : : // No need to try next k
363 : 0 : break;
364 : : }
365 : : }
366 : : }
367 : :
368 : : // GCRM is 0 based, convert vertex indices from 0 to 1 based
369 [ # # ]: 0 : for( std::size_t idx = 0; idx < vertices_on_local_cells.size(); idx++ )
370 [ # # ]: 0 : vertices_on_local_cells[idx] += 1;
371 : :
372 : : // Create local vertices
373 : : EntityHandle start_vertex;
374 [ # # ][ # # ]: 0 : ErrorCode rval = create_local_vertices( vertices_on_local_cells, start_vertex );MB_CHK_SET_ERR( rval, "Failed to create local vertices for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
375 : :
376 : : // Create local edges (unless NO_EDGES read option is set)
377 [ # # ]: 0 : if( !noEdges )
378 : : {
379 [ # # ][ # # ]: 0 : rval = create_local_edges( start_vertex );MB_CHK_SET_ERR( rval, "Failed to create local edges for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
380 : : }
381 : :
382 : : // Create local cells, padded
383 [ # # ][ # # ]: 0 : rval = create_padded_local_cells( vertices_on_local_cells, start_vertex, faces );MB_CHK_SET_ERR( rval, "Failed to create padded local cells for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
384 : :
385 [ # # ]: 0 : if( createGatherSet )
386 : : {
387 : : EntityHandle gather_set;
388 [ # # ][ # # ]: 0 : rval = _readNC->readMeshIface->create_gather_set( gather_set );MB_CHK_SET_ERR( rval, "Failed to create gather set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
389 : :
390 : : // Create gather set vertices
391 : : EntityHandle start_gather_set_vertex;
392 [ # # ][ # # ]: 0 : rval = create_gather_set_vertices( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create gather set vertices for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
393 : :
394 : : // Create gather set edges (unless NO_EDGES read option is set)
395 [ # # ]: 0 : if( !noEdges )
396 : : {
397 [ # # ][ # # ]: 0 : rval = create_gather_set_edges( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create gather set edges for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
398 : : }
399 : :
400 : : // Create gather set cells with padding
401 [ # # ][ # # ]: 0 : rval = create_padded_gather_set_cells( gather_set, start_gather_set_vertex );MB_CHK_SET_ERR( rval, "Failed to create padded gather set cells for GCRM mesh" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
402 : : }
403 : :
404 : 0 : return MB_SUCCESS;
405 : : }
406 : :
407 : 0 : ErrorCode NCHelperGCRM::read_ucd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
408 : : std::vector< int >& tstep_nums )
409 : : {
410 : 0 : Interface*& mbImpl = _readNC->mbImpl;
411 : 0 : std::vector< int >& dimLens = _readNC->dimLens;
412 : 0 : bool& noEdges = _readNC->noEdges;
413 : 0 : DebugOutput& dbgOut = _readNC->dbgOut;
414 : :
415 : 0 : Range* range = NULL;
416 : :
417 : : // Get vertices
418 [ # # ]: 0 : Range verts;
419 [ # # ][ # # ]: 0 : ErrorCode rval = mbImpl->get_entities_by_dimension( _fileSet, 0, verts );MB_CHK_SET_ERR( rval, "Trouble getting vertices in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
420 [ # # ][ # # ]: 0 : assert( "Should only have a single vertex subrange, since they were read in one shot" && verts.psize() == 1 );
421 : :
422 : : // Get edges
423 [ # # ]: 0 : Range edges;
424 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 1, edges );MB_CHK_SET_ERR( rval, "Trouble getting edges in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
425 : :
426 : : // Get faces
427 [ # # ]: 0 : Range faces;
428 [ # # ][ # # ]: 0 : rval = mbImpl->get_entities_by_dimension( _fileSet, 2, faces );MB_CHK_SET_ERR( rval, "Trouble getting faces in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
429 [ # # ][ # # ]: 0 : assert( "Should only have a single face subrange, since they were read in one shot" && faces.psize() == 1 );
430 : :
431 : : #ifdef MOAB_HAVE_MPI
432 : 0 : bool& isParallel = _readNC->isParallel;
433 [ # # ]: 0 : if( isParallel )
434 : : {
435 : 0 : ParallelComm*& myPcomm = _readNC->myPcomm;
436 [ # # ][ # # ]: 0 : rval = myPcomm->filter_pstatus( faces, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &facesOwned );MB_CHK_SET_ERR( rval, "Trouble getting owned faces in current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
437 : : }
438 : : else
439 [ # # ]: 0 : facesOwned = faces; // not running in parallel, but still with MPI
440 : : #else
441 : : facesOwned = faces;
442 : : #endif
443 : :
444 [ # # ]: 0 : for( unsigned int i = 0; i < vdatas.size(); i++ )
445 : : {
446 : : // Skip edge variables, if specified by the read options
447 [ # # ][ # # ]: 0 : if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
[ # # ][ # # ]
448 : :
449 : : // Support non-set variables with 3 dimensions like (time, cells, layers), or
450 : : // 2 dimensions like (time, cells)
451 [ # # ][ # # ]: 0 : assert( 3 == vdatas[i].varDims.size() || 2 == vdatas[i].varDims.size() );
[ # # ][ # # ]
452 : :
453 : : // For a non-set variable, time should be the first dimension
454 [ # # ][ # # ]: 0 : assert( tDim == vdatas[i].varDims[0] );
[ # # ]
455 : :
456 : : // Set up readStarts and readCounts
457 [ # # ][ # # ]: 0 : vdatas[i].readStarts.resize( 3 );
458 [ # # ][ # # ]: 0 : vdatas[i].readCounts.resize( 3 );
459 : :
460 : : // First: Time
461 [ # # ][ # # ]: 0 : vdatas[i].readStarts[0] = 0; // This value is timestep dependent, will be set later
462 [ # # ][ # # ]: 0 : vdatas[i].readCounts[0] = 1;
463 : :
464 : : // Next: nVertices / nCells / nEdges
465 [ # # ]: 0 : switch( vdatas[i].entLoc )
[ # # # # ]
466 : : {
467 : : case ReadNC::ENTLOCVERT:
468 : : // Vertices
469 : : // Start from the first localGidVerts
470 : : // Actually, this will be reset later on in a loop
471 [ # # ][ # # ]: 0 : vdatas[i].readStarts[1] = localGidVerts[0] - 1;
[ # # ]
472 [ # # ][ # # ]: 0 : vdatas[i].readCounts[1] = nLocalVertices;
473 : 0 : range = &verts;
474 : 0 : break;
475 : : case ReadNC::ENTLOCFACE:
476 : : // Faces
477 : : // Start from the first localGidCells
478 : : // Actually, this will be reset later on in a loop
479 [ # # ][ # # ]: 0 : vdatas[i].readStarts[1] = localGidCells[0] - 1;
[ # # ]
480 [ # # ][ # # ]: 0 : vdatas[i].readCounts[1] = nLocalCells;
481 : 0 : range = &facesOwned;
482 : 0 : break;
483 : : case ReadNC::ENTLOCEDGE:
484 : : // Edges
485 : : // Start from the first localGidEdges
486 : : // Actually, this will be reset later on in a loop
487 [ # # ][ # # ]: 0 : vdatas[i].readStarts[1] = localGidEdges[0] - 1;
[ # # ]
488 [ # # ][ # # ]: 0 : vdatas[i].readCounts[1] = nLocalEdges;
489 : 0 : range = &edges;
490 : 0 : break;
491 : : default:
492 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
493 : : }
494 : :
495 : : // Finally: layers or other optional levels, it is possible that there is no
496 : : // level dimension (numLev is 0) for this non-set variable
497 [ # # ][ # # ]: 0 : if( vdatas[i].numLev < 1 ) vdatas[i].numLev = 1;
[ # # ]
498 [ # # ][ # # ]: 0 : vdatas[i].readStarts[2] = 0;
499 [ # # ][ # # ]: 0 : vdatas[i].readCounts[2] = vdatas[i].numLev;
[ # # ]
500 : :
501 : : // Get variable size
502 [ # # ]: 0 : vdatas[i].sz = 1;
503 [ # # ]: 0 : for( std::size_t idx = 0; idx != 3; idx++ )
504 [ # # ][ # # ]: 0 : vdatas[i].sz *= vdatas[i].readCounts[idx];
[ # # ]
505 : :
506 [ # # ]: 0 : for( unsigned int t = 0; t < tstep_nums.size(); t++ )
507 : : {
508 [ # # ][ # # ]: 0 : dbgOut.tprintf( 2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t] );
[ # # ]
509 : :
510 [ # # ][ # # ]: 0 : if( tstep_nums[t] >= dimLens[tDim] )
[ # # ]
511 [ # # ][ # # ]: 0 : { MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t] ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
512 : :
513 : : // Get the tag to read into
514 [ # # ][ # # ]: 0 : if( !vdatas[i].varTags[t] )
[ # # ]
515 : : {
516 [ # # ][ # # ]: 0 : rval = get_tag_to_nonset( vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev );MB_CHK_SET_ERR( rval, "Trouble getting tag for variable " << vdatas[i].varName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
517 : : }
518 : :
519 : : // Get ptr to tag space
520 [ # # ][ # # ]: 0 : assert( 1 == range->psize() );
521 : : void* data;
522 : : int count;
523 [ # # ][ # # ]: 0 : rval = mbImpl->tag_iterate( vdatas[i].varTags[t], range->begin(), range->end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate tag for variable " << vdatas[i].varName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
524 [ # # ][ # # ]: 0 : assert( (unsigned)count == range->size() );
525 [ # # ][ # # ]: 0 : vdatas[i].varDatas[t] = data;
526 : : }
527 : : }
528 : :
529 : 0 : return rval;
530 : : }
531 : :
532 : : #ifdef MOAB_HAVE_PNETCDF
533 : : ErrorCode NCHelperGCRM::read_ucd_variables_to_nonset_async( std::vector< ReadNC::VarData >& vdatas,
534 : : std::vector< int >& tstep_nums )
535 : : {
536 : : bool& noEdges = _readNC->noEdges;
537 : : DebugOutput& dbgOut = _readNC->dbgOut;
538 : :
539 : : ErrorCode rval = read_ucd_variables_to_nonset_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read non-set variables" );
540 : :
541 : : // Finally, read into that space
542 : : int success;
543 : : Range* pLocalGid = NULL;
544 : :
545 : : for( unsigned int i = 0; i < vdatas.size(); i++ )
546 : : {
547 : : // Skip edge variables, if specified by the read options
548 : : if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
549 : :
550 : : switch( vdatas[i].entLoc )
551 : : {
552 : : case ReadNC::ENTLOCVERT:
553 : : pLocalGid = &localGidVerts;
554 : : break;
555 : : case ReadNC::ENTLOCFACE:
556 : : pLocalGid = &localGidCells;
557 : : break;
558 : : case ReadNC::ENTLOCEDGE:
559 : : pLocalGid = &localGidEdges;
560 : : break;
561 : : default:
562 : : MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
563 : : }
564 : :
565 : : std::size_t sz = vdatas[i].sz;
566 : :
567 : : for( unsigned int t = 0; t < tstep_nums.size(); t++ )
568 : : {
569 : : // We will synchronize all these reads with the other processors,
570 : : // so the wait will be inside this double loop; is it too much?
571 : : size_t nb_reads = pLocalGid->psize();
572 : : std::vector< int > requests( nb_reads ), statuss( nb_reads );
573 : : size_t idxReq = 0;
574 : :
575 : : // Set readStart for each timestep along time dimension
576 : : vdatas[i].readStarts[0] = tstep_nums[t];
577 : :
578 : : switch( vdatas[i].varDataType )
579 : : {
580 : : case NC_FLOAT:
581 : : case NC_DOUBLE: {
582 : : // Read float as double
583 : : std::vector< double > tmpdoubledata( sz );
584 : :
585 : : // In the case of ucd mesh, and on multiple proc,
586 : : // we need to read as many times as subranges we have in the
587 : : // localGid range;
588 : : // basically, we have to give a different point
589 : : // for data to start, for every subrange :(
590 : : size_t indexInDoubleArray = 0;
591 : : size_t ic = 0;
592 : : for( Range::pair_iterator pair_iter = pLocalGid->pair_begin(); pair_iter != pLocalGid->pair_end();
593 : : ++pair_iter, ic++ )
594 : : {
595 : : EntityHandle starth = pair_iter->first;
596 : : EntityHandle endh = pair_iter->second; // inclusive
597 : : vdatas[i].readStarts[1] = ( NCDF_SIZE )( starth - 1 );
598 : : vdatas[i].readCounts[1] = ( NCDF_SIZE )( endh - starth + 1 );
599 : :
600 : : // Do a partial read, in each subrange
601 : : // wait outside this loop
602 : : success =
603 : : NCFUNCREQG( _vara_double )( _fileId, vdatas[i].varId, &( vdatas[i].readStarts[0] ),
604 : : &( vdatas[i].readCounts[0] ),
605 : : &( tmpdoubledata[indexInDoubleArray] ), &requests[idxReq++] );
606 : : if( success )
607 : : MB_SET_ERR( MB_FAILURE,
608 : : "Failed to read double data in a loop for variable " << vdatas[i].varName );
609 : : // We need to increment the index in double array for the
610 : : // next subrange
611 : : indexInDoubleArray += ( endh - starth + 1 ) * 1 * vdatas[i].numLev;
612 : : }
613 : : assert( ic == pLocalGid->psize() );
614 : :
615 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
616 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
617 : :
618 : : void* data = vdatas[i].varDatas[t];
619 : : for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
620 : : ( (double*)data )[idx] = tmpdoubledata[idx];
621 : :
622 : : break;
623 : : }
624 : : default:
625 : : MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
626 : : }
627 : : }
628 : : }
629 : :
630 : : // Debug output, if requested
631 : : if( 1 == dbgOut.get_verbosity() )
632 : : {
633 : : dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
634 : : for( unsigned int i = 1; i < vdatas.size(); i++ )
635 : : dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
636 : : dbgOut.tprintf( 1, "\n" );
637 : : }
638 : :
639 : : return rval;
640 : : }
641 : : #else
642 : 0 : ErrorCode NCHelperGCRM::read_ucd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas,
643 : : std::vector< int >& tstep_nums )
644 : : {
645 : 0 : bool& noEdges = _readNC->noEdges;
646 : 0 : DebugOutput& dbgOut = _readNC->dbgOut;
647 : :
648 [ # # ][ # # ]: 0 : ErrorCode rval = read_ucd_variables_to_nonset_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read non-set variables" );
[ # # ][ # # ]
[ # # ][ # # ]
649 : :
650 : : // Finally, read into that space
651 : : int success;
652 : 0 : Range* pLocalGid = NULL;
653 : :
654 [ # # ]: 0 : for( unsigned int i = 0; i < vdatas.size(); i++ )
655 : : {
656 : : // Skip edge variables, if specified by the read options
657 [ # # ][ # # ]: 0 : if( noEdges && vdatas[i].entLoc == ReadNC::ENTLOCEDGE ) continue;
[ # # ]
658 : :
659 [ # # # # ]: 0 : switch( vdatas[i].entLoc )
660 : : {
661 : : case ReadNC::ENTLOCVERT:
662 : 0 : pLocalGid = &localGidVerts;
663 : 0 : break;
664 : : case ReadNC::ENTLOCFACE:
665 : 0 : pLocalGid = &localGidCells;
666 : 0 : break;
667 : : case ReadNC::ENTLOCEDGE:
668 : 0 : pLocalGid = &localGidEdges;
669 : 0 : break;
670 : : default:
671 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
672 : : }
673 : :
674 : 0 : std::size_t sz = vdatas[i].sz;
675 : :
676 [ # # ]: 0 : for( unsigned int t = 0; t < tstep_nums.size(); t++ )
677 : : {
678 : : // Set readStart for each timestep along time dimension
679 : 0 : vdatas[i].readStarts[0] = tstep_nums[t];
680 : :
681 [ # # ]: 0 : switch( vdatas[i].varDataType )
682 : : {
683 : : case NC_FLOAT:
684 : : case NC_DOUBLE: {
685 : : // Read float as double
686 [ # # ]: 0 : std::vector< double > tmpdoubledata( sz );
687 : :
688 : : // In the case of ucd mesh, and on multiple proc,
689 : : // we need to read as many times as subranges we have in the
690 : : // localGid range;
691 : : // basically, we have to give a different point
692 : : // for data to start, for every subrange :(
693 : 0 : size_t indexInDoubleArray = 0;
694 : 0 : size_t ic = 0;
695 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = pLocalGid->pair_begin(); pair_iter != pLocalGid->pair_end();
[ # # ][ # # ]
[ # # ]
696 : : ++pair_iter, ic++ )
697 : : {
698 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
699 [ # # ]: 0 : EntityHandle endh = pair_iter->second; // Inclusive
700 [ # # ][ # # ]: 0 : vdatas[i].readStarts[1] = ( NCDF_SIZE )( starth - 1 );
701 [ # # ][ # # ]: 0 : vdatas[i].readCounts[1] = ( NCDF_SIZE )( endh - starth + 1 );
702 : :
703 [ # # ][ # # ]: 0 : success = NCFUNCAG( _vara_double )( _fileId, vdatas[i].varId, &( vdatas[i].readStarts[0] ),
[ # # ]
704 [ # # ][ # # ]: 0 : &( vdatas[i].readCounts[0] ),
705 [ # # ][ # # ]: 0 : &( tmpdoubledata[indexInDoubleArray] ) );
706 [ # # ]: 0 : if( success )
707 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
708 : : "Failed to read double data in a loop for variable " << vdatas[i].varName );
709 : : // We need to increment the index in double array for the
710 : : // next subrange
711 [ # # ]: 0 : indexInDoubleArray += ( endh - starth + 1 ) * 1 * vdatas[i].numLev;
712 : : }
713 [ # # ][ # # ]: 0 : assert( ic == pLocalGid->psize() );
714 : :
715 [ # # ][ # # ]: 0 : void* data = vdatas[i].varDatas[t];
716 [ # # ]: 0 : for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
717 [ # # ]: 0 : ( (double*)data )[idx] = tmpdoubledata[idx];
718 : :
719 [ # # ]: 0 : break;
720 : : }
721 : : default:
722 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
723 : : }
724 : : }
725 : : }
726 : :
727 : : // Debug output, if requested
728 [ # # ]: 0 : if( 1 == dbgOut.get_verbosity() )
729 : : {
730 [ # # ][ # # ]: 0 : dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
731 [ # # ]: 0 : for( unsigned int i = 1; i < vdatas.size(); i++ )
732 : 0 : dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
733 : 0 : dbgOut.tprintf( 1, "\n" );
734 : : }
735 : :
736 : 0 : return rval;
737 : : }
738 : : #endif
739 : :
740 : : #ifdef MOAB_HAVE_MPI
741 : 0 : ErrorCode NCHelperGCRM::redistribute_local_cells( int start_cell_idx )
742 : : {
743 : : // If possible, apply Zoltan partition
744 : : #ifdef MOAB_HAVE_ZOLTAN
745 : : if( _readNC->partMethod == ScdParData::RCBZOLTAN )
746 : : {
747 : : // Read lat/lon coordinates of cell centers, then convert spherical to
748 : : // Cartesian, and use them as input to Zoltan partition
749 : : int xCellVarId;
750 : : int success = NCFUNC( inq_varid )( _fileId, "grid_center_lat", &xCellVarId );
751 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_center_lat" );
752 : : std::vector< double > xCell( nLocalCells );
753 : : NCDF_SIZE read_start = static_cast< NCDF_SIZE >( start_cell_idx - 1 );
754 : : NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nLocalCells );
755 : : success = NCFUNCAG( _vara_double )( _fileId, xCellVarId, &read_start, &read_count, &xCell[0] );
756 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_center_lat data" );
757 : :
758 : : // Read y coordinates of cell centers
759 : : int yCellVarId;
760 : : success = NCFUNC( inq_varid )( _fileId, "grid_center_lon", &yCellVarId );
761 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_center_lon" );
762 : : std::vector< double > yCell( nLocalCells );
763 : : success = NCFUNCAG( _vara_double )( _fileId, yCellVarId, &read_start, &read_count, &yCell[0] );
764 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_center_lon data" );
765 : :
766 : : // Convert lon/lat/rad to x/y/z
767 : : std::vector< double > zCell( nLocalCells );
768 : : double rad = 8000.0; // This is just a approximate radius
769 : : for( int i = 0; i < nLocalCells; i++ )
770 : : {
771 : : double cosphi = cos( xCell[i] );
772 : : double zmult = sin( xCell[i] );
773 : : double xmult = cosphi * cos( yCell[i] );
774 : : double ymult = cosphi * sin( yCell[i] );
775 : : xCell[i] = rad * xmult;
776 : : yCell[i] = rad * ymult;
777 : : zCell[i] = rad * zmult;
778 : : }
779 : :
780 : : // Zoltan partition using RCB; maybe more studies would be good, as to which partition
781 : : // is better
782 : : Interface*& mbImpl = _readNC->mbImpl;
783 : : DebugOutput& dbgOut = _readNC->dbgOut;
784 : : ZoltanPartitioner* mbZTool = new ZoltanPartitioner( mbImpl, false, 0, NULL );
785 : : ErrorCode rval = mbZTool->repartition( xCell, yCell, zCell, start_cell_idx, "RCB", localGidCells );MB_CHK_SET_ERR( rval, "Error in Zoltan partitioning" );
786 : : delete mbZTool;
787 : :
788 : : dbgOut.tprintf( 1, "After Zoltan partitioning, localGidCells.psize() = %d\n", (int)localGidCells.psize() );
789 : : dbgOut.tprintf( 1, " localGidCells.size() = %d\n", (int)localGidCells.size() );
790 : :
791 : : // This is important: local cells are now redistributed, so nLocalCells might be different!
792 : : nLocalCells = localGidCells.size();
793 : :
794 : : return MB_SUCCESS;
795 : : }
796 : : #endif
797 : :
798 : : // By default, apply trivial partition
799 : 0 : localGidCells.insert( start_cell_idx, start_cell_idx + nLocalCells - 1 );
800 : :
801 : 0 : return MB_SUCCESS;
802 : : }
803 : : #endif
804 : :
805 : 0 : ErrorCode NCHelperGCRM::create_local_vertices( const std::vector< int >& vertices_on_local_cells,
806 : : EntityHandle& start_vertex )
807 : : {
808 : 0 : Interface*& mbImpl = _readNC->mbImpl;
809 : 0 : Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
810 : 0 : const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
811 : 0 : DebugOutput& dbgOut = _readNC->dbgOut;
812 : 0 : std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
813 : :
814 : : // Make a copy of vertices_on_local_cells for sorting (keep original one to set cell
815 : : // connectivity later)
816 [ # # ]: 0 : std::vector< int > vertices_on_local_cells_sorted( vertices_on_local_cells );
817 [ # # ]: 0 : std::sort( vertices_on_local_cells_sorted.begin(), vertices_on_local_cells_sorted.end() );
818 : : std::copy( vertices_on_local_cells_sorted.rbegin(), vertices_on_local_cells_sorted.rend(),
819 [ # # ][ # # ]: 0 : range_inserter( localGidVerts ) );
820 [ # # ]: 0 : nLocalVertices = localGidVerts.size();
821 : :
822 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidVerts.psize() = %d\n", (int)localGidVerts.psize() );
823 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidVerts.size() = %d\n", (int)localGidVerts.size() );
824 : :
825 : : // Create local vertices
826 [ # # ]: 0 : std::vector< double* > arrays;
827 : : ErrorCode rval =
828 : : _readNC->readMeshIface->get_node_coords( 3, nLocalVertices, 0, start_vertex, arrays,
829 : : // Might have to create gather mesh later
830 [ # # ][ # # ]: 0 : ( createGatherSet ? nLocalVertices + nVertices : nLocalVertices ) );MB_CHK_SET_ERR( rval, "Failed to create local vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
831 : :
832 : : // Add local vertices to current file set
833 [ # # ]: 0 : Range local_verts_range( start_vertex, start_vertex + nLocalVertices - 1 );
834 [ # # ][ # # ]: 0 : rval = _readNC->mbImpl->add_entities( _fileSet, local_verts_range );MB_CHK_SET_ERR( rval, "Failed to add local vertices to current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
835 : :
836 : : // Get ptr to GID memory for local vertices
837 : 0 : int count = 0;
838 : 0 : void* data = NULL;
839 [ # # ][ # # ]: 0 : rval = mbImpl->tag_iterate( mGlobalIdTag, local_verts_range.begin(), local_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
840 [ # # ]: 0 : assert( count == nLocalVertices );
841 : 0 : int* gid_data = (int*)data;
842 [ # # ][ # # ]: 0 : std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
[ # # ]
843 : :
844 : : // Duplicate GID data, which will be used to resolve sharing
845 [ # # ]: 0 : if( mpFileIdTag )
846 : : {
847 [ # # ][ # # ]: 0 : rval = mbImpl->tag_iterate( *mpFileIdTag, local_verts_range.begin(), local_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate file id tag on local vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
848 [ # # ]: 0 : assert( count == nLocalVertices );
849 : 0 : int bytes_per_tag = 4;
850 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag );MB_CHK_SET_ERR( rval, "can't get number of bytes for file id tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
851 [ # # ]: 0 : if( 4 == bytes_per_tag )
852 : : {
853 : 0 : gid_data = (int*)data;
854 [ # # ][ # # ]: 0 : std::copy( localGidVerts.begin(), localGidVerts.end(), gid_data );
[ # # ]
855 : : }
856 [ # # ]: 0 : else if( 8 == bytes_per_tag )
857 : : { // Should be a handle tag on 64 bit machine?
858 : 0 : long* handle_tag_data = (long*)data;
859 [ # # ][ # # ]: 0 : std::copy( localGidVerts.begin(), localGidVerts.end(), handle_tag_data );
[ # # ]
860 : : }
861 : : }
862 : :
863 : : #ifdef MOAB_HAVE_PNETCDF
864 : : size_t nb_reads = localGidVerts.psize();
865 : : std::vector< int > requests( nb_reads );
866 : : std::vector< int > statuss( nb_reads );
867 : : size_t idxReq = 0;
868 : : #endif
869 : :
870 : : // Store lev values in levVals
871 [ # # ]: 0 : std::map< std::string, ReadNC::VarData >::iterator vmit;
872 [ # # ][ # # ]: 0 : if( ( vmit = varInfo.find( "layers" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# ]
873 : : {
874 [ # # ][ # # ]: 0 : rval = read_coordinate( "layers", 0, nLevels - 1, levVals );MB_CHK_SET_ERR( rval, "Trouble reading 'layers' variable" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
875 : : }
876 [ # # ][ # # ]: 0 : else if( ( vmit = varInfo.find( "interfaces" ) ) != varInfo.end() && ( *vmit ).second.varDims.size() == 1 )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# ]
877 : : {
878 [ # # ][ # # ]: 0 : rval = read_coordinate( "interfaces", 0, nLevels - 1, levVals );MB_CHK_SET_ERR( rval, "Trouble reading 'interfaces' variable" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
879 : : }
880 : : else
881 : : {
882 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Couldn't find 'layers' or 'interfaces' variable" );
[ # # ][ # # ]
[ # # ]
883 : : }
884 : :
885 : : // Decide whether down is positive
886 : 0 : char posval[10] = { 0 };
887 [ # # ][ # # ]: 0 : int success = NCFUNC( get_att_text )( _fileId, ( *vmit ).second.varId, "positive", posval );
888 [ # # ][ # # ]: 0 : if( 0 == success && !strncmp( posval, "down", 4 ) )
889 : : {
890 [ # # ][ # # ]: 0 : for( std::vector< double >::iterator dvit = levVals.begin(); dvit != levVals.end(); ++dvit )
[ # # ]
891 [ # # ]: 0 : ( *dvit ) *= -1.0;
892 : : }
893 : :
894 : : // Read x coordinates for local vertices
895 [ # # ]: 0 : double* xptr = arrays[0];
896 : : int xVertexVarId;
897 [ # # ]: 0 : success = NCFUNC( inq_varid )( _fileId, "grid_corner_lon", &xVertexVarId );
898 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_corner_lon" );
[ # # ][ # # ]
[ # # ][ # # ]
899 : 0 : size_t indexInArray = 0;
900 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = localGidVerts.pair_begin(); pair_iter != localGidVerts.pair_end();
[ # # ][ # # ]
[ # # ]
901 : : ++pair_iter )
902 : : {
903 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
904 [ # # ]: 0 : EntityHandle endh = pair_iter->second;
905 : 0 : NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
906 : 0 : NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
907 : :
908 : : // Do a partial read in each subrange
909 : : #ifdef MOAB_HAVE_PNETCDF
910 : : success = NCFUNCREQG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, &( xptr[indexInArray] ),
911 : : &requests[idxReq++] );
912 : : #else
913 [ # # ]: 0 : success = NCFUNCAG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, &( xptr[indexInArray] ) );
914 : : #endif
915 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lon data in a loop" );
[ # # ][ # # ]
[ # # ][ # # ]
916 : :
917 : : // Increment the index for next subrange
918 : 0 : indexInArray += ( endh - starth + 1 );
919 : : }
920 : :
921 : : #ifdef MOAB_HAVE_PNETCDF
922 : : // Wait outside the loop
923 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
924 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
925 : : #endif
926 : :
927 : : // Read y coordinates for local vertices
928 [ # # ]: 0 : double* yptr = arrays[1];
929 : : int yVertexVarId;
930 [ # # ]: 0 : success = NCFUNC( inq_varid )( _fileId, "grid_corner_lat", &yVertexVarId );
931 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_corner_lat" );
[ # # ][ # # ]
[ # # ][ # # ]
932 : : #ifdef MOAB_HAVE_PNETCDF
933 : : idxReq = 0;
934 : : #endif
935 : 0 : indexInArray = 0;
936 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = localGidVerts.pair_begin(); pair_iter != localGidVerts.pair_end();
[ # # ][ # # ]
[ # # ]
937 : : ++pair_iter )
938 : : {
939 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
940 [ # # ]: 0 : EntityHandle endh = pair_iter->second;
941 : 0 : NCDF_SIZE read_start = ( NCDF_SIZE )( starth - 1 );
942 : 0 : NCDF_SIZE read_count = ( NCDF_SIZE )( endh - starth + 1 );
943 : :
944 : : // Do a partial read in each subrange
945 : : #ifdef MOAB_HAVE_PNETCDF
946 : : success = NCFUNCREQG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, &( yptr[indexInArray] ),
947 : : &requests[idxReq++] );
948 : : #else
949 [ # # ]: 0 : success = NCFUNCAG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, &( yptr[indexInArray] ) );
950 : : #endif
951 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lat data in a loop" );
[ # # ][ # # ]
[ # # ][ # # ]
952 : :
953 : : // Increment the index for next subrange
954 : 0 : indexInArray += ( endh - starth + 1 );
955 : : }
956 : :
957 : : #ifdef MOAB_HAVE_PNETCDF
958 : : // Wait outside the loop
959 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
960 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
961 : : #endif
962 : :
963 : : // Convert lon/lat/rad to x/y/z
964 [ # # ]: 0 : double* zptr = arrays[2];
965 [ # # ]: 0 : double rad = 8000.0 + levVals[0];
966 [ # # ]: 0 : for( int i = 0; i < nLocalVertices; i++ )
967 : : {
968 : 0 : double cosphi = cos( yptr[i] );
969 : 0 : double zmult = sin( yptr[i] );
970 : 0 : double xmult = cosphi * cos( xptr[i] );
971 : 0 : double ymult = cosphi * sin( xptr[i] );
972 : 0 : xptr[i] = rad * xmult;
973 : 0 : yptr[i] = rad * ymult;
974 : 0 : zptr[i] = rad * zmult;
975 : : }
976 : :
977 : 0 : return MB_SUCCESS;
978 : : }
979 : :
980 : 0 : ErrorCode NCHelperGCRM::create_local_edges( EntityHandle start_vertex )
981 : : {
982 : 0 : Interface*& mbImpl = _readNC->mbImpl;
983 : 0 : Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
984 : 0 : DebugOutput& dbgOut = _readNC->dbgOut;
985 : :
986 : : // Read edges on each local cell, to get localGidEdges
987 : : int edgesOnCellVarId;
988 [ # # ]: 0 : int success = NCFUNC( inq_varid )( _fileId, "cell_edges", &edgesOnCellVarId );
989 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of cell_edges" );
[ # # ][ # # ]
[ # # ][ # # ]
990 : :
991 [ # # ]: 0 : std::vector< int > edges_on_local_cells( nLocalCells * EDGES_PER_CELL );
992 [ # # ]: 0 : dbgOut.tprintf( 1, " edges_on_local_cells.size() = %d\n", (int)edges_on_local_cells.size() );
993 : :
994 : : #ifdef MOAB_HAVE_PNETCDF
995 : : size_t nb_reads = localGidCells.psize();
996 : : std::vector< int > requests( nb_reads );
997 : : std::vector< int > statuss( nb_reads );
998 : : size_t idxReq = 0;
999 : : #endif
1000 : 0 : size_t indexInArray = 0;
1001 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = localGidCells.pair_begin(); pair_iter != localGidCells.pair_end();
[ # # ][ # # ]
[ # # ]
1002 : : ++pair_iter )
1003 : : {
1004 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
1005 [ # # ]: 0 : EntityHandle endh = pair_iter->second;
1006 [ # # ]: 0 : dbgOut.tprintf( 1, " starth = %d\n", (int)starth );
1007 [ # # ]: 0 : dbgOut.tprintf( 1, " endh = %d\n", (int)endh );
1008 : 0 : NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
1009 : 0 : NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ),
1010 : 0 : static_cast< NCDF_SIZE >( EDGES_PER_CELL ) };
1011 : :
1012 : : // Do a partial read in each subrange
1013 : : #ifdef MOAB_HAVE_PNETCDF
1014 : : success = NCFUNCREQG( _vara_int )( _fileId, edgesOnCellVarId, read_starts, read_counts,
1015 : : &( edges_on_local_cells[indexInArray] ), &requests[idxReq++] );
1016 : : #else
1017 : : success = NCFUNCAG( _vara_int )( _fileId, edgesOnCellVarId, read_starts, read_counts,
1018 [ # # ][ # # ]: 0 : &( edges_on_local_cells[indexInArray] ) );
1019 : : #endif
1020 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read cell_edges data in a loop" );
[ # # ][ # # ]
[ # # ][ # # ]
1021 : :
1022 : : // Increment the index for next subrange
1023 : 0 : indexInArray += ( endh - starth + 1 ) * EDGES_PER_CELL;
1024 : : }
1025 : :
1026 : : #ifdef MOAB_HAVE_PNETCDF
1027 : : // Wait outside the loop
1028 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
1029 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
1030 : : #endif
1031 : :
1032 : : // GCRM is 0 based, convert edge indices from 0 to 1 based
1033 [ # # ]: 0 : for( std::size_t idx = 0; idx < edges_on_local_cells.size(); idx++ )
1034 [ # # ]: 0 : edges_on_local_cells[idx] += 1;
1035 : :
1036 : : // Collect local edges
1037 [ # # ]: 0 : std::sort( edges_on_local_cells.begin(), edges_on_local_cells.end() );
1038 [ # # ][ # # ]: 0 : std::copy( edges_on_local_cells.rbegin(), edges_on_local_cells.rend(), range_inserter( localGidEdges ) );
1039 [ # # ]: 0 : nLocalEdges = localGidEdges.size();
1040 : :
1041 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidEdges.psize() = %d\n", (int)localGidEdges.psize() );
1042 [ # # ][ # # ]: 0 : dbgOut.tprintf( 1, " localGidEdges.size() = %d\n", (int)localGidEdges.size() );
1043 : :
1044 : : // Create local edges
1045 : : EntityHandle start_edge;
1046 : 0 : EntityHandle* conn_arr_edges = NULL;
1047 : : ErrorCode rval =
1048 : : _readNC->readMeshIface->get_element_connect( nLocalEdges, 2, MBEDGE, 0, start_edge, conn_arr_edges,
1049 : : // Might have to create gather mesh later
1050 [ # # ][ # # ]: 0 : ( createGatherSet ? nLocalEdges + nEdges : nLocalEdges ) );MB_CHK_SET_ERR( rval, "Failed to create local edges" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1051 : :
1052 : : // Add local edges to current file set
1053 [ # # ]: 0 : Range local_edges_range( start_edge, start_edge + nLocalEdges - 1 );
1054 [ # # ][ # # ]: 0 : rval = _readNC->mbImpl->add_entities( _fileSet, local_edges_range );MB_CHK_SET_ERR( rval, "Failed to add local edges to current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1055 : :
1056 : : // Get ptr to GID memory for edges
1057 : 0 : int count = 0;
1058 : 0 : void* data = NULL;
1059 [ # # ][ # # ]: 0 : rval = mbImpl->tag_iterate( mGlobalIdTag, local_edges_range.begin(), local_edges_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local edges" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1060 [ # # ]: 0 : assert( count == nLocalEdges );
1061 : 0 : int* gid_data = (int*)data;
1062 [ # # ][ # # ]: 0 : std::copy( localGidEdges.begin(), localGidEdges.end(), gid_data );
[ # # ]
1063 : :
1064 : : int verticesOnEdgeVarId;
1065 : :
1066 : : // Read vertices on each local edge, to get edge connectivity
1067 [ # # ]: 0 : success = NCFUNC( inq_varid )( _fileId, "edge_corners", &verticesOnEdgeVarId );
1068 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of edge_corners" );
[ # # ][ # # ]
[ # # ][ # # ]
1069 : : // Utilize the memory storage pointed by conn_arr_edges
1070 : 0 : int* vertices_on_local_edges = (int*)conn_arr_edges;
1071 : : #ifdef MOAB_HAVE_PNETCDF
1072 : : nb_reads = localGidEdges.psize();
1073 : : requests.resize( nb_reads );
1074 : : statuss.resize( nb_reads );
1075 : : idxReq = 0;
1076 : : #endif
1077 : 0 : indexInArray = 0;
1078 [ # # ][ # # ]: 0 : for( Range::pair_iterator pair_iter = localGidEdges.pair_begin(); pair_iter != localGidEdges.pair_end();
[ # # ][ # # ]
[ # # ]
1079 : : ++pair_iter )
1080 : : {
1081 [ # # ]: 0 : EntityHandle starth = pair_iter->first;
1082 [ # # ]: 0 : EntityHandle endh = pair_iter->second;
1083 : 0 : NCDF_SIZE read_starts[2] = { static_cast< NCDF_SIZE >( starth - 1 ), 0 };
1084 : 0 : NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( endh - starth + 1 ), 2 };
1085 : :
1086 : : // Do a partial read in each subrange
1087 : : #ifdef MOAB_HAVE_PNETCDF
1088 : : success = NCFUNCREQG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts,
1089 : : &( vertices_on_local_edges[indexInArray] ), &requests[idxReq++] );
1090 : : #else
1091 : : success = NCFUNCAG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts,
1092 [ # # ]: 0 : &( vertices_on_local_edges[indexInArray] ) );
1093 : : #endif
1094 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read edge_corners data in a loop" );
[ # # ][ # # ]
[ # # ][ # # ]
1095 : :
1096 : : // Increment the index for next subrange
1097 : 0 : indexInArray += ( endh - starth + 1 ) * 2;
1098 : : }
1099 : :
1100 : : #ifdef MOAB_HAVE_PNETCDF
1101 : : // Wait outside the loop
1102 : : success = NCFUNC( wait_all )( _fileId, requests.size(), &requests[0], &statuss[0] );
1103 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed on wait_all" );
1104 : : #endif
1105 : :
1106 : : // Populate connectivity data for local edges
1107 : : // Convert in-place from int (stored in the first half) to EntityHandle
1108 : : // Reading backward is the trick
1109 [ # # ]: 0 : for( int edge_vert = nLocalEdges * 2 - 1; edge_vert >= 0; edge_vert-- )
1110 : : {
1111 : : // Note, indices stored in vertices_on_local_edges are 0 based
1112 : 0 : int global_vert_idx = vertices_on_local_edges[edge_vert] + 1; // Global vertex index, 1 based
1113 [ # # ]: 0 : int local_vert_idx = localGidVerts.index( global_vert_idx ); // Local vertex index, 0 based
1114 [ # # ]: 0 : assert( local_vert_idx != -1 );
1115 : 0 : conn_arr_edges[edge_vert] = start_vertex + local_vert_idx;
1116 : : }
1117 : :
1118 : 0 : return MB_SUCCESS;
1119 : : }
1120 : :
1121 : 0 : ErrorCode NCHelperGCRM::create_padded_local_cells( const std::vector< int >& vertices_on_local_cells,
1122 : : EntityHandle start_vertex, Range& faces )
1123 : : {
1124 : 0 : Interface*& mbImpl = _readNC->mbImpl;
1125 : 0 : Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
1126 : :
1127 : : // Create cells
1128 : : EntityHandle start_element;
1129 : 0 : EntityHandle* conn_arr_local_cells = NULL;
1130 : : ErrorCode rval =
1131 : : _readNC->readMeshIface->get_element_connect( nLocalCells, EDGES_PER_CELL, MBPOLYGON, 0, start_element,
1132 : : conn_arr_local_cells,
1133 : : // Might have to create gather mesh later
1134 [ # # ][ # # ]: 0 : ( createGatherSet ? nLocalCells + nCells : nLocalCells ) );MB_CHK_SET_ERR( rval, "Failed to create local cells" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1135 [ # # ]: 0 : faces.insert( start_element, start_element + nLocalCells - 1 );
1136 : :
1137 : : // Add local cells to current file set
1138 [ # # ]: 0 : Range local_cells_range( start_element, start_element + nLocalCells - 1 );
1139 [ # # ][ # # ]: 0 : rval = _readNC->mbImpl->add_entities( _fileSet, local_cells_range );MB_CHK_SET_ERR( rval, "Failed to add local cells to current file set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1140 : :
1141 : : // Get ptr to GID memory for local cells
1142 : 0 : int count = 0;
1143 : 0 : void* data = NULL;
1144 [ # # ][ # # ]: 0 : rval = mbImpl->tag_iterate( mGlobalIdTag, local_cells_range.begin(), local_cells_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on local cells" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1145 [ # # ]: 0 : assert( count == nLocalCells );
1146 : 0 : int* gid_data = (int*)data;
1147 [ # # ][ # # ]: 0 : std::copy( localGidCells.begin(), localGidCells.end(), gid_data );
[ # # ]
1148 : :
1149 : : // Set connectivity array with proper local vertices handles
1150 : : // vertices_on_local_cells array was already corrected to have
1151 : : // the last vertices repeated for pentagons, e.g. 122345 => 123455
1152 [ # # ]: 0 : for( int local_cell_idx = 0; local_cell_idx < nLocalCells; local_cell_idx++ )
1153 : : {
1154 [ # # ]: 0 : for( int i = 0; i < EDGES_PER_CELL; i++ )
1155 : : {
1156 : : // Note, indices stored in vertices_on_local_cells are 1 based
1157 : : EntityHandle global_vert_idx =
1158 [ # # ]: 0 : vertices_on_local_cells[local_cell_idx * EDGES_PER_CELL + i]; // Global vertex index, 1 based
1159 [ # # ]: 0 : int local_vert_idx = localGidVerts.index( global_vert_idx ); // Local vertex index, 0 based
1160 [ # # ]: 0 : assert( local_vert_idx != -1 );
1161 : 0 : conn_arr_local_cells[local_cell_idx * EDGES_PER_CELL + i] = start_vertex + local_vert_idx;
1162 : : }
1163 : : }
1164 : :
1165 : 0 : return MB_SUCCESS;
1166 : : }
1167 : :
1168 : 0 : ErrorCode NCHelperGCRM::create_gather_set_vertices( EntityHandle gather_set, EntityHandle& gather_set_start_vertex )
1169 : : {
1170 : 0 : Interface*& mbImpl = _readNC->mbImpl;
1171 : 0 : Tag& mGlobalIdTag = _readNC->mGlobalIdTag;
1172 : 0 : const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
1173 : :
1174 : : // Create gather set vertices
1175 [ # # ]: 0 : std::vector< double* > arrays;
1176 : : // Don't need to specify allocation number here, because we know enough vertices were created
1177 : : // before
1178 [ # # ][ # # ]: 0 : ErrorCode rval = _readNC->readMeshIface->get_node_coords( 3, nVertices, 0, gather_set_start_vertex, arrays );MB_CHK_SET_ERR( rval, "Failed to create gather set vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1179 : :
1180 : : // Add vertices to the gather set
1181 [ # # ]: 0 : Range gather_set_verts_range( gather_set_start_vertex, gather_set_start_vertex + nVertices - 1 );
1182 [ # # ][ # # ]: 0 : rval = mbImpl->add_entities( gather_set, gather_set_verts_range );MB_CHK_SET_ERR( rval, "Failed to add vertices to the gather set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1183 : :
1184 : : // Read x coordinates for gather set vertices
1185 [ # # ]: 0 : double* xptr = arrays[0];
1186 : : int xVertexVarId;
1187 [ # # ]: 0 : int success = NCFUNC( inq_varid )( _fileId, "grid_corner_lon", &xVertexVarId );
1188 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_corner_lon" );
[ # # ][ # # ]
[ # # ][ # # ]
1189 : 0 : NCDF_SIZE read_start = 0;
1190 : 0 : NCDF_SIZE read_count = static_cast< NCDF_SIZE >( nVertices );
1191 : : #ifdef MOAB_HAVE_PNETCDF
1192 : : // Enter independent I/O mode, since this read is only for the gather processor
1193 : : success = NCFUNC( begin_indep_data )( _fileId );
1194 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
1195 : : success = NCFUNCG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, xptr );
1196 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lon data" );
1197 : : success = NCFUNC( end_indep_data )( _fileId );
1198 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
1199 : : #else
1200 [ # # ]: 0 : success = NCFUNCG( _vara_double )( _fileId, xVertexVarId, &read_start, &read_count, xptr );
1201 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lon data" );
[ # # ][ # # ]
[ # # ][ # # ]
1202 : : #endif
1203 : :
1204 : : // Read y coordinates for gather set vertices
1205 [ # # ]: 0 : double* yptr = arrays[1];
1206 : : int yVertexVarId;
1207 [ # # ]: 0 : success = NCFUNC( inq_varid )( _fileId, "grid_corner_lat", &yVertexVarId );
1208 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of grid_corner_lat" );
[ # # ][ # # ]
[ # # ][ # # ]
1209 : : #ifdef MOAB_HAVE_PNETCDF
1210 : : // Enter independent I/O mode, since this read is only for the gather processor
1211 : : success = NCFUNC( begin_indep_data )( _fileId );
1212 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
1213 : : success = NCFUNCG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, yptr );
1214 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lat data" );
1215 : : success = NCFUNC( end_indep_data )( _fileId );
1216 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
1217 : : #else
1218 [ # # ]: 0 : success = NCFUNCG( _vara_double )( _fileId, yVertexVarId, &read_start, &read_count, yptr );
1219 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read grid_corner_lat data" );
[ # # ][ # # ]
[ # # ][ # # ]
1220 : : #endif
1221 : :
1222 : : // Convert lon/lat/rad to x/y/z
1223 [ # # ]: 0 : double* zptr = arrays[2];
1224 [ # # ]: 0 : double rad = 8000.0 + levVals[0];
1225 [ # # ]: 0 : for( int i = 0; i < nVertices; i++ )
1226 : : {
1227 : 0 : double cosphi = cos( yptr[i] );
1228 : 0 : double zmult = sin( yptr[i] );
1229 : 0 : double xmult = cosphi * cos( xptr[i] );
1230 : 0 : double ymult = cosphi * sin( xptr[i] );
1231 : 0 : xptr[i] = rad * xmult;
1232 : 0 : yptr[i] = rad * ymult;
1233 : 0 : zptr[i] = rad * zmult;
1234 : : }
1235 : :
1236 : : // Get ptr to GID memory for gather set vertices
1237 : 0 : int count = 0;
1238 : 0 : void* data = NULL;
1239 : : rval =
1240 [ # # ][ # # ]: 0 : mbImpl->tag_iterate( mGlobalIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global id tag on gather set vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1241 [ # # ]: 0 : assert( count == nVertices );
1242 : 0 : int* gid_data = (int*)data;
1243 [ # # ]: 0 : for( int j = 1; j <= nVertices; j++ )
1244 : 0 : gid_data[j - 1] = j;
1245 : :
1246 : : // Set the file id tag too, it should be bigger something not interfering with global id
1247 [ # # ]: 0 : if( mpFileIdTag )
1248 : : {
1249 : : rval = mbImpl->tag_iterate( *mpFileIdTag, gather_set_verts_range.begin(), gather_set_verts_range.end(), count,
1250 [ # # ][ # # ]: 0 : data );MB_CHK_SET_ERR( rval, "Failed to iterate file id tag on gather set vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1251 [ # # ]: 0 : assert( count == nVertices );
1252 : 0 : int bytes_per_tag = 4;
1253 [ # # ][ # # ]: 0 : rval = mbImpl->tag_get_bytes( *mpFileIdTag, bytes_per_tag );MB_CHK_SET_ERR( rval, "Can't get number of bytes for file id tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1254 [ # # ]: 0 : if( 4 == bytes_per_tag )
1255 : : {
1256 : 0 : gid_data = (int*)data;
1257 [ # # ]: 0 : for( int j = 1; j <= nVertices; j++ )
1258 : 0 : gid_data[j - 1] = nVertices + j; // Bigger than global id tag
1259 : : }
1260 [ # # ]: 0 : else if( 8 == bytes_per_tag )
1261 : : { // Should be a handle tag on 64 bit machine?
1262 : 0 : long* handle_tag_data = (long*)data;
1263 [ # # ]: 0 : for( int j = 1; j <= nVertices; j++ )
1264 : 0 : handle_tag_data[j - 1] = nVertices + j; // Bigger than global id tag
1265 : : }
1266 : : }
1267 : :
1268 : 0 : return MB_SUCCESS;
1269 : : }
1270 : :
1271 : 0 : ErrorCode NCHelperGCRM::create_gather_set_edges( EntityHandle gather_set, EntityHandle gather_set_start_vertex )
1272 : : {
1273 : 0 : Interface*& mbImpl = _readNC->mbImpl;
1274 : :
1275 : : // Create gather set edges
1276 : : EntityHandle start_edge;
1277 : 0 : EntityHandle* conn_arr_gather_set_edges = NULL;
1278 : : // Don't need to specify allocation number here, because we know enough edges were created
1279 : : // before
1280 : : ErrorCode rval =
1281 [ # # ][ # # ]: 0 : _readNC->readMeshIface->get_element_connect( nEdges, 2, MBEDGE, 0, start_edge, conn_arr_gather_set_edges );MB_CHK_SET_ERR( rval, "Failed to create gather set edges" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1282 : :
1283 : : // Add edges to the gather set
1284 [ # # ]: 0 : Range gather_set_edges_range( start_edge, start_edge + nEdges - 1 );
1285 [ # # ][ # # ]: 0 : rval = mbImpl->add_entities( gather_set, gather_set_edges_range );MB_CHK_SET_ERR( rval, "Failed to add edges to the gather set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1286 : :
1287 : : // Read vertices on each edge
1288 : : int verticesOnEdgeVarId;
1289 [ # # ]: 0 : int success = NCFUNC( inq_varid )( _fileId, "edge_corners", &verticesOnEdgeVarId );
1290 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of edge_corners" );
[ # # ][ # # ]
[ # # ][ # # ]
1291 : : // Utilize the memory storage pointed by conn_arr_gather_set_edges
1292 : 0 : int* vertices_on_gather_set_edges = (int*)conn_arr_gather_set_edges;
1293 : 0 : NCDF_SIZE read_starts[2] = { 0, 0 };
1294 : 0 : NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( nEdges ), 2 };
1295 : : #ifdef MOAB_HAVE_PNETCDF
1296 : : // Enter independent I/O mode, since this read is only for the gather processor
1297 : : success = NCFUNC( begin_indep_data )( _fileId );
1298 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
1299 : : success =
1300 : : NCFUNCG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges );
1301 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read edge_corners data" );
1302 : : success = NCFUNC( end_indep_data )( _fileId );
1303 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
1304 : : #else
1305 : : success =
1306 [ # # ]: 0 : NCFUNCG( _vara_int )( _fileId, verticesOnEdgeVarId, read_starts, read_counts, vertices_on_gather_set_edges );
1307 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read edge_corners data" );
[ # # ][ # # ]
[ # # ][ # # ]
1308 : : #endif
1309 : :
1310 : : // Populate connectivity data for gather set edges
1311 : : // Convert in-place from int (stored in the first half) to EntityHandle
1312 : : // Reading backward is the trick
1313 [ # # ]: 0 : for( int edge_vert = nEdges * 2 - 1; edge_vert >= 0; edge_vert-- )
1314 : : {
1315 : : // Note, indices stored in vertices_on_gather_set_edges are 0 based
1316 : 0 : int gather_set_vert_idx = vertices_on_gather_set_edges[edge_vert]; // Global vertex index, 0 based
1317 : : // Connectivity array is shifted by where the gather set vertices start
1318 : 0 : conn_arr_gather_set_edges[edge_vert] = gather_set_start_vertex + gather_set_vert_idx;
1319 : : }
1320 : :
1321 : 0 : return MB_SUCCESS;
1322 : : }
1323 : :
1324 : 0 : ErrorCode NCHelperGCRM::create_padded_gather_set_cells( EntityHandle gather_set, EntityHandle gather_set_start_vertex )
1325 : : {
1326 : 0 : Interface*& mbImpl = _readNC->mbImpl;
1327 : :
1328 : : // Create gather set cells
1329 : : EntityHandle start_element;
1330 : 0 : EntityHandle* conn_arr_gather_set_cells = NULL;
1331 : : // Don't need to specify allocation number here, because we know enough cells were created
1332 : : // before
1333 : : ErrorCode rval = _readNC->readMeshIface->get_element_connect( nCells, EDGES_PER_CELL, MBPOLYGON, 0, start_element,
1334 [ # # ][ # # ]: 0 : conn_arr_gather_set_cells );MB_CHK_SET_ERR( rval, "Failed to create gather set cells" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1335 : :
1336 : : // Add cells to the gather set
1337 [ # # ]: 0 : Range gather_set_cells_range( start_element, start_element + nCells - 1 );
1338 [ # # ][ # # ]: 0 : rval = mbImpl->add_entities( gather_set, gather_set_cells_range );MB_CHK_SET_ERR( rval, "Failed to add cells to the gather set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1339 : :
1340 : : // Read vertices on each gather set cell (connectivity)
1341 : : int verticesOnCellVarId;
1342 [ # # ]: 0 : int success = NCFUNC( inq_varid )( _fileId, "cell_corners", &verticesOnCellVarId );
1343 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to get variable id of cell_corners" );
[ # # ][ # # ]
[ # # ][ # # ]
1344 : : // Utilize the memory storage pointed by conn_arr_gather_set_cells
1345 : 0 : int* vertices_on_gather_set_cells = (int*)conn_arr_gather_set_cells;
1346 : 0 : NCDF_SIZE read_starts[2] = { 0, 0 };
1347 : 0 : NCDF_SIZE read_counts[2] = { static_cast< NCDF_SIZE >( nCells ), static_cast< NCDF_SIZE >( EDGES_PER_CELL ) };
1348 : : #ifdef MOAB_HAVE_PNETCDF
1349 : : // Enter independent I/O mode, since this read is only for the gather processor
1350 : : success = NCFUNC( begin_indep_data )( _fileId );
1351 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
1352 : : success =
1353 : : NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells );
1354 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read cell_corners data" );
1355 : : success = NCFUNC( end_indep_data )( _fileId );
1356 : : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
1357 : : #else
1358 : : success =
1359 [ # # ]: 0 : NCFUNCG( _vara_int )( _fileId, verticesOnCellVarId, read_starts, read_counts, vertices_on_gather_set_cells );
1360 [ # # ][ # # ]: 0 : if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read cell_corners data" );
[ # # ][ # # ]
[ # # ][ # # ]
1361 : : #endif
1362 : :
1363 : : // Correct gather set cell vertices array in the same way as local cell vertices array
1364 : : // Pentagons as hexagons should have a connectivity like 123455 and not 122345
1365 [ # # ]: 0 : for( int gather_set_cell_idx = 0; gather_set_cell_idx < nCells; gather_set_cell_idx++ )
1366 : : {
1367 : 0 : int* pvertex = vertices_on_gather_set_cells + gather_set_cell_idx * EDGES_PER_CELL;
1368 [ # # ]: 0 : for( int k = 0; k < EDGES_PER_CELL - 2; k++ )
1369 : : {
1370 [ # # ]: 0 : if( *( pvertex + k ) == *( pvertex + k + 1 ) )
1371 : : {
1372 : : // Shift the connectivity
1373 [ # # ]: 0 : for( int kk = k + 1; kk < EDGES_PER_CELL - 1; kk++ )
1374 : 0 : *( pvertex + kk ) = *( pvertex + kk + 1 );
1375 : : // No need to try next k
1376 : 0 : break;
1377 : : }
1378 : : }
1379 : : }
1380 : :
1381 : : // Populate connectivity data for gather set cells
1382 : : // Convert in-place from int (stored in the first half) to EntityHandle
1383 : : // Reading backward is the trick
1384 [ # # ]: 0 : for( int cell_vert = nCells * EDGES_PER_CELL - 1; cell_vert >= 0; cell_vert-- )
1385 : : {
1386 : : // Note, indices stored in vertices_on_gather_set_cells are 0 based
1387 : 0 : int gather_set_vert_idx = vertices_on_gather_set_cells[cell_vert]; // Global vertex index, 0 based
1388 : : // Connectivity array is shifted by where the gather set vertices start
1389 : 0 : conn_arr_gather_set_cells[cell_vert] = gather_set_start_vertex + gather_set_vert_idx;
1390 : : }
1391 : :
1392 : 0 : return MB_SUCCESS;
1393 : : }
1394 : :
1395 [ + - ][ + - ]: 228 : } // namespace moab
|