17 #include "FiniteElementTools.h"
21 #ifdef MOAB_HAVE_NETCDFPAR
24 #include "netcdfcpp.h"
27 #ifdef MOAB_HAVE_PNETCDF
30 #define ERR_PARNC( err ) \
31 if( err != NC_NOERR ) \
33 fprintf( stderr, "Error at line %d: %s\n", __LINE__, ncmpi_strerror( err ) ); \
34 MPI_Abort( MPI_COMM_WORLD, 1 ); \
41 #define MPI_CHK_ERR( err ) \
44 std::cout << "MPI Failure. ErrorCode (" << ( err ) << ") "; \
45 std::cout << "\nMPI Aborting... \n"; \
46 return moab::MB_FAILURE; \
49 #ifdef MOAB_HAVE_EIGEN3
52 template <
typename SparseMatrixType >
55 std::ofstream ofs( filename );
58 std::cerr <<
"Failed to open file for writing: " << filename << std::endl;
63 int rows = mat.rows();
64 int cols = mat.cols();
65 typename SparseMatrixType::Index nnz = mat.nonZeros();
66 ofs << rows <<
" " << cols <<
" " << nnz <<
"\n";
69 for(
int k = 0; k < mat.outerSize(); ++k )
71 for(
typename SparseMatrixType::InnerIterator it( mat, k ); it; ++it )
77 auto value = it.value();
78 ofs << row <<
" " << col <<
" " << value <<
"\n";
86 int moab::TempestOnlineMap::rearrange_arrays_by_dofs(
const std::vector< unsigned int >& gdofmap,
87 DataArray1D< double >& vecFaceArea,
88 DataArray1D< double >& dCenterLon,
89 DataArray1D< double >& dCenterLat,
90 DataArray2D< double >& dVertexLon,
91 DataArray2D< double >& dVertexLat,
92 std::vector< int >& masks,
98 unsigned int localmax = 0;
99 for(
unsigned i = 0; i < N; i++ )
100 if( gdofmap[i] > localmax ) localmax = gdofmap[i];
103 MPI_Allreduce( &localmax, &maxdof, 1, MPI_INT, MPI_MAX, m_pcomm->comm() );
106 int size_per_task = ( maxdof + 1 ) / size;
109 unsigned numr = 2 * nv + 3;
114 for(
unsigned i = 0; i < N; i++ )
116 int gdof = gdofmap[i];
117 int to_proc = gdof / size_per_task;
118 int mask = (i >= masks.size() ? 1: masks[i]);
119 if( to_proc >= size ) to_proc = size - 1;
121 tl.
vi_wr[3 * n] = to_proc;
122 tl.
vi_wr[3 * n + 1] = gdof;
123 tl.
vi_wr[3 * n + 2] = mask;
124 tl.
vr_wr[n * numr] = vecFaceArea[i];
125 tl.
vr_wr[n * numr + 1] = dCenterLon[i];
126 tl.
vr_wr[n * numr + 2] = dCenterLat[i];
127 for(
int j = 0; j < nv; j++ )
129 tl.
vr_wr[n * numr + 3 + j] = dVertexLon[i][j];
130 tl.
vr_wr[n * numr + 3 + nv + j] = dVertexLat[i][j];
136 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tl, 0 );
141 sort_buffer.buffer_init( tl.
get_n() );
142 tl.
sort( 1, &sort_buffer );
145 for(
unsigned i = 0; i < tl.
get_n() - 1; i++ )
147 if( tl.
vi_wr[3 * i + 1] != tl.
vi_wr[3 * i + 4] ) nb_unique++;
149 vecFaceArea.Allocate( nb_unique );
150 dCenterLon.Allocate( nb_unique );
151 dCenterLat.Allocate( nb_unique );
152 dVertexLon.Allocate( nb_unique, nv );
153 dVertexLat.Allocate( nb_unique, nv );
154 masks.resize( nb_unique );
155 int current_size = 1;
156 vecFaceArea[0] = tl.
vr_wr[0];
157 dCenterLon[0] = tl.
vr_wr[1];
158 dCenterLat[0] = tl.
vr_wr[2];
159 masks[0] = tl.
vi_wr[2];
160 for(
int j = 0; j < nv; j++ )
162 dVertexLon[0][j] = tl.
vr_wr[3 + j];
163 dVertexLat[0][j] = tl.
vr_wr[3 + nv + j];
165 for(
unsigned i = 0; i < tl.
get_n() - 1; i++ )
168 if( tl.
vi_wr[3 * i + 1] != tl.
vi_wr[3 * i + 4] )
170 vecFaceArea[current_size] = tl.
vr_wr[i1 * numr];
171 dCenterLon[current_size] = tl.
vr_wr[i1 * numr + 1];
172 dCenterLat[current_size] = tl.
vr_wr[i1 * numr + 2];
173 for(
int j = 0; j < nv; j++ )
175 dVertexLon[current_size][j] = tl.
vr_wr[i1 * numr + 3 + j];
176 dVertexLat[current_size][j] = tl.
vr_wr[i1 * numr + 3 + nv + j];
178 masks[current_size] = tl.
vi_wr[3 * i1 + 2];
183 vecFaceArea[current_size - 1] += tl.
vr_wr[i1 * numr];
195 const std::map< std::string, std::string >& attrMap )
197 size_t lastindex = strFilename.find_last_of(
"." );
198 std::string extension = strFilename.substr( lastindex + 1, strFilename.size() );
201 if( extension ==
"nc" )
203 #if !defined( MOAB_HAVE_NETCDFPAR )
209 std::string h5mFilename = strFilename.substr( 0, lastindex ) +
".h5m";
212 std::cout <<
" [WriteParallelMap]: Parallel NetCDF not available; writing map to "
213 <<
"HDF5 format (" << h5mFilename <<
") instead of SCRIP (.nc)\n";
215 MB_CHK_ERR( this->WriteHDF5MapFile( h5mFilename.c_str() ) );
220 MB_CHK_ERR( this->WriteSCRIPMapFile( strFilename.c_str(), attrMap ) );
225 MB_CHK_ERR( this->WriteHDF5MapFile( strFilename.c_str() ) );
234 const std::map< std::string, std::string >& attrMap )
236 NcError
error( NcError::silent_nonfatal );
238 #ifdef MOAB_HAVE_NETCDFPAR
239 bool is_independent =
true;
240 ParNcFile ncMap( m_pcomm->comm(), MPI_INFO_NULL, strFilename.c_str(), NcFile::Replace, NcFile::Netcdf4 );
243 NcFile ncMap( strFilename.c_str(), NcFile::Replace );
246 if( !ncMap.is_valid() )
248 _EXCEPTION1(
"Unable to open output map file \"%s\"", strFilename.c_str() );
253 auto it = attrMap.begin();
254 while( it != attrMap.end() )
257 ncMap.add_att( it->first.c_str(), it->second.c_str() );
271 DataArray1D< double > vecSourceFaceArea, vecTargetFaceArea;
272 DataArray1D< double > dSourceCenterLon, dSourceCenterLat, dTargetCenterLon, dTargetCenterLat;
273 DataArray2D< double > dSourceVertexLon, dSourceVertexLat, dTargetVertexLon, dTargetVertexLat;
274 if( m_srcDiscType == DiscretizationType_FV || m_srcDiscType == DiscretizationType_PCLOUD )
276 this->InitializeCoordinatesFromMeshFV(
277 *m_meshInput, dSourceCenterLon, dSourceCenterLat, dSourceVertexLon, dSourceVertexLat,
279 m_remapper->max_source_edges );
281 vecSourceFaceArea.Allocate( m_meshInput->vecFaceArea.GetRows() );
282 for(
unsigned i = 0; i < m_meshInput->vecFaceArea.GetRows(); ++i )
283 vecSourceFaceArea[i] = m_meshInput->vecFaceArea[i];
287 DataArray3D< double > dataGLLJacobianSrc;
288 this->InitializeCoordinatesFromMeshFE( *m_meshInput, m_nDofsPEl_Src, dataGLLNodesSrc, dSourceCenterLon,
289 dSourceCenterLat, dSourceVertexLon, dSourceVertexLat );
292 GenerateMetaData( *m_meshInput, m_nDofsPEl_Src,
false , dataGLLNodesSrc, dataGLLJacobianSrc );
294 if( m_srcDiscType == DiscretizationType_CGLL )
296 GenerateUniqueJacobian( dataGLLNodesSrc, dataGLLJacobianSrc, vecSourceFaceArea );
300 GenerateDiscontinuousJacobian( dataGLLJacobianSrc, vecSourceFaceArea );
304 if( m_destDiscType == DiscretizationType_FV || m_destDiscType == DiscretizationType_PCLOUD )
306 this->InitializeCoordinatesFromMeshFV(
307 *m_meshOutput, dTargetCenterLon, dTargetCenterLat, dTargetVertexLon, dTargetVertexLat,
309 m_remapper->max_target_edges );
311 vecTargetFaceArea.Allocate( m_meshOutput->vecFaceArea.GetRows() );
312 for(
unsigned i = 0; i < m_meshOutput->vecFaceArea.GetRows(); ++i )
314 vecTargetFaceArea[i] = m_meshOutput->vecFaceArea[i];
319 DataArray3D< double > dataGLLJacobianDest;
320 this->InitializeCoordinatesFromMeshFE( *m_meshOutput, m_nDofsPEl_Dest, dataGLLNodesDest, dTargetCenterLon,
321 dTargetCenterLat, dTargetVertexLon, dTargetVertexLat );
324 GenerateMetaData( *m_meshOutput, m_nDofsPEl_Dest,
false , dataGLLNodesDest, dataGLLJacobianDest );
326 if( m_destDiscType == DiscretizationType_CGLL )
328 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobianDest, vecTargetFaceArea );
332 GenerateDiscontinuousJacobian( dataGLLJacobianDest, vecTargetFaceArea );
337 unsigned nA = ( vecSourceFaceArea.GetRows() );
338 unsigned nB = ( vecTargetFaceArea.GetRows() );
340 std::vector< int > masksA, masksB;
345 int nSourceNodesPerFace = dSourceVertexLon.GetColumns();
346 int nTargetNodesPerFace = dTargetVertexLon.GetColumns();
352 for(
unsigned i = 0; i < nA; i++ )
354 const Face&
face = m_meshInput->faces[i];
356 int nNodes =
face.edges.size();
357 int indexNodeAtPole = -1;
360 for(
int j = 0; j < nNodes; j++ )
361 if( fabs( fabs( dSourceVertexLat[i][j] ) - 90.0 ) < 1.0e-12 )
367 if( indexNodeAtPole < 0 )
continue;
369 int nodeAtPole =
face[indexNodeAtPole];
370 Node nodePole = m_meshInput->nodes[nodeAtPole];
371 Node newCenter = nodePole * 2;
372 for(
int j = 1; j < nNodes; j++ )
374 int indexi = ( indexNodeAtPole + j ) % nNodes;
375 const Node& node = m_meshInput->nodes[
face[indexi]];
376 newCenter = newCenter + node;
378 newCenter = newCenter * 0.25;
379 newCenter = newCenter.Normalized();
382 double iniLon = dSourceCenterLon[i], iniLat = dSourceCenterLat[i];
385 XYZtoRLL_Deg( newCenter.x, newCenter.y, newCenter.z, dSourceCenterLon[i], dSourceCenterLat[i] );
387 std::cout <<
" modify center of triangle from " << iniLon <<
" " << iniLat <<
" to " << dSourceCenterLon[i]
388 <<
" " << dSourceCenterLat[i] <<
"\n";
393 #if defined( MOAB_HAVE_MPI )
394 int max_row_dof, max_col_dof;
397 int ierr = rearrange_arrays_by_dofs( srccol_gdofmap, vecSourceFaceArea, dSourceCenterLon, dSourceCenterLat,
398 dSourceVertexLon, dSourceVertexLat, masksA, nA, nSourceNodesPerFace,
402 _EXCEPTION1(
"Unable to arrange source data %d ", nA );
406 ierr = rearrange_arrays_by_dofs( row_gdofmap, vecTargetFaceArea, dTargetCenterLon, dTargetCenterLat,
407 dTargetVertexLon, dTargetVertexLat, masksB, nB, nTargetNodesPerFace,
411 _EXCEPTION1(
"Unable to arrange target data %d ", nB );
417 int nS = m_weightMatrix.nonZeros();
419 #if defined( MOAB_HAVE_MPI ) && defined( MOAB_HAVE_NETCDFPAR )
420 int locbuf[5] = { (int)nA, (
int)nB, nS, nSourceNodesPerFace, nTargetNodesPerFace };
421 int offbuf[3] = { 0, 0, 0 };
422 int globuf[5] = { 0, 0, 0, 0, 0 };
423 MPI_Scan( locbuf, offbuf, 3, MPI_INT, MPI_SUM, m_pcomm->comm() );
424 MPI_Allreduce( locbuf, globuf, 3, MPI_INT, MPI_SUM, m_pcomm->comm() );
425 MPI_Allreduce( &locbuf[3], &globuf[3], 2, MPI_INT, MPI_MAX, m_pcomm->comm() );
433 int offbuf[3] = { 0, 0, 0 };
434 int globuf[5] = { (int)nA, (
int)nB, nS, nSourceNodesPerFace, nTargetNodesPerFace };
437 std::vector< std::string > srcdimNames, tgtdimNames;
438 std::vector< int > srcdimSizes, tgtdimSizes;
442 srcdimNames.push_back(
"lat" );
443 srcdimNames.push_back(
"lon" );
444 srcdimSizes.resize( 2, 0 );
445 srcdimSizes[0] = m_remapper->m_source_metadata[0];
446 srcdimSizes[1] = m_remapper->m_source_metadata[1];
450 srcdimNames.push_back(
"num_elem" );
451 srcdimSizes.push_back( globuf[0] );
456 tgtdimNames.push_back(
"lat" );
457 tgtdimNames.push_back(
"lon" );
458 tgtdimSizes.resize( 2, 0 );
459 tgtdimSizes[0] = m_remapper->m_target_metadata[0];
460 tgtdimSizes[1] = m_remapper->m_target_metadata[1];
464 tgtdimNames.push_back(
"num_elem" );
465 tgtdimSizes.push_back( globuf[1] );
470 unsigned nSrcGridDims = ( srcdimSizes.size() );
471 unsigned nDstGridDims = ( tgtdimSizes.size() );
473 NcDim* dimSrcGridRank = ncMap.add_dim(
"src_grid_rank", nSrcGridDims );
474 NcDim* dimDstGridRank = ncMap.add_dim(
"dst_grid_rank", nDstGridDims );
476 NcVar* varSrcGridDims = ncMap.add_var(
"src_grid_dims", ncInt, dimSrcGridRank );
477 NcVar* varDstGridDims = ncMap.add_var(
"dst_grid_dims", ncInt, dimDstGridRank );
479 #ifdef MOAB_HAVE_NETCDFPAR
480 ncMap.enable_var_par_access( varSrcGridDims, is_independent );
481 ncMap.enable_var_par_access( varDstGridDims, is_independent );
487 for(
unsigned i = 0; i < srcdimSizes.size(); i++ )
489 varSrcGridDims->set_cur( nSrcGridDims - i - 1 );
490 varSrcGridDims->put( &( srcdimSizes[nSrcGridDims - i - 1] ), 1 );
493 for(
unsigned i = 0; i < srcdimSizes.size(); i++ )
495 snprintf( szDim, 64,
"name%u", i );
496 varSrcGridDims->add_att( szDim, srcdimNames[nSrcGridDims - i - 1].c_str() );
499 for(
unsigned i = 0; i < tgtdimSizes.size(); i++ )
501 varDstGridDims->set_cur( nDstGridDims - i - 1 );
502 varDstGridDims->put( &( tgtdimSizes[nDstGridDims - i - 1] ), 1 );
505 for(
unsigned i = 0; i < tgtdimSizes.size(); i++ )
507 snprintf( szDim, 64,
"name%u", i );
508 varDstGridDims->add_att( szDim, tgtdimNames[nDstGridDims - i - 1].c_str() );
513 NcDim* dimNA = ncMap.add_dim(
"n_a", globuf[0] );
514 NcDim* dimNB = ncMap.add_dim(
"n_b", globuf[1] );
517 NcDim* dimNVA = ncMap.add_dim(
"nv_a", globuf[3] );
518 NcDim* dimNVB = ncMap.add_dim(
"nv_b", globuf[4] );
521 NcVar* varYCA = ncMap.add_var(
"yc_a", ncDouble, dimNA );
522 NcVar* varYCB = ncMap.add_var(
"yc_b", ncDouble, dimNB );
524 NcVar* varXCA = ncMap.add_var(
"xc_a", ncDouble, dimNA );
525 NcVar* varXCB = ncMap.add_var(
"xc_b", ncDouble, dimNB );
527 NcVar* varYVA = ncMap.add_var(
"yv_a", ncDouble, dimNA, dimNVA );
528 NcVar* varYVB = ncMap.add_var(
"yv_b", ncDouble, dimNB, dimNVB );
530 NcVar* varXVA = ncMap.add_var(
"xv_a", ncDouble, dimNA, dimNVA );
531 NcVar* varXVB = ncMap.add_var(
"xv_b", ncDouble, dimNB, dimNVB );
534 NcVar* varMaskA = ncMap.add_var(
"mask_a", ncInt, dimNA );
535 NcVar* varMaskB = ncMap.add_var(
"mask_b", ncInt, dimNB );
537 #ifdef MOAB_HAVE_NETCDFPAR
538 ncMap.enable_var_par_access( varYCA, is_independent );
539 ncMap.enable_var_par_access( varYCB, is_independent );
540 ncMap.enable_var_par_access( varXCA, is_independent );
541 ncMap.enable_var_par_access( varXCB, is_independent );
542 ncMap.enable_var_par_access( varYVA, is_independent );
543 ncMap.enable_var_par_access( varYVB, is_independent );
544 ncMap.enable_var_par_access( varXVA, is_independent );
545 ncMap.enable_var_par_access( varXVB, is_independent );
546 ncMap.enable_var_par_access( varMaskA, is_independent );
547 ncMap.enable_var_par_access( varMaskB, is_independent );
550 varYCA->add_att(
"units",
"degrees" );
551 varYCB->add_att(
"units",
"degrees" );
553 varXCA->add_att(
"units",
"degrees" );
554 varXCB->add_att(
"units",
"degrees" );
556 varYVA->add_att(
"units",
"degrees" );
557 varYVB->add_att(
"units",
"degrees" );
559 varXVA->add_att(
"units",
"degrees" );
560 varXVB->add_att(
"units",
"degrees" );
563 if( dSourceCenterLon.GetRows() != nA )
565 _EXCEPTIONT(
"Mismatch between dSourceCenterLon and nA" );
567 if( dSourceCenterLat.GetRows() != nA )
569 _EXCEPTIONT(
"Mismatch between dSourceCenterLat and nA" );
571 if( dTargetCenterLon.GetRows() != nB )
573 _EXCEPTIONT(
"Mismatch between dTargetCenterLon and nB" );
575 if( dTargetCenterLat.GetRows() != nB )
577 _EXCEPTIONT(
"Mismatch between dTargetCenterLat and nB" );
579 if( dSourceVertexLon.GetRows() != nA )
581 _EXCEPTIONT(
"Mismatch between dSourceVertexLon and nA" );
583 if( dSourceVertexLat.GetRows() != nA )
585 _EXCEPTIONT(
"Mismatch between dSourceVertexLat and nA" );
587 if( dTargetVertexLon.GetRows() != nB )
589 _EXCEPTIONT(
"Mismatch between dTargetVertexLon and nB" );
591 if( dTargetVertexLat.GetRows() != nB )
593 _EXCEPTIONT(
"Mismatch between dTargetVertexLat and nB" );
596 varYCA->set_cur( (
long)offbuf[0] );
597 varYCA->put( &( dSourceCenterLat[0] ), nA );
598 varYCB->set_cur( (
long)offbuf[1] );
599 varYCB->put( &( dTargetCenterLat[0] ), nB );
601 varXCA->set_cur( (
long)offbuf[0] );
602 varXCA->put( &( dSourceCenterLon[0] ), nA );
603 varXCB->set_cur( (
long)offbuf[1] );
604 varXCB->put( &( dTargetCenterLon[0] ), nB );
606 varYVA->set_cur( (
long)offbuf[0] );
607 varYVA->put( &( dSourceVertexLat[0][0] ), nA, nSourceNodesPerFace );
608 varYVB->set_cur( (
long)offbuf[1] );
609 varYVB->put( &( dTargetVertexLat[0][0] ), nB, nTargetNodesPerFace );
611 varXVA->set_cur( (
long)offbuf[0] );
612 varXVA->put( &( dSourceVertexLon[0][0] ), nA, nSourceNodesPerFace );
613 varXVB->set_cur( (
long)offbuf[1] );
614 varXVB->put( &( dTargetVertexLon[0][0] ), nB, nTargetNodesPerFace );
616 varMaskA->set_cur( (
long)offbuf[0] );
617 varMaskA->put( &( masksA[0] ), nA );
618 varMaskB->set_cur( (
long)offbuf[1] );
619 varMaskB->put( &( masksB[0] ), nB );
622 NcVar* varAreaA = ncMap.add_var(
"area_a", ncDouble, dimNA );
623 #ifdef MOAB_HAVE_NETCDFPAR
624 ncMap.enable_var_par_access( varAreaA, is_independent );
626 varAreaA->set_cur( (
long)offbuf[0] );
627 varAreaA->put( &( vecSourceFaceArea[0] ), nA );
629 NcVar* varAreaB = ncMap.add_var(
"area_b", ncDouble, dimNB );
630 #ifdef MOAB_HAVE_NETCDFPAR
631 ncMap.enable_var_par_access( varAreaB, is_independent );
633 varAreaB->set_cur( (
long)offbuf[1] );
634 varAreaB->put( &( vecTargetFaceArea[0] ), nB );
637 DataArray1D< int > vecRow( nS );
638 DataArray1D< int > vecCol( nS );
639 DataArray1D< double > vecS( nS );
640 DataArray1D< double > dFracA( nA );
641 DataArray1D< double > dFracB( nB );
657 #if defined( MOAB_HAVE_MPI )
658 int nAbase = ( max_col_dof + 1 ) / size;
659 int nBbase = ( max_row_dof + 1 ) / size;
661 for(
int i = 0; i < m_weightMatrix.outerSize(); ++i )
663 for( WeightMatrix::InnerIterator it( m_weightMatrix, i ); it; ++it )
665 vecRow[offset] = 1 + this->GetRowGlobalDoF( it.row() );
666 vecCol[offset] = 1 + this->GetColGlobalDoF( it.col() );
667 vecS[offset] = it.value();
669 #if defined( MOAB_HAVE_MPI )
672 int procRow = ( vecRow[offset] - 1 ) / nBbase;
673 if( procRow >= size ) procRow = size - 1;
674 int procCol = ( vecCol[offset] - 1 ) / nAbase;
675 if( procCol >= size ) procCol = size - 1;
676 int nrInd = tlValRow.
get_n();
677 tlValRow.
vi_wr[2 * nrInd] = procRow;
678 tlValRow.
vi_wr[2 * nrInd + 1] = vecRow[offset] - 1;
679 tlValRow.
vr_wr[nrInd] = vecS[offset];
681 int ncInd = tlValCol.
get_n();
682 tlValCol.
vi_wr[3 * ncInd] = procCol;
683 tlValCol.
vi_wr[3 * ncInd + 1] = vecRow[offset] - 1;
684 tlValCol.
vi_wr[3 * ncInd + 2] = vecCol[offset] - 1;
685 tlValCol.
vr_wr[ncInd] = vecS[offset];
693 #if defined( MOAB_HAVE_MPI )
696 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tlValCol, 0 );
697 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tlValRow, 0 );
703 for(
unsigned i = 0; i < tlValRow.
get_n(); i++ )
706 int gRowInd = tlValRow.
vi_wr[2 * i + 1];
707 int localIndexRow = gRowInd - nBbase * rank;
708 double wgt = tlValRow.
vr_wr[i];
709 assert( localIndexRow >= 0 );
710 assert( nB - localIndexRow > 0 );
711 dFracB[localIndexRow] += wgt;
715 std::set< int > neededRows;
716 for(
unsigned i = 0; i < tlValCol.
get_n(); i++ )
718 int rRowInd = tlValCol.
vi_wr[3 * i + 1];
719 neededRows.insert( rRowInd );
723 tgtAreaReq.
initialize( 2, 0, 0, 0, neededRows.size() );
725 for( std::set< int >::iterator sit = neededRows.begin(); sit != neededRows.end(); ++sit )
727 int neededRow = *sit;
728 int procRow = neededRow / nBbase;
729 if( procRow >= size ) procRow = size - 1;
730 int nr = tgtAreaReq.
get_n();
731 tgtAreaReq.
vi_wr[2 * nr] = procRow;
732 tgtAreaReq.
vi_wr[2 * nr + 1] = neededRow;
736 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tgtAreaReq, 0 );
741 for(
unsigned i = 0; i < tgtAreaReq.
get_n(); i++ )
743 int from_proc = tgtAreaReq.
vi_wr[2 * i];
744 int row = tgtAreaReq.
vi_wr[2 * i + 1];
745 int locaIndexRow = row - rank * nBbase;
746 double areaToSend = vecTargetFaceArea[locaIndexRow];
749 tgtAreaInfo.
vi_wr[2 * i] = from_proc;
750 tgtAreaInfo.
vi_wr[2 * i + 1] = row;
751 tgtAreaInfo.
vr_wr[i] = areaToSend;
754 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tgtAreaInfo, 0 );
756 std::map< int, double > areaAtRow;
757 for(
unsigned i = 0; i < tgtAreaInfo.
get_n(); i++ )
760 int row = tgtAreaInfo.
vi_wr[2 * i + 1];
761 areaAtRow[row] = tgtAreaInfo.
vr_wr[i];
769 for(
unsigned i = 0; i < tlValCol.
get_n(); i++ )
771 int rRowInd = tlValCol.
vi_wr[3 * i + 1];
772 int colInd = tlValCol.
vi_wr[3 * i + 2];
773 double val = tlValCol.
vr_wr[i];
774 int localColInd = colInd - rank * nAbase;
776 auto itMap = areaAtRow.find( rRowInd );
777 if( itMap != areaAtRow.end() )
779 double areaRow = itMap->second;
780 dFracA[localColInd] += val / vecSourceFaceArea[localColInd] * areaRow;
786 NcDim* dimNS = ncMap.add_dim(
"n_s", globuf[2] );
788 NcVar* varRow = ncMap.add_var(
"row", ncInt, dimNS );
789 NcVar* varCol = ncMap.add_var(
"col", ncInt, dimNS );
790 NcVar* varS = ncMap.add_var(
"S", ncDouble, dimNS );
791 #ifdef MOAB_HAVE_NETCDFPAR
792 ncMap.enable_var_par_access( varRow, is_independent );
793 ncMap.enable_var_par_access( varCol, is_independent );
794 ncMap.enable_var_par_access( varS, is_independent );
797 varRow->set_cur( (
long)offbuf[2] );
798 varRow->put( vecRow, nS );
800 varCol->set_cur( (
long)offbuf[2] );
801 varCol->put( vecCol, nS );
803 varS->set_cur( (
long)offbuf[2] );
804 varS->put( &( vecS[0] ), nS );
807 NcVar* varFracA = ncMap.add_var(
"frac_a", ncDouble, dimNA );
808 #ifdef MOAB_HAVE_NETCDFPAR
809 ncMap.enable_var_par_access( varFracA, is_independent );
811 varFracA->add_att(
"name",
"fraction of target coverage of source dof" );
812 varFracA->add_att(
"units",
"unitless" );
813 varFracA->set_cur( (
long)offbuf[0] );
814 varFracA->put( &( dFracA[0] ), nA );
816 NcVar* varFracB = ncMap.add_var(
"frac_b", ncDouble, dimNB );
817 #ifdef MOAB_HAVE_NETCDFPAR
818 ncMap.enable_var_par_access( varFracB, is_independent );
820 varFracB->add_att(
"name",
"fraction of source coverage of target dof" );
821 varFracB->add_att(
"units",
"unitless" );
822 varFracB->set_cur( (
long)offbuf[1] );
823 varFracB->put( &( dFracB[0] ), nB );
837 serializeSparseMatrix( m_weightMatrix,
"map_operator_" + std::to_string( rank ) +
".txt" );
855 DataArray1D< double > vecSourceFaceArea, vecTargetFaceArea;
856 DataArray1D< double > dSourceCenterLon, dSourceCenterLat, dTargetCenterLon, dTargetCenterLat;
857 DataArray2D< double > dSourceVertexLon, dSourceVertexLat, dTargetVertexLon, dTargetVertexLat;
858 if( m_srcDiscType == DiscretizationType_FV || m_srcDiscType == DiscretizationType_PCLOUD )
860 this->InitializeCoordinatesFromMeshFV(
861 *m_meshInput, dSourceCenterLon, dSourceCenterLat, dSourceVertexLon, dSourceVertexLat,
863 m_remapper->max_source_edges );
865 vecSourceFaceArea.Allocate( m_meshInput->vecFaceArea.GetRows() );
866 for(
unsigned i = 0; i < m_meshInput->vecFaceArea.GetRows(); ++i )
867 vecSourceFaceArea[i] = m_meshInput->vecFaceArea[i];
871 DataArray3D< double > dataGLLJacobianSrc;
872 this->InitializeCoordinatesFromMeshFE( *m_meshInput, m_nDofsPEl_Src, dataGLLNodesSrc, dSourceCenterLon,
873 dSourceCenterLat, dSourceVertexLon, dSourceVertexLat );
876 GenerateMetaData( *m_meshInput, m_nDofsPEl_Src,
false , dataGLLNodesSrc, dataGLLJacobianSrc );
878 if( m_srcDiscType == DiscretizationType_CGLL )
880 GenerateUniqueJacobian( dataGLLNodesSrc, dataGLLJacobianSrc, vecSourceFaceArea );
884 GenerateDiscontinuousJacobian( dataGLLJacobianSrc, vecSourceFaceArea );
888 if( m_destDiscType == DiscretizationType_FV || m_destDiscType == DiscretizationType_PCLOUD )
890 this->InitializeCoordinatesFromMeshFV(
891 *m_meshOutput, dTargetCenterLon, dTargetCenterLat, dTargetVertexLon, dTargetVertexLat,
893 m_remapper->max_target_edges );
895 vecTargetFaceArea.Allocate( m_meshOutput->vecFaceArea.GetRows() );
896 for(
unsigned i = 0; i < m_meshOutput->vecFaceArea.GetRows(); ++i )
897 vecTargetFaceArea[i] = m_meshOutput->vecFaceArea[i];
901 DataArray3D< double > dataGLLJacobianDest;
902 this->InitializeCoordinatesFromMeshFE( *m_meshOutput, m_nDofsPEl_Dest, dataGLLNodesDest, dTargetCenterLon,
903 dTargetCenterLat, dTargetVertexLon, dTargetVertexLat );
906 GenerateMetaData( *m_meshOutput, m_nDofsPEl_Dest,
false , dataGLLNodesDest, dataGLLJacobianDest );
908 if( m_destDiscType == DiscretizationType_CGLL )
910 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobianDest, vecTargetFaceArea );
914 GenerateDiscontinuousJacobian( dataGLLJacobianDest, vecTargetFaceArea );
919 int tot_src_ents = m_remapper->m_source_entities.size();
920 int tot_tgt_ents = m_remapper->m_target_entities.size();
921 int tot_src_size = dSourceCenterLon.GetRows();
922 int tot_tgt_size = m_dTargetCenterLon.GetRows();
923 int tot_vsrc_size = dSourceVertexLon.GetRows() * dSourceVertexLon.GetColumns();
924 int tot_vtgt_size = m_dTargetVertexLon.GetRows() * m_dTargetVertexLon.GetColumns();
926 const int weightMatNNZ = m_weightMatrix.nonZeros();
927 moab::Tag tagMapMetaData, tagMapIndexRow, tagMapIndexCol, tagMapValues, srcEleIDs, tgtEleIDs;
930 "Retrieving tag handles failed" );
933 "Retrieving tag handles failed" );
936 "Retrieving tag handles failed" );
939 "Retrieving tag handles failed" );
942 "Retrieving tag handles failed" );
945 "Retrieving tag handles failed" );
949 "Retrieving tag handles failed" );
952 "Retrieving tag handles failed" );
953 moab::Tag tagSrcCoordsCLon, tagSrcCoordsCLat, tagTgtCoordsCLon, tagTgtCoordsCLat;
957 "Retrieving tag handles failed" );
961 "Retrieving tag handles failed" );
965 "Retrieving tag handles failed" );
969 "Retrieving tag handles failed" );
970 moab::Tag tagSrcCoordsVLon, tagSrcCoordsVLat, tagTgtCoordsVLon, tagTgtCoordsVLat;
974 "Retrieving tag handles failed" );
978 "Retrieving tag handles failed" );
982 "Retrieving tag handles failed" );
986 "Retrieving tag handles failed" );
988 if( m_iSourceMask.IsAttached() )
993 "Retrieving tag handles failed" );
995 if( m_iTargetMask.IsAttached() )
1000 "Retrieving tag handles failed" );
1003 std::vector< int > smatrowvals( weightMatNNZ ), smatcolvals( weightMatNNZ );
1004 std::vector< double > smatvals( weightMatNNZ );
1007 for(
int k = 0, offset = 0; k < m_weightMatrix.outerSize(); ++k )
1009 for( moab::TempestOnlineMap::WeightMatrix::InnerIterator it( m_weightMatrix, k ); it; ++it, ++offset )
1011 smatrowvals[offset] = this->GetRowGlobalDoF( it.row() );
1012 smatcolvals[offset] = this->GetColGlobalDoF( it.col() );
1013 smatvals[offset] = it.value();
1022 int maxrow = 0, maxcol = 0;
1023 std::vector< int > src_global_dofs( tot_src_size ), tgt_global_dofs( tot_tgt_size );
1024 for(
int i = 0; i < tot_src_size; ++i )
1026 src_global_dofs[i] = srccol_gdofmap[i];
1027 maxcol = ( src_global_dofs[i] > maxcol ) ? src_global_dofs[i] : maxcol;
1030 for(
int i = 0; i < tot_tgt_size; ++i )
1032 tgt_global_dofs[i] = row_gdofmap[i];
1033 maxrow = ( tgt_global_dofs[i] > maxrow ) ? tgt_global_dofs[i] : maxrow;
1058 int map_disc_details[6];
1059 map_disc_details[0] = m_nDofsPEl_Src;
1060 map_disc_details[1] = m_nDofsPEl_Dest;
1061 map_disc_details[2] = ( m_srcDiscType == DiscretizationType_FV || m_srcDiscType == DiscretizationType_PCLOUD
1063 : ( m_srcDiscType == DiscretizationType_CGLL ? 1 : 2 ) );
1064 map_disc_details[3] = ( m_destDiscType == DiscretizationType_FV || m_destDiscType == DiscretizationType_PCLOUD
1066 : ( m_destDiscType == DiscretizationType_CGLL ? 1 : 2 ) );
1067 map_disc_details[4] = ( m_bConserved ? 1 : 0 );
1068 map_disc_details[5] = m_iMonotonicity;
1070 #ifdef MOAB_HAVE_MPI
1071 int loc_smatmetadata[13] = { tot_src_ents,
1073 m_remapper->max_source_edges,
1074 m_remapper->max_target_edges,
1078 map_disc_details[0],
1079 map_disc_details[1],
1080 map_disc_details[2],
1081 map_disc_details[3],
1082 map_disc_details[4],
1083 map_disc_details[5] };
1084 MB_CHK_SET_ERR( m_interface->tag_set_data( tagMapMetaData, &m_meshOverlapSet, 1, &loc_smatmetadata[0] ),
1085 "Setting local tag data failed" );
1086 int glb_smatmetadata[13] = { 0,
1093 map_disc_details[0],
1094 map_disc_details[1],
1095 map_disc_details[2],
1096 map_disc_details[3],
1097 map_disc_details[4],
1098 map_disc_details[5] };
1100 tot_src_ents, tot_tgt_ents, weightMatNNZ, m_remapper->max_source_edges, m_remapper->max_target_edges,
1102 int glb_buf[4] = { 0, 0, 0, 0 };
1103 MPI_Reduce( &loc_buf[0], &glb_buf[0], 3, MPI_INT, MPI_SUM, 0, m_pcomm->comm() );
1104 glb_smatmetadata[0] = glb_buf[0];
1105 glb_smatmetadata[1] = glb_buf[1];
1106 glb_smatmetadata[6] = glb_buf[2];
1107 MPI_Reduce( &loc_buf[3], &glb_buf[0], 4, MPI_INT, MPI_MAX, 0, m_pcomm->comm() );
1108 glb_smatmetadata[2] = glb_buf[0];
1109 glb_smatmetadata[3] = glb_buf[1];
1110 glb_smatmetadata[4] = glb_buf[2];
1111 glb_smatmetadata[5] = glb_buf[3];
1113 int glb_smatmetadata[13] = { tot_src_ents,
1115 m_remapper->max_source_edges,
1116 m_remapper->max_target_edges,
1120 map_disc_details[0],
1121 map_disc_details[1],
1122 map_disc_details[2],
1123 map_disc_details[3],
1124 map_disc_details[4],
1125 map_disc_details[5] };
1128 glb_smatmetadata[4]++;
1129 glb_smatmetadata[5]++;
1133 std::cout <<
" " << this->rank <<
" Writing remap weights with size [" << glb_smatmetadata[4] <<
" X "
1134 << glb_smatmetadata[5] <<
"] and NNZ = " << glb_smatmetadata[6] << std::endl;
1136 MB_CHK_SET_ERR( m_interface->tag_set_data( tagMapMetaData, &root_set, 1, &glb_smatmetadata[0] ),
1137 "Setting local tag data failed" );
1141 const int numval = weightMatNNZ;
1142 const void* smatrowvals_d = smatrowvals.data();
1143 const void* smatcolvals_d = smatcolvals.data();
1144 const void* smatvals_d = smatvals.data();
1145 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagMapIndexRow, &m_meshOverlapSet, 1, &smatrowvals_d, &numval ),
1146 "Setting local tag data failed" );
1147 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagMapIndexCol, &m_meshOverlapSet, 1, &smatcolvals_d, &numval ),
1148 "Setting local tag data failed" );
1149 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagMapValues, &m_meshOverlapSet, 1, &smatvals_d, &numval ),
1150 "Setting local tag data failed" );
1153 const void* srceleidvals_d = src_global_dofs.data();
1154 const void* tgteleidvals_d = tgt_global_dofs.data();
1155 dsize = src_global_dofs.size();
1156 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( srcEleIDs, &m_meshOverlapSet, 1, &srceleidvals_d, &dsize ),
1157 "Setting local tag data failed" );
1158 dsize = tgt_global_dofs.size();
1159 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tgtEleIDs, &m_meshOverlapSet, 1, &tgteleidvals_d, &dsize ),
1160 "Setting local tag data failed" );
1163 const void* srcareavals_d = vecSourceFaceArea;
1164 const void* tgtareavals_d = vecTargetFaceArea;
1165 dsize = tot_src_size;
1166 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( srcAreaValues, &m_meshOverlapSet, 1, &srcareavals_d, &dsize ),
1167 "Setting local tag data failed" );
1168 dsize = tot_tgt_size;
1169 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tgtAreaValues, &m_meshOverlapSet, 1, &tgtareavals_d, &dsize ),
1170 "Setting local tag data failed" );
1173 const void* srccoordsclonvals_d = &dSourceCenterLon[0];
1174 const void* srccoordsclatvals_d = &dSourceCenterLat[0];
1175 dsize = dSourceCenterLon.GetRows();
1176 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagSrcCoordsCLon, &m_meshOverlapSet, 1, &srccoordsclonvals_d, &dsize ),
1177 "Setting local tag data failed" );
1178 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagSrcCoordsCLat, &m_meshOverlapSet, 1, &srccoordsclatvals_d, &dsize ),
1179 "Setting local tag data failed" );
1180 const void* tgtcoordsclonvals_d = &m_dTargetCenterLon[0];
1181 const void* tgtcoordsclatvals_d = &m_dTargetCenterLat[0];
1182 dsize = vecTargetFaceArea.GetRows();
1183 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagTgtCoordsCLon, &m_meshOverlapSet, 1, &tgtcoordsclonvals_d, &dsize ),
1184 "Setting local tag data failed" );
1185 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagTgtCoordsCLat, &m_meshOverlapSet, 1, &tgtcoordsclatvals_d, &dsize ),
1186 "Setting local tag data failed" );
1189 const void* srccoordsvlonvals_d = &( dSourceVertexLon[0][0] );
1190 const void* srccoordsvlatvals_d = &( dSourceVertexLat[0][0] );
1191 dsize = dSourceVertexLon.GetRows() * dSourceVertexLon.GetColumns();
1192 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagSrcCoordsVLon, &m_meshOverlapSet, 1, &srccoordsvlonvals_d, &dsize ),
1193 "Setting local tag data failed" );
1194 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagSrcCoordsVLat, &m_meshOverlapSet, 1, &srccoordsvlatvals_d, &dsize ),
1195 "Setting local tag data failed" );
1196 const void* tgtcoordsvlonvals_d = &( m_dTargetVertexLon[0][0] );
1197 const void* tgtcoordsvlatvals_d = &( m_dTargetVertexLat[0][0] );
1198 dsize = m_dTargetVertexLon.GetRows() * m_dTargetVertexLon.GetColumns();
1199 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagTgtCoordsVLon, &m_meshOverlapSet, 1, &tgtcoordsvlonvals_d, &dsize ),
1200 "Setting local tag data failed" );
1201 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tagTgtCoordsVLat, &m_meshOverlapSet, 1, &tgtcoordsvlatvals_d, &dsize ),
1202 "Setting local tag data failed" );
1205 if( m_iSourceMask.IsAttached() )
1207 const void* srcmaskvals_d = m_iSourceMask;
1208 dsize = m_iSourceMask.GetRows();
1209 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( srcMaskValues, &m_meshOverlapSet, 1, &srcmaskvals_d, &dsize ),
1210 "Setting local tag data failed" );
1213 if( m_iTargetMask.IsAttached() )
1215 const void* tgtmaskvals_d = m_iTargetMask;
1216 dsize = m_iTargetMask.GetRows();
1217 MB_CHK_SET_ERR( m_interface->tag_set_by_ptr( tgtMaskValues, &m_meshOverlapSet, 1, &tgtmaskvals_d, &dsize ),
1218 "Setting local tag data failed" );
1221 #ifdef MOAB_HAVE_MPI
1222 const char* writeOptions = ( this->size > 1 ?
"PARALLEL=WRITE_PART" :
"" );
1224 const char* writeOptions =
"";
1229 MB_CHK_ERR( m_interface->write_file( strOutputFile.c_str(), NULL, writeOptions, sets, 1 ) );
1231 #ifdef WRITE_SCRIP_FILE
1233 sstr << ctx.outFilename.substr( 0, lastindex ) <<
"_" << proc_id <<
".nc";
1234 std::map< std::string, std::string > mapAttributes;
1235 mapAttributes[
"Creator"] =
"MOAB mbtempest workflow";
1236 if( !ctx.proc_id ) std::cout <<
"Writing offline map to file: " << sstr.str() << std::endl;
1237 this->Write( strOutputFile.c_str(), mapAttributes, NcFile::Netcdf4 );
1248 std::cout << message <<
" [";
1249 int pos = barWidth * progress;
1250 for(
int i = 0; i < barWidth; ++i )
1259 std::cout <<
"] " << int( progress * 100.0 ) <<
" %\r";
1324 std::FILE* fp = std::fopen( path,
"rb" );
1327 unsigned char magic[8] = { 0 };
1328 const size_t nread = std::fread( magic, 1,
sizeof( magic ), fp );
1334 if( magic[0] ==
'C' && magic[1] ==
'D' && magic[2] ==
'F' )
1336 if( magic[3] == 0x01 || magic[3] == 0x02 || magic[3] == 0x05 )
return MAP_FORMAT_CLASSIC;
1340 if( nread >= 8 && magic[0] == 0x89 && magic[1] ==
'H' && magic[2] ==
'D' && magic[3] ==
'F' && magic[4] == 0x0D &&
1341 magic[5] == 0x0A && magic[6] == 0x1A && magic[7] == 0x0A )
1350 const std::vector< int >& owned_dof_ids,
1352 std::vector< double >& vecAreaA,
1354 std::vector< double >& vecAreaB,
1357 NcError
error( NcError::silent_nonfatal );
1359 const bool readAreaA = ( 1 == arearead || 3 == arearead );
1360 const bool readAreaB = ( 2 == arearead || 3 == arearead );
1373 std::vector< int > vecRow, vecCol;
1374 std::vector< double > vecS;
1382 #ifdef MOAB_HAVE_MPI
1386 int dims[3] = { 0, 0, 0 };
1390 NcFile ncDims( strSource, NcFile::ReadOnly );
1391 if( !ncDims.is_valid() )
1393 _EXCEPTION1(
"Unable to open input map file \"%s\" on rank 0", strSource );
1395 NcDim* dimNA = ncDims.get_dim(
"n_a" );
1396 NcDim* dimNB = ncDims.get_dim(
"n_b" );
1397 NcDim* dimNS = ncDims.get_dim(
"n_s" );
1398 if( !dimNA || !dimNB || !dimNS )
1400 _EXCEPTION1(
"Map file \"%s\" missing required dimensions (n_a, n_b, n_s)", strSource );
1402 dims[0] =
static_cast< int >( dimNA->size() );
1403 dims[1] =
static_cast< int >( dimNB->size() );
1404 dims[2] =
static_cast< int >( dimNS->size() );
1408 MPI_Bcast( dims, 3, MPI_INT, 0, m_pcomm->comm() );
1414 bool useBufferedRead =
true;
1419 #if defined( MOAB_HAVE_PNETCDF ) || defined( MOAB_HAVE_NETCDFPAR )
1420 useBufferedRead =
false;
1425 if( useBufferedRead )
1437 std::cout <<
" [ReadParallelMap]: Using buffered read strategy for " << nS
1441 const int nNNZBytes = 2 *
sizeof( int ) +
sizeof(
double );
1443 const int nBufferedReads =
static_cast< int >( std::ceil( 1.0 * nS / nMaxPerChunk ) );
1446 const int nRowPerPart = nB / size;
1447 const int nRowRemainder = nB % size;
1448 std::vector< int > rowOwnership( size );
1449 rowOwnership[0] = nRowPerPart + nRowRemainder;
1450 for(
int ip = 1; ip < size; ++ip )
1451 rowOwnership[ip] = rowOwnership[ip - 1] + nRowPerPart;
1454 NcFile* ncMap =
nullptr;
1455 NcVar *varRowF =
nullptr, *varColF =
nullptr, *varSF =
nullptr;
1456 NcVar *varAreaAF =
nullptr, *varAreaBF =
nullptr;
1460 ncMap =
new NcFile( strSource, NcFile::ReadOnly );
1461 if( !ncMap->is_valid() )
1463 _EXCEPTION1(
"Unable to open map file \"%s\" for buffered read", strSource );
1465 varRowF = ncMap->get_var(
"row" );
1466 varColF = ncMap->get_var(
"col" );
1467 varSF = ncMap->get_var(
"S" );
1468 if( readAreaA ) varAreaAF = ncMap->get_var(
"area_a" );
1469 if( readAreaB ) varAreaBF = ncMap->get_var(
"area_b" );
1473 std::vector< int > localRows, localCols;
1474 std::vector< double > localVals;
1475 localRows.reserve( nS / size + nS / ( size * 10 ) );
1476 localCols.reserve( nS / size + nS / ( size * 10 ) );
1477 localVals.reserve( nS / size + nS / ( size * 10 ) );
1479 int nEntriesRemaining = nS;
1480 long fileOffset = 0;
1482 for(
int iRead = 0; iRead < nBufferedReads; ++iRead )
1485 std::vector< int > chunkRow, chunkCol;
1486 std::vector< double > chunkS;
1487 std::vector< std::vector< int > > entriesPerProc( size );
1488 std::vector< int > nPerProc( size, 0 );
1492 int chunkSize = std::min( nEntriesRemaining, nMaxPerChunk );
1494 chunkRow.resize( chunkSize );
1495 chunkCol.resize( chunkSize );
1496 chunkS.resize( chunkSize );
1498 varRowF->set_cur( fileOffset );
1499 varRowF->get( chunkRow.data(), chunkSize );
1500 varColF->set_cur( fileOffset );
1501 varColF->get( chunkCol.data(), chunkSize );
1502 varSF->set_cur( fileOffset );
1503 varSF->get( chunkS.data(), chunkSize );
1506 for(
int ip = 0; ip < size; ++ip )
1507 entriesPerProc[ip].reserve( chunkSize / size + 64 );
1509 for(
int i = 0; i < chunkSize; ++i )
1511 int rowIdx = chunkRow[i] - 1;
1513 if( rowIdx >= rowOwnership[0] )
1516 owner =
static_cast< int >(
1517 std::upper_bound( rowOwnership.begin(), rowOwnership.end(), rowIdx ) -
1518 rowOwnership.begin() );
1519 if( owner >= size ) owner = size - 1;
1521 entriesPerProc[owner].push_back( i );
1524 fileOffset += chunkSize;
1525 nEntriesRemaining -= chunkSize;
1527 for(
int ip = 0; ip < size; ++ip )
1528 nPerProc[ip] =
static_cast< int >( entriesPerProc[ip].size() );
1533 MPI_Scatter( nPerProc.data(), 1, MPI_INT, &nRecv, 1, MPI_INT, 0, m_pcomm->comm() );
1538 std::vector< MPI_Request > requests;
1539 requests.reserve( 2 * ( size - 1 ) );
1542 std::vector< std::vector< int > > sendRowCol( size );
1543 std::vector< std::vector< double > > sendVals( size );
1545 for(
int ip = 1; ip < size; ++ip )
1547 const int nDPP = nPerProc[ip];
1550 sendRowCol[ip].resize( 2 * nDPP );
1551 sendVals[ip].resize( nDPP );
1552 for(
int j = 0; j < nDPP; ++j )
1554 int idx = entriesPerProc[ip][j];
1555 sendRowCol[ip][2 * j] = chunkRow[idx];
1556 sendRowCol[ip][2 * j + 1] = chunkCol[idx];
1557 sendVals[ip][j] = chunkS[idx];
1560 MPI_Request rqRC, rqV;
1561 MPI_Isend( sendRowCol[ip].data(), 2 * nDPP, MPI_INT, ip,
1562 iRead * 1000, m_pcomm->comm(), &rqRC );
1563 MPI_Isend( sendVals[ip].data(), nDPP, MPI_DOUBLE, ip,
1564 iRead * 1000 + 1, m_pcomm->comm(), &rqV );
1565 requests.push_back( rqRC );
1566 requests.push_back( rqV );
1571 for(
int j = 0; j < nRecv; ++j )
1573 int idx = entriesPerProc[0][j];
1574 localRows.push_back( chunkRow[idx] );
1575 localCols.push_back( chunkCol[idx] );
1576 localVals.push_back( chunkS[idx] );
1580 if( !requests.empty() )
1582 std::vector< MPI_Status > stats( requests.size() );
1583 MPI_Waitall(
static_cast< int >( requests.size() ), requests.data(), stats.data() );
1586 else if( nRecv > 0 )
1589 std::vector< int > recvRowCol( 2 * nRecv );
1590 std::vector< double > recvVals( nRecv );
1593 MPI_Irecv( recvRowCol.data(), 2 * nRecv, MPI_INT, 0,
1594 iRead * 1000, m_pcomm->comm(), &rqs[0] );
1595 MPI_Irecv( recvVals.data(), nRecv, MPI_DOUBLE, 0,
1596 iRead * 1000 + 1, m_pcomm->comm(), &rqs[1] );
1599 MPI_Waitall( 2, rqs, sts );
1601 for(
int j = 0; j < nRecv; ++j )
1603 localRows.push_back( recvRowCol[2 * j] );
1604 localCols.push_back( recvRowCol[2 * j + 1] );
1605 localVals.push_back( recvVals[j] );
1609 MPI_Barrier( m_pcomm->comm() );
1620 auto scatter_trivial = [](
int Ntot,
int rk,
int sz, NcVar* var, std::vector< double >& localSlice,
1622 const int base = Ntot / sz;
1623 const int rem = Ntot % sz;
1624 const int localCount = ( rk == sz - 1 ) ? ( base + rem ) : base;
1625 localSlice.resize( localCount );
1628 std::vector< double > fullBuf( Ntot );
1632 var->get( fullBuf.data(), Ntot );
1635 std::copy( fullBuf.begin(), fullBuf.begin() + localCount, localSlice.begin() );
1636 for(
int dst = 1; dst < sz; dst++ )
1638 const int dstCount = ( dst == sz - 1 ) ? ( base + rem ) : base;
1639 MPI_Send( fullBuf.data() + dst * base, dstCount, MPI_DOUBLE, dst, 0xA9EA, comm );
1644 MPI_Recv( localSlice.data(), localCount, MPI_DOUBLE, 0, 0xA9EA, comm, MPI_STATUS_IGNORE );
1647 if( readAreaA ) scatter_trivial( nA, rank, size, varAreaAF, vecAreaA, m_pcomm->comm() );
1648 if( readAreaB ) scatter_trivial( nB, rank, size, varAreaBF, vecAreaB, m_pcomm->comm() );
1657 localSize =
static_cast< int >( localRows.size() );
1658 vecRow.swap( localRows );
1659 vecCol.swap( localCols );
1660 vecS.swap( localVals );
1680 std::cout <<
" [ReadParallelMap]: Using direct parallel read for " << nS
1686 MPI_Bcast( &fileFormat, 1, MPI_INT, 0, m_pcomm->comm() );
1691 if( !isClassic && !isNetCDF4 )
1693 _EXCEPTION1(
"Map file \"%s\" is not in a recognized NetCDF format "
1694 "(expected classic CDF-1/2/5 or NetCDF-4/HDF5)",
1699 localSize = nS / size;
1700 long offsetRead = rank * localSize;
1701 if( rank == size - 1 ) localSize += nS % size;
1703 vecRow.resize( localSize );
1704 vecCol.resize( localSize );
1705 vecS.resize( localSize );
1708 int localSizeA = nA / size;
1709 long offsetReadA = rank * localSizeA;
1710 if( rank == size - 1 ) localSizeA += nA % size;
1712 int localSizeB = nB / size;
1713 long offsetReadB = rank * localSizeB;
1714 if( rank == size - 1 ) localSizeB += nB % size;
1716 if( readAreaA ) vecAreaA.resize( localSizeA );
1717 if( readAreaB ) vecAreaB.resize( localSizeB );
1719 bool parReadDone =
false;
1724 #ifdef MOAB_HAVE_PNETCDF
1728 int pnc_err = ncmpi_open( m_pcomm->comm(), strSource, NC_NOWRITE, MPI_INFO_NULL, &ncfile );
1729 if( pnc_err == NC_NOERR )
1732 std::cout <<
" [ReadParallelMap]: Reading classic-format file via PNetCDF\n";
1734 MPI_Offset start =
static_cast< MPI_Offset
>( offsetRead );
1735 MPI_Offset count =
static_cast< MPI_Offset
>( localSize );
1738 ERR_PARNC( ncmpi_inq_varid( ncfile,
"S", &varid ) );
1739 ERR_PARNC( ncmpi_get_vara_double_all( ncfile, varid, &start, &count, vecS.data() ) );
1740 ERR_PARNC( ncmpi_inq_varid( ncfile,
"row", &varid ) );
1741 ERR_PARNC( ncmpi_get_vara_int_all( ncfile, varid, &start, &count, vecRow.data() ) );
1742 ERR_PARNC( ncmpi_inq_varid( ncfile,
"col", &varid ) );
1743 ERR_PARNC( ncmpi_get_vara_int_all( ncfile, varid, &start, &count, vecCol.data() ) );
1747 MPI_Offset startA =
static_cast< MPI_Offset
>( offsetReadA );
1748 MPI_Offset countA =
static_cast< MPI_Offset
>( localSizeA );
1749 ERR_PARNC( ncmpi_inq_varid( ncfile,
"area_a", &varid ) );
1750 ERR_PARNC( ncmpi_get_vara_double_all( ncfile, varid, &startA, &countA, vecAreaA.data() ) );
1754 MPI_Offset startB =
static_cast< MPI_Offset
>( offsetReadB );
1755 MPI_Offset countB =
static_cast< MPI_Offset
>( localSizeB );
1756 ERR_PARNC( ncmpi_inq_varid( ncfile,
"area_b", &varid ) );
1757 ERR_PARNC( ncmpi_get_vara_double_all( ncfile, varid, &startB, &countB, vecAreaB.data() ) );
1759 ERR_PARNC( ncmpi_close( ncfile ) );
1765 #ifdef MOAB_HAVE_NETCDFPAR
1772 std::cout <<
" [ReadParallelMap]: PNetCDF unavailable; reading classic-format "
1773 "file via parallel NetCDF (NETCDFPAR)\n";
1774 ParNcFile ncMap( m_pcomm->comm(), MPI_INFO_NULL, strSource, NcFile::ReadOnly, NcFile::Classic );
1775 if( ncMap.is_valid() )
1777 NcVar* varRowP = ncMap.get_var(
"row" );
1778 NcVar* varColP = ncMap.get_var(
"col" );
1779 NcVar* varSP = ncMap.get_var(
"S" );
1780 ncMap.enable_var_par_access( varRowP,
true );
1781 ncMap.enable_var_par_access( varColP,
true );
1782 ncMap.enable_var_par_access( varSP,
true );
1784 varRowP->set_cur( offsetRead );
1785 varRowP->get( vecRow.data(), localSize );
1786 varColP->set_cur( offsetRead );
1787 varColP->get( vecCol.data(), localSize );
1788 varSP->set_cur( offsetRead );
1789 varSP->get( vecS.data(), localSize );
1793 NcVar* varAreaAP = ncMap.get_var(
"area_a" );
1794 ncMap.enable_var_par_access( varAreaAP,
true );
1795 varAreaAP->set_cur( offsetReadA );
1796 varAreaAP->get( vecAreaA.data(), localSizeA );
1800 NcVar* varAreaBP = ncMap.get_var(
"area_b" );
1801 ncMap.enable_var_par_access( varAreaBP,
true );
1802 varAreaBP->set_cur( offsetReadB );
1803 varAreaBP->get( vecAreaB.data(), localSizeB );
1813 _EXCEPTION1(
"Classic-format map file \"%s\" cannot be read in parallel: "
1814 "neither PNetCDF nor parallel NetCDF (NETCDFPAR) is configured "
1815 "(or both failed to open the file)",
1822 #ifdef MOAB_HAVE_NETCDFPAR
1825 std::cout <<
" [ReadParallelMap]: Reading NetCDF-4/HDF5 file via parallel NetCDF\n";
1826 ParNcFile ncMap( m_pcomm->comm(), MPI_INFO_NULL, strSource, NcFile::ReadOnly, NcFile::Netcdf4 );
1827 if( ncMap.is_valid() )
1829 NcVar* varRowP = ncMap.get_var(
"row" );
1830 NcVar* varColP = ncMap.get_var(
"col" );
1831 NcVar* varSP = ncMap.get_var(
"S" );
1832 ncMap.enable_var_par_access( varRowP,
true );
1833 ncMap.enable_var_par_access( varColP,
true );
1834 ncMap.enable_var_par_access( varSP,
true );
1836 varRowP->set_cur( offsetRead );
1837 varRowP->get( vecRow.data(), localSize );
1838 varColP->set_cur( offsetRead );
1839 varColP->get( vecCol.data(), localSize );
1840 varSP->set_cur( offsetRead );
1841 varSP->get( vecS.data(), localSize );
1845 NcVar* varAreaAP = ncMap.get_var(
"area_a" );
1846 ncMap.enable_var_par_access( varAreaAP,
true );
1847 varAreaAP->set_cur( offsetReadA );
1848 varAreaAP->get( vecAreaA.data(), localSizeA );
1852 NcVar* varAreaBP = ncMap.get_var(
"area_b" );
1853 ncMap.enable_var_par_access( varAreaBP,
true );
1854 varAreaBP->set_cur( offsetReadB );
1855 varAreaBP->get( vecAreaB.data(), localSizeB );
1865 _EXCEPTION1(
"NetCDF-4/HDF5 map file \"%s\" cannot be read in parallel: "
1866 "parallel NetCDF (NETCDFPAR) is not configured "
1867 "(PNetCDF cannot read NetCDF-4 files)",
1879 std::cout <<
" [ReadParallelMap]: Using serial read (single process)\n";
1880 NcFile ncMap( strSource, NcFile::ReadOnly );
1881 if( !ncMap.is_valid() )
1883 _EXCEPTION1(
"Unable to open input map file \"%s\"", strSource );
1886 NcDim* dimNS = ncMap.get_dim(
"n_s" );
1887 NcDim* dimNA = ncMap.get_dim(
"n_a" );
1888 NcDim* dimNB = ncMap.get_dim(
"n_b" );
1889 if( !dimNS || !dimNA || !dimNB )
1891 _EXCEPTION1(
"Map file \"%s\" missing required dimensions", strSource );
1893 nS =
static_cast< int >( dimNS->size() );
1894 nA =
static_cast< int >( dimNA->size() );
1895 nB =
static_cast< int >( dimNB->size() );
1898 vecRow.resize( nS );
1899 vecCol.resize( nS );
1902 NcVar* varRowS = ncMap.get_var(
"row" );
1903 NcVar* varColS = ncMap.get_var(
"col" );
1904 NcVar* varSS = ncMap.get_var(
"S" );
1905 varRowS->get( vecRow.data(), nS );
1906 varColS->get( vecCol.data(), nS );
1907 varSS->get( vecS.data(), nS );
1911 vecAreaA.resize( nA );
1912 NcVar* varAreaAS = ncMap.get_var(
"area_a" );
1913 if( varAreaAS ) varAreaAS->get( vecAreaA.data(), nA );
1917 vecAreaB.resize( nB );
1918 NcVar* varAreaBS = ncMap.get_var(
"area_b" );
1919 if( varAreaBS ) varAreaBS->get( vecAreaB.data(), nB );
1936 #ifdef MOAB_HAVE_EIGEN3
1938 typedef Eigen::Triplet< double >
Triplet;
1939 std::vector< Triplet > tripletList;
1941 #ifdef MOAB_HAVE_MPI
1945 const int nPerPart = nB / size;
1952 for(
int i = 0; i < localSize; i++ )
1954 int rowval = vecRow[i] - 1;
1955 int colval = vecCol[i] - 1;
1956 int to_proc = rowval / nPerPart;
1957 if( to_proc >= size ) to_proc = size - 1;
1959 int n = tl->
get_n();
1960 tl->
vi_wr[3 * n] = to_proc;
1961 tl->
vi_wr[3 * n + 1] = rowval;
1962 tl->
vi_wr[3 * n + 2] = colval;
1963 tl->
vr_wr[n] = vecS[i];
1968 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, *tl, 0 );
1970 if( owned_dof_ids.size() > 0 )
1974 tl_re.
initialize( 2, 0, 0, 0, owned_dof_ids.size() );
1978 for(
size_t i = 0; i < owned_dof_ids.size(); i++ )
1981 int dof_val = owned_dof_ids[i] - 1;
1982 to_proc = dof_val / nPerPart;
1983 if( to_proc == size ) to_proc = size - 1;
1985 int n = tl_re.
get_n();
1986 tl_re.
vi_wr[2 * n] = to_proc;
1987 tl_re.
vi_wr[2 * n + 1] = dof_val;
1991 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, tl_re, 0 );
1994 sort_buffer.buffer_init( tl_re.
get_n() );
1995 tl_re.
sort( 1, &sort_buffer );
1999 std::map< int, int > startDofIndex, endDofIndex;
2001 if( tl_re.
get_n() > 0 )
2003 dofVal = tl_re.
vi_rd[1];
2005 startDofIndex[dofVal] = 0;
2006 endDofIndex[dofVal] = 0;
2007 for(
unsigned k = 1; k < tl_re.
get_n(); k++ )
2009 int newDof = tl_re.
vi_rd[2 * k + 1];
2010 if( dofVal == newDof )
2012 endDofIndex[dofVal] = k;
2017 startDofIndex[dofVal] = k;
2018 endDofIndex[dofVal] = k;
2035 for(
unsigned k = 0; k < tl->
get_n(); k++ )
2037 int valDof = tl->
vi_rd[3 * k + 1];
2038 if( startDofIndex.find( valDof ) == startDofIndex.end() )
continue;
2039 for(
int ire = startDofIndex[valDof]; ire <= endDofIndex[valDof]; ire++ )
2041 int to_proc = tl_re.
vi_rd[2 * ire];
2042 int n = tl_back->
get_n();
2043 tl_back->
vi_wr[3 * n] = to_proc;
2044 tl_back->
vi_wr[3 * n + 1] = tl->
vi_rd[3 * k + 1];
2045 tl_back->
vi_wr[3 * n + 2] = tl->
vi_rd[3 * k + 2];
2052 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, *tl_back, 0 );
2060 std::set< int > rowSet;
2061 std::set< int > colSet;
2063 int n = tl->
get_n();
2064 for(
int i = 0; i < n; i++ )
2066 const int vecRowValue = tl->
vi_wr[3 * i + 1];
2067 const int vecColValue = tl->
vi_wr[3 * i + 2];
2068 rowSet.insert( vecRowValue );
2069 colSet.insert( vecColValue );
2072 row_gdofmap.resize( rowSet.size() );
2073 for(
auto setIt : rowSet )
2075 row_gdofmap[
index] = setIt;
2076 rowMap[setIt] =
index++;
2078 m_nTotDofs_Dest =
index;
2080 col_gdofmap.resize( colSet.size() );
2081 for(
auto setIt : colSet )
2083 col_gdofmap[
index] = setIt;
2084 colMap[setIt] =
index++;
2086 m_nTotDofs_SrcCov =
index;
2088 tripletList.reserve( n );
2089 for(
int i = 0; i < n; i++ )
2091 const int vecRowValue = tl->
vi_wr[3 * i + 1];
2092 const int vecColValue = tl->
vi_wr[3 * i + 2];
2093 double value = tl->
vr_wr[i];
2094 tripletList.emplace_back( rowMap[vecRowValue], colMap[vecColValue], value );
2102 std::set< int > rowSet;
2103 std::set< int > colSet;
2105 for(
int i = 0; i < nS; i++ )
2107 const int vecRowValue = vecRow[i] - 1;
2108 const int vecColValue = vecCol[i] - 1;
2109 rowSet.insert( vecRowValue );
2110 colSet.insert( vecColValue );
2114 row_gdofmap.resize( rowSet.size() );
2115 for(
auto setIt : rowSet )
2117 row_gdofmap[
index] = setIt;
2118 rowMap[setIt] =
index++;
2120 m_nTotDofs_Dest =
index;
2122 col_gdofmap.resize( colSet.size() );
2123 for(
auto setIt : colSet )
2125 col_gdofmap[
index] = setIt;
2126 colMap[setIt] =
index++;
2128 m_nTotDofs_SrcCov =
index;
2130 tripletList.reserve( nS );
2131 for(
int i = 0; i < nS; i++ )
2133 const int vecRowValue = vecRow[i] - 1;
2134 const int vecColValue = vecCol[i] - 1;
2135 double value = vecS[i];
2136 tripletList.emplace_back( rowMap[vecRowValue], colMap[vecColValue], value );
2140 m_weightMatrix.resize( m_nTotDofs_Dest, m_nTotDofs_SrcCov );
2141 m_rowVector.resize( m_nTotDofs_Dest );
2142 m_colVector.resize( m_nTotDofs_SrcCov );
2143 m_nTotDofs_Src = m_nTotDofs_SrcCov;
2147 m_nTotDofs_SrcGlobal = nA;
2148 m_weightMatrix.setFromTriplets( tripletList.begin(), tripletList.end() );
2150 m_rowVector.setZero();
2151 m_colVector.setZero();
2153 serializeSparseMatrix( m_weightMatrix,
"map_operator_" + std::to_string( rank ) +
".txt" );
2159 m_nDofsPEl_Dest = 1;