27 constexpr
double kPi = 3.14159265358979323846;
32 const double r = std::sqrt( x * x + y * y + z * z );
41 if( lon < 0.0 ) lon += 360.0;
59 "Failed to gather 2-D cells for ESMF write" );
60 if( allCells.
empty() )
MB_SET_ERR( MB_FAILURE,
"No 2-D cells in file set; cannot write ESMF grid" );
71 "Failed to filter owned cells for ESMF write" );
79 int localMaxCorners = 0;
85 localMaxCorners = numConn;
91 _writeNC->myPcomm->proc_config().proc_comm() );
102 std::set< EntityHandle > usedVerts;
103 std::vector< std::vector< EntityHandle > > perCellConn(
mLocalCells );
113 if( mGlobalIdTag ) mbImpl->
tag_get_data( mGlobalIdTag, &( *cit ), 1, &gid );
120 perCellConn[ci].assign( conn, conn + numConn );
123 double cx = 0.0, cy = 0.0, cz = 0.0;
124 for(
int k = 0; k < numConn; ++k )
126 usedVerts.insert( conn[k] );
127 double vc[3] = { 0.0, 0.0, 0.0 };
140 const size_t localNodeCount = usedVerts.size();
142 mNodeLon.assign( localNodeCount, 0.0 );
143 mNodeLat.assign( localNodeCount, 0.0 );
149 if( mGlobalIdTag ) mbImpl->
tag_get_data( mGlobalIdTag, &v, 1, &vgid );
151 double vc[3] = { 0.0, 0.0, 0.0 };
163 const std::vector< EntityHandle >& cv = perCellConn[c];
165 for(
int k = 0; k < (int)cv.size(); ++k )
168 if( mGlobalIdTag ) mbImpl->
tag_get_data( mGlobalIdTag, &cv[k], 1, &vgid );
170 if( k == 0 ) firstGid = vgid;
205 MPI_Allreduce( &localN, &
mGlobalCells, 1, MPI_LONG, MPI_SUM,
206 _writeNC->myPcomm->proc_config().proc_comm() );
220 long localN =
static_cast< long >( localNodeCount );
221 MPI_Allreduce( &localN, &
mGlobalNodes, 1, MPI_LONG, MPI_SUM,
222 _writeNC->myPcomm->proc_config().proc_comm() );
226 dbgOut.
tprintf( 1,
" ESMF write: local_cells=%ld global_cells=%ld local_nodes=%zu max_corners=%d\n",
mLocalCells,
239 std::vector< std::string >& ,
244 MB_SET_ERR( MB_FAILURE,
"Failed to define nodeCount dim" );
246 MB_SET_ERR( MB_FAILURE,
"Failed to define elementCount dim" );
249 MB_SET_ERR( MB_FAILURE,
"Failed to define maxNodePElement dim" );
251 MB_SET_ERR( MB_FAILURE,
"Failed to define coordDim dim" );
259 MB_SET_ERR( MB_FAILURE,
"Failed to define nodeCoords var" );
261 MB_SET_ERR( MB_FAILURE,
"Failed to define elementConn var" );
263 MB_SET_ERR( MB_FAILURE,
"Failed to define numElementConn var" );
265 MB_SET_ERR( MB_FAILURE,
"Failed to define centerCoords var" );
270 MB_SET_ERR( MB_FAILURE,
"Failed to define elementArea var" );
275 MB_SET_ERR( MB_FAILURE,
"Failed to define elementMask var" );
278 const char* deg =
"degrees";
283 const char* rad2 =
"radians^2";
286 const char* gridtype =
"unstructured";
287 NCFUNC( put_att_text )(
_fileId, NC_GLOBAL,
"gridType", std::strlen( gridtype ), gridtype );
288 const char* title =
"MOAB:NCWriteESMF generated ESMF unstructured grid file";
289 NCFUNC( put_att_text )(
_fileId, NC_GLOBAL,
"title", std::strlen( title ), title );
304 std::vector< int >& )
309 auto writeAll = [&](
const std::vector< int >& allCellGids,
const std::vector< int >& allNumNodes,
310 const std::vector< int >& allConnGid,
const std::vector< double >& allCenterLat,
311 const std::vector< double >& allCenterLon,
const std::vector< int >& allNodeGids,
312 const std::vector< double >& allNodeLat,
const std::vector< double >& allNodeLon,
313 const std::vector< double >& allAreas,
const std::vector< int >& allMask ) ->
ErrorCode {
315 const long nCellsG =
static_cast< long >( allCellGids.size() );
316 const long nNodesIn =
static_cast< long >( allNodeGids.size() );
321 std::vector< int > nodeOrder( nNodesIn );
322 for(
long i = 0; i < nNodesIn; ++i )
323 nodeOrder[i] =
static_cast< int >( i );
324 std::sort( nodeOrder.begin(), nodeOrder.end(),
325 [&](
int a,
int b ) { return allNodeGids[a] < allNodeGids[b]; } );
327 std::vector< int > uniqNodeGids;
328 std::vector< double > uniqNodeLat, uniqNodeLon;
329 std::map< int, int > gid2Idx;
330 uniqNodeGids.reserve( nNodesIn );
331 uniqNodeLat.reserve( nNodesIn );
332 uniqNodeLon.reserve( nNodesIn );
334 for(
long i = 0; i < nNodesIn; ++i )
336 const int idx = nodeOrder[i];
337 const int g = allNodeGids[idx];
340 uniqNodeGids.push_back( g );
341 uniqNodeLat.push_back( allNodeLat[idx] );
342 uniqNodeLon.push_back( allNodeLon[idx] );
343 gid2Idx[g] =
static_cast< int >( uniqNodeGids.size() );
347 const long nNodesU =
static_cast< long >( uniqNodeGids.size() );
350 std::vector< long > cellOrder( nCellsG );
351 for(
long i = 0; i < nCellsG; ++i )
353 std::sort( cellOrder.begin(), cellOrder.end(),
354 [&](
long a,
long b ) { return allCellGids[a] < allCellGids[b]; } );
357 std::vector< int > numNodes( nCellsG );
358 std::vector< int > connIdx(
static_cast< size_t >( nCellsG ) * ncpc );
359 std::vector< double > centerLat( nCellsG ), centerLon( nCellsG );
360 std::vector< double > areas;
361 std::vector< int > mask;
362 if( !allAreas.empty() ) areas.resize( nCellsG );
363 if( !allMask.empty() ) mask.resize( nCellsG );
365 for(
long i = 0; i < nCellsG; ++i )
367 const long src = cellOrder[i];
368 numNodes[i] = allNumNodes[src];
369 centerLat[i] = allCenterLat[src];
370 centerLon[i] = allCenterLon[src];
371 if( !areas.empty() ) areas[i] = allAreas[src];
372 if( !mask.empty() ) mask[i] = allMask[src];
374 for(
int k = 0; k < ncpc; ++k )
376 const int g = allConnGid[src * ncpc + k];
377 auto it = gid2Idx.find( g );
378 connIdx[i * ncpc + k] = ( it == gid2Idx.end() ) ? 0 : it->second;
383 std::vector< double > nodeCoords( nNodesU * 2 ), centerCoords( nCellsG * 2 );
384 for(
long i = 0; i < nNodesU; ++i )
386 nodeCoords[i * 2 + 0] = uniqNodeLon[i];
387 nodeCoords[i * 2 + 1] = uniqNodeLat[i];
389 for(
long i = 0; i < nCellsG; ++i )
391 centerCoords[i * 2 + 0] = centerLon[i];
392 centerCoords[i * 2 + 1] = centerLat[i];
396 const size_t startN[2] = { 0, 0 };
397 const size_t countN[2] = {
static_cast< size_t >( nNodesU ),
static_cast< size_t >(
mCoordDim ) };
399 MB_SET_ERR( MB_FAILURE,
"Failed to write nodeCoords" );
401 const size_t startE[2] = { 0, 0 };
402 const size_t countE[2] = {
static_cast< size_t >( nCellsG ),
static_cast< size_t >( ncpc ) };
404 MB_SET_ERR( MB_FAILURE,
"Failed to write elementConn" );
406 size_t s1 = 0, c1 =
static_cast< size_t >( nCellsG );
408 MB_SET_ERR( MB_FAILURE,
"Failed to write numElementConn" );
410 const size_t startC[2] = { 0, 0 };
411 const size_t countC[2] = {
static_cast< size_t >( nCellsG ),
static_cast< size_t >(
mCoordDim ) };
413 MB_SET_ERR( MB_FAILURE,
"Failed to write centerCoords" );
418 MB_SET_ERR( MB_FAILURE,
"Failed to write elementArea" );
423 MB_SET_ERR( MB_FAILURE,
"Failed to write elementMask" );
432 MPI_Comm comm =
_writeNC->myPcomm->proc_config().proc_comm();
433 const int rank =
_writeNC->myPcomm->proc_config().proc_rank();
434 const int size =
_writeNC->myPcomm->proc_config().proc_size();
439 std::vector< int > cellCounts( size, 0 ), cellDispls( size, 0 );
440 MPI_Gather( &myCells, 1, MPI_INT, cellCounts.data(), 1, MPI_INT, 0, comm );
444 int myNodes =
static_cast< int >(
mNodeGids.size() );
445 std::vector< int > nodeCounts( size, 0 ), nodeDispls( size, 0 );
446 MPI_Gather( &myNodes, 1, MPI_INT, nodeCounts.data(), 1, MPI_INT, 0, comm );
449 std::vector< int > cellCountsC( size, 0 ), cellDisplsC( size, 0 );
452 int accC = 0, accCC = 0, accN = 0;
453 for(
int i = 0; i < size; ++i )
455 cellDispls[i] = accC;
456 accC += cellCounts[i];
457 cellCountsC[i] = cellCounts[i] * ncpc;
458 cellDisplsC[i] = accCC;
459 accCC += cellCountsC[i];
460 nodeDispls[i] = accN;
461 accN += nodeCounts[i];
466 long nNodesGlobal = 0;
467 if( rank == 0 )
for(
int i = 0; i < size; ++i ) nNodesGlobal += nodeCounts[i];
470 std::vector< int > allCellGids, allNumNodes, allConnGid, allNodeGids;
471 std::vector< double > allCenterLat, allCenterLon, allNodeLat, allNodeLon;
472 std::vector< double > allAreas;
473 std::vector< int > allMask;
476 allCellGids.resize( nCellsGlobal );
477 allNumNodes.resize( nCellsGlobal );
478 allConnGid.resize(
static_cast< size_t >( nCellsGlobal ) * ncpc );
479 allCenterLat.resize( nCellsGlobal );
480 allCenterLon.resize( nCellsGlobal );
481 allNodeGids.resize( nNodesGlobal );
482 allNodeLat.resize( nNodesGlobal );
483 allNodeLon.resize( nNodesGlobal );
484 if(
mHasAreas ) allAreas.resize( nCellsGlobal );
485 if(
mHasMask ) allMask.resize( nCellsGlobal );
488 MPI_Gatherv(
mLocalCellGids.data(), myCells, MPI_INT, allCellGids.data(), cellCounts.data(),
489 cellDispls.data(), MPI_INT, 0, comm );
490 MPI_Gatherv(
mElementNumNodes.data(), myCells, MPI_INT, allNumNodes.data(), cellCounts.data(),
491 cellDispls.data(), MPI_INT, 0, comm );
492 MPI_Gatherv(
mCenterLat.data(), myCells, MPI_DOUBLE, allCenterLat.data(), cellCounts.data(), cellDispls.data(),
493 MPI_DOUBLE, 0, comm );
494 MPI_Gatherv(
mCenterLon.data(), myCells, MPI_DOUBLE, allCenterLon.data(), cellCounts.data(), cellDispls.data(),
495 MPI_DOUBLE, 0, comm );
496 MPI_Gatherv(
mElementConn.data(), myCells * ncpc, MPI_INT, allConnGid.data(), cellCountsC.data(),
497 cellDisplsC.data(), MPI_INT, 0, comm );
499 MPI_Gatherv(
mNodeGids.data(), myNodes, MPI_INT, allNodeGids.data(), nodeCounts.data(), nodeDispls.data(),
501 MPI_Gatherv(
mNodeLat.data(), myNodes, MPI_DOUBLE, allNodeLat.data(), nodeCounts.data(), nodeDispls.data(),
502 MPI_DOUBLE, 0, comm );
503 MPI_Gatherv(
mNodeLon.data(), myNodes, MPI_DOUBLE, allNodeLon.data(), nodeCounts.data(), nodeDispls.data(),
504 MPI_DOUBLE, 0, comm );
507 MPI_Gatherv(
mAreas.data(), myCells, MPI_DOUBLE, allAreas.data(), cellCounts.data(), cellDispls.data(),
508 MPI_DOUBLE, 0, comm );
510 MPI_Gatherv(
mMask.data(), myCells, MPI_INT, allMask.data(), cellCounts.data(), cellDispls.data(), MPI_INT,
515 rc = writeAll( allCellGids, allNumNodes, allConnGid, allCenterLat, allCenterLon, allNodeGids, allNodeLat,
516 allNodeLon, allAreas, allMask );
517 int rcInt =
static_cast< int >( rc );
518 MPI_Bcast( &rcInt, 1, MPI_INT, 0, comm );
521 dbgOut.
tprintf( 1,
" ESMF write: gathered+wrote %ld cells from %d ranks\n",
mGlobalCells, size );
531 std::vector< int >& )