14 #ifndef MOAB_HAVE_TEMPESTREMAP
15 #error Need TempestRemap dependency for this test
18 #include "OfflineMap.h"
23 #ifndef IS_BUILDING_MB
24 #define IS_BUILDING_MB
31 #include <netcdf_par.h>
41 int main(
int argc,
char** argv )
53 MPI_Init( &argc, &argv );
62 #define NCERROREXIT( err, MSG ) \
65 std::cout << "Error (" << ( err ) << "): " << ( MSG ); \
66 std::cout << "\nAborting with message: " << nc_strerror( err ) << "... \n"; \
72 NcError
error( NcError::silent_nonfatal );
76 NcVar *varRow = NULL, *varCol = NULL, *varS = NULL;
80 const int rootProc = 0;
85 const int nBufferSize = 64 * 1024;
86 const int nNNZBytes = 2 *
sizeof( int ) +
sizeof(
double );
87 const int nMaxEntries = nBufferSize / nNNZBytes;
88 int nA = 0, nB = 0, nVA = 0, nVB = 0, nS = 0;
89 double dTolerance = 1e-08;
91 int nprocs = 1,
rank = 0;
94 MPI_Comm_size( commW, &nprocs );
95 MPI_Comm_rank( commW, &
rank );
99 if(
rank == rootProc )
102 ncMap =
new NcFile(
inMapFilename.c_str(), NcFile::ReadOnly );
103 if( !ncMap->is_valid() )
105 _EXCEPTION1(
"Unable to open input map file \"%s\"",
inMapFilename.c_str() );
109 NcDim* dimNA = ncMap->get_dim(
"n_a" );
112 _EXCEPTIONT(
"Input map missing dimension \"n_a\"" );
117 NcDim* dimNB = ncMap->get_dim(
"n_b" );
120 _EXCEPTIONT(
"Input map missing dimension \"n_b\"" );
125 NcDim* dimNVA = ncMap->get_dim(
"nv_a" );
128 _EXCEPTIONT(
"Input map missing dimension \"nv_a\"" );
131 nVA = dimNVA->size();
133 NcDim* dimNVB = ncMap->get_dim(
"nv_b" );
136 _EXCEPTIONT(
"Input map missing dimension \"nv_b\"" );
139 nVB = dimNVB->size();
142 NcDim* dimNS = ncMap->get_dim(
"n_s" );
145 _EXCEPTION1(
"Map file \"%s\" does not contain dimension \"n_s\"",
inMapFilename.c_str() );
150 varRow = ncMap->get_var(
"row" );
153 _EXCEPTION1(
"Map file \"%s\" does not contain variable \"row\"",
inMapFilename.c_str() );
156 varCol = ncMap->get_var(
"col" );
159 _EXCEPTION1(
"Map file \"%s\" does not contain variable \"col\"",
inMapFilename.c_str() );
162 varS = ncMap->get_var(
"S" );
165 _EXCEPTION1(
"Map file \"%s\" does not contain variable \"S\"",
inMapFilename.c_str() );
170 int nEntriesRemaining = nS;
171 int nBufferedReads =
static_cast< int >( ceil( ( 1.0 * nS ) / ( 1.0 * nMaxEntries ) ) );
172 int runData[6] = { nA, nB, nVA, nVB, nS, nBufferedReads };
174 mpierr = MPI_Bcast( runData, 6, MPI_INT, rootProc, commW );
178 if(
rank != rootProc )
185 nBufferedReads = runData[5];
188 printf(
"Global parameters: nA = %d, nB = %d, nS = %d\n", nA, nB, nS );
190 printf(
"Global parameters: nA = %d, nB = %d, nS = %d\n", nA, nB, nS );
193 std::vector< int > rowOwnership( nprocs );
194 int nGRowPerPart = nB / nprocs;
195 int nGRowRemainder = nB % nprocs;
196 rowOwnership[0] = nGRowPerPart + nGRowRemainder;
197 for(
int ip = 1, roffset = rowOwnership[0]; ip < nprocs; ++ip )
199 roffset += nGRowPerPart;
200 rowOwnership[ip] = roffset;
205 SparseMatrix< double >& sparseMatrix = mapRemap.GetSparseMatrix();
208 if(
rank == rootProc )
210 printf(
"Parameters: nA=%d, nB=%d, nVA=%d, nVB=%d, nS=%d, nNNZBytes = %d, nBufferedReads = %d\n", nA, nB, nVA,
211 nVB, nS, nNNZBytes, nBufferedReads );
213 std::map< int, int > rowMap, colMap;
214 int rindexMax = 0, cindexMax = 0;
219 for(
int iRead = 0; iRead < nBufferedReads; ++iRead )
222 DataArray1D< int > vecRow;
223 DataArray1D< int > vecCol;
224 DataArray1D< double > vecS;
225 std::vector< std::vector< int > > dataPerProcess( nprocs );
226 std::vector< int > nDataPerProcess( nprocs, 0 );
227 for(
int ip = 0; ip < nprocs; ++ip )
228 dataPerProcess[ip].reserve( std::max( 100, nMaxEntries / nprocs ) );
231 if(
rank == rootProc )
234 int nLocSize = std::min( nEntriesRemaining,
static_cast< int >( ceil( nBufferSize * 1.0 / nNNZBytes ) ) );
236 printf(
"Reading file: elements %ld to %ld\n", offset, offset + nLocSize );
239 vecRow.Allocate( nLocSize );
240 vecCol.Allocate( nLocSize );
241 vecS.Allocate( nLocSize );
243 varRow->set_cur( (
long)( offset ) );
244 varRow->get( &( vecRow[0] ), nLocSize );
246 varCol->set_cur( (
long)( offset ) );
247 varCol->get( &( vecCol[0] ), nLocSize );
249 varS->set_cur( (
long)( offset ) );
250 varS->get( &( vecS[0] ), nLocSize );
253 for(
size_t i = 0; i < vecRow.GetRows(); i++ )
260 if( rowOwnership[0] > vecRow[i] )
264 for(
int ip = 1; ip < nprocs; ++ip )
266 if( rowOwnership[ip - 1] <= vecRow[i] && rowOwnership[ip] > vecRow[i] )
274 assert( pOwner >= 0 && pOwner < nprocs );
275 dataPerProcess[pOwner].push_back( i );
279 nEntriesRemaining -= nLocSize;
281 for(
int ip = 0; ip < nprocs; ++ip )
282 nDataPerProcess[ip] = dataPerProcess[ip].
size();
286 int nEntriesComm = 0;
287 mpierr = MPI_Scatter( nDataPerProcess.data(), 1, MPI_INT, &nEntriesComm, 1, MPI_INT, rootProc, commW );
291 if(
rank == rootProc )
294 std::vector< MPI_Request > cRequests;
295 std::vector< MPI_Status > cStats( 2 * nprocs - 2 );
296 cRequests.reserve( 2 * nprocs - 2 );
299 std::vector< std::vector< int > > dataRowColsAll( nprocs );
300 std::vector< std::vector< double > > dataEntriesAll( nprocs );
301 for(
int ip = 1; ip < nprocs; ++ip )
303 const int nDPP = nDataPerProcess[ip];
306 std::vector< int >& dataRowCols = dataRowColsAll[ip];
307 dataRowCols.resize( 2 * nDPP );
308 std::vector< double >& dataEntries = dataEntriesAll[ip];
309 dataEntries.resize( nDPP );
311 for(
int ij = 0; ij < nDPP; ++ij )
313 dataRowCols[ij * 2] = vecRow[dataPerProcess[ip][ij]];
314 dataRowCols[ij * 2 + 1] = vecCol[dataPerProcess[ip][ij]];
315 dataEntries[ij] = vecS[dataPerProcess[ip][ij]];
318 MPI_Request rcsend, dsend;
319 mpierr = MPI_Isend( dataRowCols.data(), 2 * nDPP, MPI_INT, ip, iRead * 1000, commW, &rcsend );
321 mpierr = MPI_Isend( dataEntries.data(), nDPP, MPI_DOUBLE, ip, iRead * 1000 + 1, commW, &dsend );
324 cRequests.push_back( rcsend );
325 cRequests.push_back( dsend );
331 int rindex = 0, cindex = 0;
332 assert( dataPerProcess[0].
size() - nEntriesComm == 0 );
333 for(
int i = 0; i < nEntriesComm; ++i )
335 const int& vecRowValue = vecRow[dataPerProcess[0][i]];
336 const int& vecColValue = vecCol[dataPerProcess[0][i]];
338 std::map< int, int >::iterator riter = rowMap.find( vecRowValue );
339 if( riter == rowMap.end() )
341 rowMap[vecRowValue] = rindexMax;
346 rindex = riter->second;
348 std::map< int, int >::iterator citer = colMap.find( vecColValue );
349 if( citer == colMap.end() )
351 colMap[vecColValue] = cindexMax;
356 cindex = citer->second;
358 sparseMatrix( rindex, cindex ) = vecS[i];
362 mpierr = MPI_Waitall( cRequests.size(), cRequests.data(), cStats.data() );
368 if( nEntriesComm > 0 )
370 MPI_Request cRequests[2];
371 MPI_Status cStats[2];
374 std::vector< int > dataRowCols( 2 * nEntriesComm );
375 vecRow.Allocate( nEntriesComm );
376 vecCol.Allocate( nEntriesComm );
377 vecS.Allocate( nEntriesComm );
381 mpierr = MPI_Irecv( dataRowCols.data(), 2 * nEntriesComm, MPI_INT, rootProc, iRead * 1000, commW,
385 mpierr = MPI_Irecv( vecS, nEntriesComm, MPI_DOUBLE, rootProc, iRead * 1000 + 1, commW, &cRequests[1] );
389 mpierr = MPI_Waitall( 2, cRequests, cStats );
393 int rindex = 0, cindex = 0;
394 for(
int i = 0; i < nEntriesComm; ++i )
396 const int& vecRowValue = dataRowCols[i * 2];
397 const int& vecColValue = dataRowCols[i * 2 + 1];
399 std::map< int, int >::iterator riter = rowMap.find( vecRowValue );
400 if( riter == rowMap.end() )
402 rowMap[vecRowValue] = rindexMax;
407 rindex = riter->second;
410 std::map< int, int >::iterator citer = colMap.find( vecColValue );
411 if( citer == colMap.end() )
413 colMap[vecColValue] = cindexMax;
418 cindex = citer->second;
421 sparseMatrix( rindex, cindex ) = vecS[i];
429 MPI_Barrier( commW );
434 if(
rank == rootProc )
437 assert( nEntriesRemaining == 0 );
448 printf(
"Rank %d: sparsematrix size = %d x %d\n",
rank, sparseMatrix.GetRows(), sparseMatrix.GetColumns() );
452 int isConsistentP = mapRemap.IsConsistent( dTolerance );
453 if( 0 != isConsistentP )
455 printf(
"Rank %d failed consistency checks...\n",
rank );
466 int isMonotoneP = mapRemap.IsMonotone( dTolerance );
469 mpierr = MPI_Allreduce( &isMonotoneP, &isMonotoneG, 1, MPI_INT, MPI_SUM, commW );
484 NcError
error( NcError::verbose_nonfatal );
486 std::vector< int > tmp_owned_ids;
487 double dTolerance = 1e-08;
489 std::string remap_weights_filename = TestDir +
"unittest/outCS5ICOD5_map.nc";
503 rval = onlinemap.
ReadParallelMap( remap_weights_filename.c_str(), tmp_owned_ids,
true );
507 int isConsistentP = onlinemap.
IsConsistent( dTolerance );
517 int isMonotoneP = onlinemap.
IsMonotone( dTolerance );
563 NcError
error( NcError::silent_nonfatal );
565 const int rootProc = 0;
567 double dTolerance = 1e-08;
574 const double dFillValueOverride = 0.0;
578 std::cout <<
"Reading file: " << outFilename << std::endl;
579 mapRemap.Read( outFilename );
580 mapRemap.SetFillValueOverrideDbl( dFillValueOverride );
581 mapRemap.SetFillValueOverride(
static_cast< float >( dFillValueOverride ) );
583 int isConsistent = mapRemap.IsConsistent( dTolerance );
585 int isConservative = mapRemap.IsConservative( dTolerance );
587 int isMonotone = mapRemap.IsMonotone( dTolerance );
591 DataArray1D< double >& srcAreas = mapRemap.GetSourceAreas();
592 DataArray1D< double >& tgtAreas = mapRemap.GetTargetAreas();
594 double totSrcArea = 0.0;
595 for(
size_t i = 0; i < srcAreas.GetRows(); ++i )
596 totSrcArea += srcAreas[i];
598 double totTgtArea = 0.0;
599 for(
size_t i = 0; i < tgtAreas.GetRows(); ++i )
600 totTgtArea += tgtAreas[i];
605 MPI_Barrier( commW );
607 SparseMatrix< double >& sparseMatrix = mapRemap.GetSparseMatrix();
611 DataArray1D< int > dataRowsGlobal, dataColsGlobal;
612 DataArray1D< double > dataEntriesGlobal;
615 sparseMatrix.GetEntries( dataRowsGlobal, dataColsGlobal, dataEntriesGlobal );
616 std::cout <<
"Total NNZ in remap matrix = " << dataRowsGlobal.GetRows() << std::endl;
619 int *rg =
nullptr, *cg =
nullptr;
620 double* de =
nullptr;
621 int nMapGlobalRowCols[3] = { sparseMatrix.GetRows(), sparseMatrix.GetColumns(),
622 static_cast< int >( dataEntriesGlobal.GetRows() ) };
625 std::vector< int > rowAllocation;
626 std::vector< int > sendCounts;
627 std::vector< int > displs;
633 de = dataEntriesGlobal;
636 rowAllocation.resize( nprocs * NDATA );
637 displs.resize( nprocs );
638 sendCounts.resize( nprocs );
640 int nRowPerPart = nMapGlobalRowCols[0] / nprocs;
641 int remainder = nMapGlobalRowCols[0] % nprocs;
644 for(
int i = 0; i < nprocs; ++i )
646 rowAllocation[i * NDATA] = nRowPerPart + ( i == 0 ? remainder : 0 );
647 rowAllocation[i * NDATA + 1] = std::find( rg, rg + dataRowsGlobal.GetRows(),
sum ) - rg;
648 sum += rowAllocation[i * NDATA];
649 displs[i] = rowAllocation[i * NDATA + 1];
651 for(
int i = 0; i < nprocs - 1; ++i )
653 rowAllocation[i * NDATA + 2] = rowAllocation[( i + 1 ) * NDATA + 1] - rowAllocation[i * NDATA + 1];
654 sendCounts[i] = rowAllocation[i * NDATA + 2];
656 rowAllocation[( nprocs - 1 ) * NDATA + 2] = nMapGlobalRowCols[2] - displs[nprocs - 1];
657 sendCounts[nprocs - 1] = rowAllocation[( nprocs - 1 ) * NDATA + 2];
664 mpierr = MPI_Bcast( nMapGlobalRowCols, 3, MPI_INT, rootProc, commW );
667 int allocationSize[NDATA] = { 0, 0, 0 };
668 mpierr = MPI_Scatter( rowAllocation.data(), NDATA, MPI_INT, &allocationSize, NDATA, MPI_INT, rootProc, commW );
672 DataArray1D< int > dataRows, dataCols;
673 DataArray1D< double > dataEntries;
674 dataRows.Allocate( allocationSize[2] );
675 dataCols.Allocate( allocationSize[2] );
676 dataEntries.Allocate( allocationSize[2] );
680 mpierr = MPI_Scatterv( rg, sendCounts.data(), displs.data(), MPI_INT, (
int*)( dataRows ), dataRows.GetByteSize(),
681 MPI_INT, rootProc, commW );
684 mpierr = MPI_Scatterv( cg, sendCounts.data(), displs.data(), MPI_INT, (
int*)( dataCols ), dataCols.GetByteSize(),
685 MPI_INT, rootProc, commW );
688 mpierr = MPI_Scatterv( de, sendCounts.data(), displs.data(), MPI_DOUBLE, (
double*)( dataEntries ),
689 dataEntries.GetByteSize(), MPI_DOUBLE, rootProc, commW );
693 std::vector< int > rowMap, colMap;
694 for(
int i = 0; i < allocationSize[2]; ++i )
697 std::vector< int >::iterator riter = std::find( rowMap.begin(), rowMap.end(), dataRows[i] );
698 if( riter == rowMap.end() )
700 rowMap.push_back( dataRows[i] );
701 rindex = rowMap.size() - 1;
704 rindex = riter - rowMap.begin();
705 dataRows[i] = rindex;
707 std::vector< int >::iterator citer = std::find( colMap.begin(), colMap.end(), dataCols[i] );
708 if( citer == colMap.end() )
710 colMap.push_back( dataCols[i] );
711 cindex = colMap.size() - 1;
714 cindex = citer - colMap.begin();
715 dataCols[i] = cindex;
719 sparseMatrix.SetEntries( dataRows, dataCols, dataEntries );
730 int isConsistentP = mapRemap.IsConsistent( dTolerance );
738 int isMonotoneP = mapRemap.IsMonotone( dTolerance );
741 mpierr = MPI_Allreduce( &isMonotoneP, &isMonotoneG, 1, MPI_INT, MPI_SUM, commW );