21 #include <unordered_map>
41 #ifdef MOAB_HAVE_TEMPESTREMAP
43 #include "FiniteElementTools.h"
44 #include "GaussLobattoQuadrature.h"
56 if( initialize_fsets )
75 MPI_Initialized( &flagInit );
78 assert( m_pcomm !=
nullptr );
79 rank = m_pcomm->rank();
80 size = m_pcomm->size();
85 AnnounceOnlyOutputOnRankZero();
145 #ifdef MOAB_HAVE_NETCDF
148 std::string inputFilename,
149 TempestMeshType type )
154 return load_tempest_mesh_private( inputFilename, &
m_source );
159 return load_tempest_mesh_private( inputFilename, &
m_target );
164 return load_tempest_mesh_private( inputFilename, &
m_overlap );
168 MB_CHK_SET_ERR( MB_FAILURE,
"Invalid IntersectionContext context provided" );
172 ErrorCode TempestRemapper::load_tempest_mesh_private( std::string inputFilename, Mesh** tempest_mesh )
175 if( outputEnabled ) std::cout <<
"\nLoading TempestRemap Mesh object from file = " << inputFilename <<
" ...\n";
180 NcError
error( NcError::silent_nonfatal );
185 if( outputEnabled ) std::cout <<
"Loading mesh ...\n";
186 Mesh* mesh =
new Mesh( inputFilename );
187 mesh->RemoveZeroEdges();
188 if( outputEnabled ) std::cout <<
"----------------\n";
193 if( outputEnabled ) std::cout <<
"Validating mesh ...\n";
195 if( outputEnabled ) std::cout <<
"-------------------\n";
201 if( outputEnabled ) std::cout <<
"Constructing edge map on mesh ...\n";
202 mesh->ConstructEdgeMap(
false );
203 if( outputEnabled ) std::cout <<
"---------------------------------\n";
206 if( tempest_mesh ) *tempest_mesh = mesh;
208 catch( Exception& e )
210 std::cout <<
"TempestRemap ERROR: " << e.ToString() <<
"\n";
228 if( outputEnabled ) std::cout <<
"Converting (source) TempestRemap Mesh object to MOAB representation ...\n";
234 if( outputEnabled ) std::cout <<
"Converting (target) TempestRemap Mesh object to MOAB representation ...\n";
240 if( outputEnabled ) std::cout <<
"Converting (overlap) TempestRemap Mesh object to MOAB representation ...\n";
245 MB_CHK_SET_ERR( MB_FAILURE,
"Invalid IntersectionContext context provided" );
249 #define NEW_CONVERT_LOGIC
251 #ifdef NEW_CONVERT_LOGIC
259 const NodeVector& nodes = mesh->nodes;
260 const FaceVector& faces = mesh->faces;
271 std::vector< double* > arrays;
272 std::vector< int > gidsv( nodes.size() );
274 MB_CHK_SET_ERR(
iface->get_node_coords( 3, nodes.size(), 0, startv, arrays ),
"Can't get node coords" );
275 for(
unsigned iverts = 0; iverts < nodes.size(); ++iverts )
277 const Node& node = nodes[iverts];
278 arrays[0][iverts] = node.x;
279 arrays[1][iverts] = node.y;
280 arrays[2][iverts] = node.z;
281 gidsv[iverts] = iverts + 1;
283 Range mbverts( startv, startv + nodes.size() - 1 );
290 Tag srcParentTag, tgtParentTag;
291 std::vector< int > srcParent( faces.size(), -1 ), tgtParent( faces.size(), -1 );
292 std::vector< int > gidse( faces.size(), -1 );
293 bool storeParentInfo = ( mesh->vecSourceFaceIx.size() > 0 );
295 if( storeParentInfo )
300 "can't create positive tag" );
304 "can't create negative tag" );
315 dbgprint.printf( 0,
"..Mesh size: Nodes [%zu] Elements [%zu].\n", nodes.size(), faces.size() );
316 std::vector< EntityHandle > mbcells( faces.size() );
317 unsigned ntris = 0, nquads = 0, npolys = 0;
318 std::vector< EntityHandle > conn( 16 );
320 for(
unsigned ifaces = 0; ifaces < faces.size(); ++ifaces )
322 const Face&
face = faces[ifaces];
323 const unsigned num_v_per_elem =
face.edges.size();
325 for(
unsigned iedges = 0; iedges < num_v_per_elem; ++iedges )
327 conn[iedges] = startv +
face.edges[iedges].node[0];
330 switch( num_v_per_elem )
336 "Can't get element connectivity" );
343 "Can't get element connectivity" );
351 "Can't get element connectivity" );
356 gidse[ifaces] = ifaces + 1;
358 if( storeParentInfo )
360 srcParent[ifaces] = mesh->vecSourceFaceIx[ifaces] + 1;
361 tgtParent[ifaces] = mesh->vecTargetFaceIx[ifaces] + 1;
365 if( ntris )
dbgprint.printf( 0,
"....Triangular Elements [%u].\n", ntris );
366 if( nquads )
dbgprint.printf( 0,
"....Quadrangular Elements [%u].\n", nquads );
367 if( npolys )
dbgprint.printf( 0,
"....Polygonal Elements [%u].\n", npolys );
372 "Can't set global_id tag" );
374 MB_CHK_SET_ERR( m_pcomm->assign_global_ids(mesh_set, 2, 1,
false,
true,
false ),
"Unable to set global IDs" );
377 if( storeParentInfo )
380 "Can't set tag data" );
382 "Can't set tag data" );
386 std::copy( mbcells.begin(), mbcells.end(),
range_inserter( entities ) );
389 if( vertices ) *vertices = mbverts;
404 const NodeVector& nodes = mesh->nodes;
405 const FaceVector& faces = mesh->faces;
408 dbgprint.set_prefix(
"[TempestToMOAB]: " );
416 std::vector< double* > arrays;
417 std::vector< int > gidsv( nodes.size() );
419 MB_CHK_SET_ERR(
iface->get_node_coords( 3, nodes.size(), 0, startv, arrays ),
"Can't get node coords" );
420 for(
unsigned iverts = 0; iverts < nodes.size(); ++iverts )
422 const Node& node = nodes[iverts];
423 arrays[0][iverts] = node.x;
424 arrays[1][iverts] = node.y;
425 arrays[2][iverts] = node.z;
426 gidsv[iverts] = iverts + 1;
428 Range mbverts( startv, startv + nodes.size() - 1 );
435 Tag srcParentTag, tgtParentTag;
436 std::vector< int > srcParent, tgtParent;
437 bool storeParentInfo = ( mesh->vecSourceFaceIx.size() > 0 );
439 if( storeParentInfo )
444 "can't create positive tag" );
448 "can't create negative tag" );
459 dbgprint.printf( 0,
"..Mesh size: Nodes [%zu] Elements [%zu].\n", nodes.size(), faces.size() );
460 const int NMAXPOLYEDGES = 15;
461 std::vector< unsigned > nPolys( NMAXPOLYEDGES, 0 );
462 std::vector< std::vector< int > > typeNSeqs( NMAXPOLYEDGES );
463 for(
unsigned ifaces = 0; ifaces < faces.size(); ++ifaces )
465 const int iType = faces[ifaces].edges.size();
467 typeNSeqs[iType].push_back( ifaces );
470 for(
unsigned iType = 0; iType < NMAXPOLYEDGES; ++iType )
472 if( !nPolys[iType] )
continue;
474 const unsigned num_v_per_elem = iType;
479 switch( num_v_per_elem )
483 dbgprint.printf( 0,
"....Block %d: Triangular Elements [%u].\n", iBlock++, nPolys[iType] );
485 "Can't get element connectivity" );
489 dbgprint.printf( 0,
"....Block %d: Quadrilateral Elements [%u].\n", iBlock++, nPolys[iType] );
492 "Can't get element connectivity" );
496 dbgprint.printf( 0,
"....Block %d: Polygonal [%u] Elements [%u].\n", iBlock++, iType,
500 "Can't get element connectivity" );
504 Range mbcells( starte, starte + nPolys[iType] - 1 );
507 if( storeParentInfo )
509 srcParent.resize( mbcells.size(), -1 );
510 tgtParent.resize( mbcells.size(), -1 );
513 std::vector< int > gids( typeNSeqs[iType].
size() );
514 for(
unsigned ifaces = 0, offset = 0; ifaces < typeNSeqs[iType].size(); ++ifaces )
516 const int fIndex = typeNSeqs[iType][ifaces];
517 const Face&
face = faces[fIndex];
519 for(
unsigned iedges = 0; iedges <
face.edges.size(); ++iedges )
521 conn[offset++] = startv +
face.edges[iedges].node[0];
524 if( storeParentInfo )
526 srcParent[ifaces] = mesh->vecSourceFaceIx[fIndex] + 1;
527 tgtParent[ifaces] = mesh->vecTargetFaceIx[fIndex] + 1;
530 gids[ifaces] = typeNSeqs[iType][ifaces] + 1;
538 "Can't update adjacencies" );
545 if( storeParentInfo )
548 "Can't set tag data" );
550 "Can't set tag data" );
552 entities.
merge( mbcells );
556 if( vertices ) *vertices = mbverts;
572 "Can't convert source mesh to TempestRemap format" );
578 "Can't convert source coverage mesh to TempestRemap format" );
584 "Can't convert target mesh to TempestRemap format" );
601 if( outputEnabled )
dbgprint.printf( 0,
"Converting (source) MOAB to TempestRemap Mesh representation ...\n" );
604 "Can't convert source mesh to Tempest" );
614 dbgprint.printf( 0,
"Converting (covering source) MOAB to TempestRemap Mesh representation ...\n" );
617 "Can't convert convering source mesh to TempestRemap format" );
622 if( outputEnabled )
dbgprint.printf( 0,
"Converting (target) MOAB to TempestRemap Mesh representation ...\n" );
625 "Can't convert target mesh to Tempest" );
631 if( outputEnabled )
dbgprint.printf( 0,
"Converting (overlap) MOAB to TempestRemap Mesh representation ...\n" );
636 MB_CHK_SET_ERR( MB_FAILURE,
"Invalid IntersectionContext context provided" );
647 NodeVector& nodes = mesh->nodes;
648 FaceVector& faces = mesh->faces;
653 const size_t nelems = elems.
size();
656 faces.resize( nelems );
661 if( verts.
size() == 0 )
667 std::map< EntityHandle, int > indxMap;
668 bool useRange =
true;
677 std::vector< int > globIds( nelems );
680 std::vector< size_t > sortedIdx;
683 sortedIdx.resize( nelems );
685 std::iota( sortedIdx.begin(), sortedIdx.end(), 0 );
688 std::sort( sortedIdx.begin(), sortedIdx.end(),
689 [&globIds](
size_t i1,
size_t i2 ) { return globIds[i1] < globIds[i2]; } );
702 while( connectface[nnodesf - 2] == connectface[nnodesf - 1] && nnodesf > 3 )
705 face.edges.resize( nnodesf );
706 for(
int iverts = 0; iverts < nnodesf; ++iverts )
708 int indx = ( useRange ? verts.
index( connectface[iverts] ) : indxMap[connectface[iverts]] );
710 face.SetNode( iverts, indx );
714 unsigned nnodes = verts.
size();
715 nodes.resize( nnodes );
718 std::vector< double > coordx( nnodes ), coordy( nnodes ), coordz( nnodes );
720 for(
unsigned inode = 0; inode < nnodes; ++inode )
722 Node& node = nodes[inode];
723 node.x = coordx[inode];
724 node.y = coordy[inode];
725 node.z = coordz[inode];
731 mesh->RemoveCoincidentNodes();
732 mesh->RemoveZeroEdges();
754 if( std::get< 1 >( a ) == std::get< 1 >( b ) )
755 return std::get< 2 >( a ) < std::get< 2 >( b );
757 return std::get< 1 >( a ) < std::get< 1 >( b );
762 sharedGhostEntities.
clear();
769 MB_CHK_SET_ERR( m_interface->get_entities_by_dimension( m_overlap_set, 2, allents ),
770 "Getting entities dim 2 failed" );
774 std::vector< int > ghFlags( allents.
size() );
775 MB_CHK_ERR( m_interface->tag_get_handle(
"ORIG_PROC", ghostTag ) );
776 MB_CHK_ERR( m_interface->tag_get_data( ghostTag, allents, &ghFlags[0] ) );
777 for(
unsigned i = 0; i < allents.
size(); ++i )
778 if( ghFlags[i] >= 0 )
779 sharedents.
insert( allents[i] );
781 allents =
subtract( allents, sharedents );
786 MB_CHK_SET_ERR( m_interface->get_connectivity( allents, ownedverts ),
"Deleting entities dim 0 failed" );
787 MB_CHK_SET_ERR( m_interface->get_connectivity( sharedents, sharedverts ),
"Deleting entities dim 0 failed" );
788 sharedverts =
subtract( sharedverts, ownedverts );
792 sharedGhostEntities.
merge( sharedents );
808 std::vector< std::array< int, 3 > > sorted_overlap_order( n_overlap_entitites,
809 std::array< int, 3 >( { -1, -1, -1 } ) );
811 Tag srcParentTag, tgtParentTag;
815 m_overlap->vecTargetFaceIx.resize( n_overlap_entitites );
816 m_overlap->vecSourceFaceIx.resize( n_overlap_entitites );
834 auto build_index = [](
const std::vector< int >& gids ) {
835 std::unordered_map< int, int >
index;
836 index.reserve( gids.size() * 2 );
837 for(
size_t i = 0; i < gids.size(); i++ )
838 index.emplace( gids[i],
static_cast< int >( i ) );
842 std::unordered_map< int, int > index_src, index_tgt;
845 index_src = build_index( gids_src );
846 index_tgt = build_index( gids_tgt );
849 auto find_lid = [
this](
const std::unordered_map< int, int >&
index,
int gid ) ->
int {
851 auto it =
index.find( gid );
852 return ( it !=
index.end() ? it->second : -1 );
855 std::vector< int > ghFlags;
859 ghFlags.resize( n_overlap_entitites );
865 std::vector< int > rbids_src( n_overlap_entitites ), rbids_tgt( n_overlap_entitites );
869 for(
size_t ix = 0; ix < n_overlap_entitites; ++ix )
871 std::get< 0 >( sorted_overlap_order[ix] ) = ix;
872 std::get< 1 >( sorted_overlap_order[ix] ) = find_lid( index_src, rbids_src[ix] );
873 assert( std::get< 1 >( sorted_overlap_order[ix] ) >= 0 );
880 std::get< 2 >( sorted_overlap_order[ix] ) = -1;
883 std::get< 2 >( sorted_overlap_order[ix] ) = find_lid( index_tgt, rbids_tgt[ix] );
887 std::sort( sorted_overlap_order.begin(), sorted_overlap_order.end(),
IntPairComparator );
889 for(
unsigned ie = 0; ie < n_overlap_entitites; ++ie )
891 m_overlap->vecSourceFaceIx[ie] = std::get< 1 >( sorted_overlap_order[ie] );
892 m_overlap->vecTargetFaceIx[ie] = std::get< 2 >( sorted_overlap_order[ie] );
897 faces.resize( n_overlap_entitites );
903 std::map< EntityHandle, int > indxMap;
912 const unsigned iface = std::get< 0 >( sorted_overlap_order[ifac] );
913 Face&
face = faces[ifac];
921 face.edges.resize( nnodesf );
922 for(
int iverts = 0; iverts < nnodesf; ++iverts )
924 int indx = indxMap[connectface[iverts]];
926 face.SetNode( iverts, indx );
930 sorted_overlap_order.clear();
932 unsigned nnodes = verts.
size();
934 nodes.resize( nnodes );
937 std::vector< double > coordx( nnodes ), coordy( nnodes ), coordz( nnodes );
939 for(
unsigned inode = 0; inode < nnodes; ++inode )
941 Node& node = nodes[inode];
942 node.x = coordx[inode];
943 node.y = coordy[inode];
944 node.z = coordz[inode];
969 const bool fAllParallel,
970 const bool fInputConcave,
971 const bool fOutputConcave )
977 if( is_root && size == 1 )
979 this->m_source->CalculateFaceAreas( fInputConcave );
980 this->m_target->CalculateFaceAreas( fOutputConcave );
985 this->m_source->CalculateFaceAreas( fInputConcave );
986 this->m_covering_source->CalculateFaceAreas( fInputConcave );
987 this->m_target->CalculateFaceAreas( fOutputConcave );
992 this->m_source->CalculateFaceAreas( fInputConcave );
993 this->m_target->CalculateFaceAreas( fOutputConcave );
999 #ifdef MOAB_HAVE_NETCDF
1000 this->m_overlap->Write( strOutputFileName.c_str(), NcFile::Netcdf4 );
1002 if( is_root ) std::cout <<
"NetCDF is not configured. Intersection mesh write will be skipped...\n";
1037 #ifndef MOAB_HAVE_MPI
1040 const int dimension,
1041 const int start_id )
1051 int idoffset = start_id;
1052 std::vector< int > gid( entities.
size() );
1053 for(
unsigned i = 0; i < entities.
size(); ++i )
1054 gid[i] = idoffset++;
1067 return std::pow( lhs.x - rhs.x, 2.0 ) + std::pow( lhs.y - rhs.y, 2.0 ) + std::pow( lhs.z - rhs.z, 2.0 );
1073 const std::string& dofTagName,
1076 const int csResolution = std::sqrt( ntot_elements / 6.0 );
1077 if( csResolution * csResolution * 6 != ntot_elements )
return MB_INVALID_SIZE;
1082 if( GenerateCSMesh( csMesh, csResolution,
"",
"NetCDF4" ) )
1084 "Failed to generate CS mesh through TempestRemap" );
1087 if( this->
GenerateMeshMetadata( csMesh, ntot_elements, ents, secondary_ents, dofTagName, nP ) )
1088 MB_CHK_SET_ERR( moab::MB_FAILURE,
"Failed in call to GenerateMeshMetadata" );
1094 const int ntot_elements,
1097 const std::string& dofTagName,
1101 bool created =
false;
1104 "Failed creating DoF tag" );
1107 int nElements =
static_cast< int >( csMesh.faces.size() );
1112 DataArray3D< int > dataGLLnodes;
1113 dataGLLnodes.Allocate( nP, nP, nElements );
1115 std::map< Node, int > mapNodes;
1116 std::map< Node, moab::EntityHandle > mapLocalMBNodes;
1119 DataArray1D< double > dG;
1120 DataArray1D< double > dW;
1121 GaussLobattoQuadrature::GetPoints( nP, 0.0, 1.0, dG, dW );
1124 if( secondary_ents ) entities.
insert( secondary_ents->
begin(), secondary_ents->
end() );
1126 for(
unsigned iel = 0; iel < entities.
size(); ++iel )
1130 Node elCentroid( elcoords[0], elcoords[1], elcoords[2] );
1131 mapLocalMBNodes.insert( std::pair< Node, moab::EntityHandle >( elCentroid, eh ) );
1140 int* dofIDs =
new int[nP * nP];
1143 for(
int k = 0; k < nElements; k++ )
1145 const Face&
face = csMesh.faces[k];
1146 const NodeVector& nodes = csMesh.nodes;
1148 if(
face.edges.size() != 4 )
1150 _EXCEPTIONT(
"Mesh must only contain quadrilateral elements" );
1154 centroid.x = centroid.y = centroid.z = 0.0;
1155 for(
unsigned l = 0; l <
face.edges.size(); ++l )
1157 centroid.x += nodes[
face[l]].x;
1158 centroid.y += nodes[
face[l]].y;
1159 centroid.z += nodes[
face[l]].z;
1161 const double factor = 1.0 /
face.edges.size();
1162 centroid.x *= factor;
1163 centroid.y *= factor;
1164 centroid.z *= factor;
1166 bool locElem =
false;
1168 if( mapLocalMBNodes.find( centroid ) != mapLocalMBNodes.end() )
1171 current_eh = mapLocalMBNodes[centroid];
1174 for(
int j = 0; j < nP; j++ )
1176 for(
int i = 0; i < nP; i++ )
1191 const double& dAlpha = dG[i];
1192 const double& dBeta = dG[j];
1195 double dXc = nodes[
face[0]].x * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1196 nodes[
face[1]].x * dAlpha * ( 1.0 - dBeta ) + nodes[
face[2]].x * dAlpha * dBeta +
1197 nodes[
face[3]].x * ( 1.0 - dAlpha ) * dBeta;
1199 double dYc = nodes[
face[0]].y * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1200 nodes[
face[1]].y * dAlpha * ( 1.0 - dBeta ) + nodes[
face[2]].y * dAlpha * dBeta +
1201 nodes[
face[3]].y * ( 1.0 - dAlpha ) * dBeta;
1203 double dZc = nodes[
face[0]].z * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1204 nodes[
face[1]].z * dAlpha * ( 1.0 - dBeta ) + nodes[
face[2]].z * dAlpha * dBeta +
1205 nodes[
face[3]].z * ( 1.0 - dAlpha ) * dBeta;
1207 double dR = sqrt( dXc * dXc + dYc * dYc + dZc * dZc );
1210 nodeGLL.x = dXc / dR;
1211 nodeGLL.y = dYc / dR;
1212 nodeGLL.z = dZc / dR;
1215 std::map< Node, int >::const_iterator iter = mapNodes.find( nodeGLL );
1216 if( iter == mapNodes.end() )
1219 int ixNode =
static_cast< int >( mapNodes.size() );
1220 mapNodes.insert( std::pair< Node, int >( nodeGLL, ixNode ) );
1221 dataGLLnodes[j][i][k] = ixNode + 1;
1225 dataGLLnodes[j][i][k] = iter->second + 1;
1228 dofIDs[j * nP + i] = dataGLLnodes[j][i][k];
1235 "Failed to tag_set_data for DoFs" );
1241 mapLocalMBNodes.clear();
1252 const char* mesh_name,
1253 std::string& error_message )
1259 const char* what = ( 0 == dimension ?
"vertex" :
"element" );
1261 std::vector< int > gids( ents.
size(), -1 );
1268 for(
size_t i = 0; i < gids.size(); ++i )
1271 if( !n_bad ) first_bad = gids[i];
1277 std::ostringstream os;
1278 os << mesh_name <<
" mesh has " << n_bad <<
" of " << ents.
size() <<
" " << what
1279 <<
" entities with a non-positive GLOBAL_ID (first bad value = " << first_bad <<
")";
1280 if( n_bad == ents.
size() )
1281 os <<
"; the GLOBAL_ID tag is most likely absent, so every entry is the tag default";
1282 error_message = os.str();
1288 std::vector< int > sorted( gids );
1289 std::sort( sorted.begin(), sorted.end() );
1290 std::vector< int >::iterator dup = std::adjacent_find( sorted.begin(), sorted.end() );
1291 if( dup != sorted.end() )
1293 const size_t n_unique = std::distance( sorted.begin(), std::unique( sorted.begin(), sorted.end() ) );
1294 std::ostringstream os;
1295 os << mesh_name <<
" mesh has duplicate " << what <<
" GLOBAL_IDs: " << ents.
size() <<
" entities but only "
1296 << n_unique <<
" distinct ids (e.g. id " << *dup <<
" appears more than once)";
1297 error_message = os.str();
1317 const char* names[2] = {
"source",
"target" };
1319 std::string message;
1321 for(
int im = 0; im < 2 && !local_bad; ++im )
1323 if( !sets[im] )
continue;
1324 for(
int dim = ( check_vertices ? 0 : 2 ); dim <= 2; dim += 2 )
1334 int global_bad = local_bad;
1335 #ifdef MOAB_HAVE_MPI
1340 MPI_Allreduce( &local_bad, &global_bad, 1, MPI_INT, MPI_MAX, m_pcomm->comm() );
1347 std::cout <<
"[ERROR] rank " <<
rank <<
": " << message << std::endl;
1349 std::cout <<
"[ERROR] invalid GLOBAL_IDs detected on another rank" << std::endl;
1352 MB_SET_ERR( MB_FAILURE,
"Invalid GLOBAL_ID tags on input meshes; refusing to proceed. "
1353 "Ensure both meshes carry unique, strictly positive GLOBAL_IDs on "
1354 "vertices and elements (e.g. re-partition with 'mbpart -j', or read "
1355 "SCRIP/NetCDF sources in parallel so ids are assigned)." );
1368 int nb_ghost_layers )
1370 if( nb_ghost_layers >= 1 ) gnomonic =
false;
1388 #ifdef MOAB_HAVE_MPI
1389 mbintx->set_parallel_comm( m_pcomm );
1399 #ifdef MOAB_HAVE_MPI
1405 "Can't create new set" );
1409 std::stringstream filename;
1410 filename <<
"covering" <<
rank <<
".h5m";
1412 std::stringstream targetFile;
1413 targetFile <<
"target" <<
rank <<
".h5m";
1433 #ifdef MOAB_HAVE_MPI
1447 const bool outputEnabled = ( this->
rank == 0 );
1449 dbgprint.
set_prefix(
"[ComputeOverlapMesh]: " );
1469 bool concaveMeshA =
false, concaveMeshB =
false;
1474 "exact", concaveMeshA, concaveMeshB,
true,
false ) )
1475 MB_CHK_SET_ERR( MB_FAILURE,
"TempestRemap: cannot compute the intersection of meshes on the sphere" );
1482 if( outputEnabled )
dbgprint.printf( 0,
"Computing intersection mesh with the Kd-tree search algorithm" );
1484 "Can't compute the intersection of meshes on the sphere with kd-tree" );
1489 dbgprint.printf( 0,
"Computing intersection mesh with the advancing-front propagation algorithm" );
1491 "Can't compute the intersection of meshes on the sphere" );
1494 #ifdef MOAB_HAVE_MPI
1498 std::stringstream ffc, fft, ffo;
1499 ffc <<
"cover_" <<
rank <<
".h5m";
1500 fft <<
"target_" <<
rank <<
".h5m";
1501 ffo <<
"intx_" <<
rank <<
".h5m";
1514 std::map< int, int > loc_gid_to_lid_covsrc;
1515 std::vector< int > gids( covEnts.
size(), -1 );
1520 for(
unsigned ie = 0; ie < gids.size(); ++ie )
1522 assert( gids[ie] > 0 );
1523 loc_gid_to_lid_covsrc[gids[ie]] = ie;
1526 Range intxCov, intxCells;
1536 assert( srcParent >= 0 );
1537 intxCov.
insert( covEnts[loc_gid_to_lid_covsrc[srcParent]] );
1560 MB_CHK_ERR(
mb->get_connectivity( eh, conn, num_nodes ) );
1569 "Unable to find skin" );
1574 MB_CHK_ERR(
mb->get_connectivity( *it, conn, len,
false ) );
1575 for(
int ie = 0; ie < len; ++ie )
1577 std::vector< EntityHandle > adjacent_entities;
1579 for(
auto ent : adjacent_entities )
1580 notNeededCovCells.
erase( ent );
1585 std::string(
"sourcecoveragemesh_p" + std::to_string(
rank ) +
".h5m" ).c_str(),
1596 std::cout <<
" total participating elements in the covering set: " << intxCov.
size() <<
"\n";
1597 std::cout <<
" remove from coverage set elements that are not intersected: " << notNeededCovCells.
size()
1636 #ifdef MOAB_HAVE_MPI
1660 Range boundaryEdges;
1661 MB_CHK_ERR( skinner.find_skin( 0, this->m_target_entities,
false, boundaryEdges ) );
1665 Range boundaryCells;
1675 std::stringstream ffs;
1676 ffs <<
"boundaryCells_0" <<
rank <<
".h5m";
1683 std::set< int > targetBoundaryIds;
1689 "Can't get global id tag on target cell" );
1690 if( tid < 0 ) std::cout <<
" incorrect id for a target cell\n";
1691 targetBoundaryIds.insert( tid );
1697 std::set< int > affectedSourceCellsIds;
1698 Tag targetParentTag, sourceParentTag;
1701 for(
Range::iterator it = overlapCells.begin(); it != overlapCells.end(); ++it )
1704 int targetParentID, sourceParentID;
1706 if( targetBoundaryIds.find( targetParentID ) != targetBoundaryIds.end() )
1710 affectedSourceCellsIds.insert( sourceParentID );
1719 std::map< int, EntityHandle > affectedCovCellFromID;
1725 std::set< EntityHandle > affectedCovCells;
1730 for(
Range::iterator it = covCells.begin(); it != covCells.end(); ++it )
1735 if( affectedSourceCellsIds.find( covID ) != affectedSourceCellsIds.end() )
1738 affectedCovCellFromID[covID] = covCell;
1739 affectedCovCells.insert( covCell );
1750 std::map< int, std::set< EntityHandle > > overlapCellsForTask;
1753 std::set< EntityHandle > overlapCellsToSend;
1755 for(
Range::iterator it = overlapCells.begin(); it != overlapCells.end(); ++it )
1761 if( affectedSourceCellsIds.find( sourceParentID ) != affectedSourceCellsIds.end() )
1764 EntityHandle covCell = affectedCovCellFromID[sourceParentID];
1767 overlapCellsForTask[orgTask].insert( intxCell );
1769 overlapCellsToSend.insert( intxCell );
1778 for( std::set< EntityHandle >::iterator it = overlapCellsToSend.begin(); it != overlapCellsToSend.end(); ++it )
1784 if( maxEdges < nnodes ) maxEdges = nnodes;
1790 MPI_Allreduce( &maxEdges, &globalMaxEdges, 1, MPI_INT, MPI_MAX, m_pcomm->comm() );
1792 globalMaxEdges = maxEdges;
1795 if(
is_root ) std::cout <<
"maximum number of edges for polygons to send is " << globalMaxEdges <<
"\n";
1802 for( std::set< EntityHandle >::iterator it = overlapCellsToSend.begin(); it != overlapCellsToSend.end(); ++it )
1807 for( std::set< EntityHandle >::iterator it = affectedCovCells.begin(); it != affectedCovCells.end(); ++it )
1812 std::stringstream ffs2;
1814 ffs2 <<
"affectedCells_" << m_pcomm->rank() <<
".h5m";
1827 std::map< int, std::set< EntityHandle > > verticesOverlapForTask;
1829 std::set< EntityHandle > allVerticesToSend;
1830 std::map< EntityHandle, int > allVerticesToSendMap;
1832 int numOverlapCells = 0;
1833 for( std::map<
int, std::set< EntityHandle > >::iterator it = overlapCellsForTask.begin();
1834 it != overlapCellsForTask.end(); ++it )
1836 int sendToProc = it->first;
1837 const std::set< EntityHandle >& overlapCellsToSend2 = it->second;
1839 std::set< EntityHandle > vertices;
1840 for( std::set< EntityHandle >::iterator set_it = overlapCellsToSend2.begin();
1841 set_it != overlapCellsToSend2.end(); ++set_it )
1843 int nnodes_local = 0;
1846 for(
int k = 0; k < nnodes_local; k++ )
1847 vertices.insert( conn1[k] );
1849 verticesOverlapForTask[sendToProc] = vertices;
1850 numVerts += (int)vertices.size();
1851 numOverlapCells += (int)overlapCellsToSend2.size();
1852 allVerticesToSend.insert( vertices.begin(), vertices.end() );
1856 for( std::set< EntityHandle >::iterator vert_it = allVerticesToSend.begin(); vert_it != allVerticesToSend.end();
1860 allVerticesToSendMap[vert] = j;
1866 TLv.initialize( 2, 0, 0, 3, numVerts );
1867 TLv.enableWriteAccess();
1869 for( std::map<
int, std::set< EntityHandle > >::iterator it = verticesOverlapForTask.begin();
1870 it != verticesOverlapForTask.end(); ++it )
1872 int sendToProc = it->first;
1873 const std::set< EntityHandle >& vertices = it->second;
1875 for( std::set< EntityHandle >::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2, ++i )
1877 int n = TLv.get_n();
1878 TLv.vi_wr[2 * n] = sendToProc;
1880 int indexInAllVert = allVerticesToSendMap[v];
1881 TLv.vi_wr[2 * n + 1] = indexInAllVert;
1885 TLv.vr_wr[3 * n] = coords[0];
1886 TLv.vr_wr[3 * n + 1] = coords[1];
1887 TLv.vr_wr[3 * n + 2] = coords[2];
1893 int sizeTuple = 4 + globalMaxEdges;
1895 TLc.initialize( sizeTuple, 0, 0, 0,
1898 TLc.enableWriteAccess();
1900 for( std::map<
int, std::set< EntityHandle > >::iterator it = overlapCellsForTask.begin();
1901 it != overlapCellsForTask.end(); ++it )
1903 int sendToProc = it->first;
1904 const std::set< EntityHandle >& overlapCellsToSend2 = it->second;
1906 for( std::set< EntityHandle >::const_iterator it2 = overlapCellsToSend2.begin();
1907 it2 != overlapCellsToSend2.end(); ++it2 )
1910 int sourceParentID, targetParentID;
1913 int n = TLc.get_n();
1914 TLc.vi_wr[sizeTuple * n] = sendToProc;
1915 TLc.vi_wr[sizeTuple * n + 1] = sourceParentID;
1916 TLc.vi_wr[sizeTuple * n + 2] = targetParentID;
1920 TLc.vi_wr[sizeTuple * n + 3] = nnodes;
1921 for(
int i = 0; i < nnodes; i++ )
1923 int indexVertex = allVerticesToSendMap[conn[i]];
1925 if( -1 == indexVertex )
MB_CHK_SET_ERR( MB_FAILURE,
"Can't find vertex in range of vertices to send" );
1926 TLc.vi_wr[sizeTuple * n + 4 + i] = indexVertex;
1929 for(
int i = nnodes; i < globalMaxEdges; i++ )
1930 TLc.vi_wr[sizeTuple * n + 4 + i] = 0;
1939 std::stringstream ff1;
1940 ff1 <<
"TLc_" <<
rank <<
".txt";
1941 TLc.print_to_file( ff1.str().c_str() );
1942 std::stringstream ffv;
1943 ffv <<
"TLv_" <<
rank <<
".txt";
1944 TLv.print_to_file( ffv.str().c_str() );
1946 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 );
1947 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLc, 0 );
1950 TLc.print_to_file( ff1.str().c_str() );
1951 TLv.print_to_file( ffv.str().c_str() );
1957 buffer.buffer_init( sizeTuple * TLc.get_n() * 2 );
1960 TLc.print_to_file( ff1.str().c_str() );
1971 std::map< int, std::map< int, int > > availVertexIndicesPerProcessor;
1972 int nv = TLv.get_n();
1973 for(
int i = 0; i < nv; i++ )
1976 int orgProc = TLv.vi_rd[2 * i];
1977 int indexVert = TLv.vi_rd[2 * i + 1];
1978 availVertexIndicesPerProcessor[orgProc][indexVert] = i;
1988 int n = TLc.get_n();
1989 std::map< int, int > currentProcsCount;
1993 std::map< int, std::set< int > > sourcesForTasks;
1997 int currentSourceID = TLc.vi_rd[sizeTuple * 0 + 1];
1998 int proc0 = TLc.vi_rd[sizeTuple * 0];
1999 currentProcsCount[proc0] = 1;
2001 for(
int i = 1; i < n; i++ )
2003 int proc = TLc.vi_rd[sizeTuple * i];
2004 int sourceID = TLc.vi_rd[sizeTuple * i + 1];
2005 if( sourceID == currentSourceID )
2007 if( currentProcsCount.find( proc ) == currentProcsCount.end() )
2009 currentProcsCount[proc] = 1;
2012 currentProcsCount[proc]++;
2014 if( sourceID != currentSourceID || ( ( n - 1 ) == i ) )
2018 if( currentProcsCount.size() > 1 )
2021 std::cout <<
" source element " << currentSourceID <<
" intersects with "
2022 << currentProcsCount.size() <<
" target partitions\n";
2023 for( std::map< int, int >::iterator it = currentProcsCount.begin(); it != currentProcsCount.end();
2026 int procID = it->first;
2027 int numOverCells = it->second;
2028 std::cout <<
" task:" << procID <<
" " << numOverCells <<
" cells\n";
2033 for( std::map< int, int >::iterator it1 = currentProcsCount.begin(); it1 != currentProcsCount.end();
2036 int proc1 = it1->first;
2037 sourcesForTasks[currentSourceID].insert( proc1 );
2038 for( std::map< int, int >::iterator it2 = currentProcsCount.begin();
2039 it2 != currentProcsCount.end(); ++it2 )
2041 int proc2 = it2->first;
2042 if( proc1 != proc2 ) sizeOfTLc2 += it2->second;
2047 if( sourceID != currentSourceID )
2049 currentSourceID = sourceID;
2050 currentProcsCount.clear();
2051 currentProcsCount[proc] = 1;
2060 std::cout <<
" need to initialize TLc2 with " << sizeOfTLc2 <<
" cells\n ";
2064 int sizeTuple2 = 5 + globalMaxEdges;
2067 TLc2.initialize( sizeTuple2, 0, 0, 0, sizeOfTLc2 );
2068 TLc2.enableWriteAccess();
2071 std::map< int, std::set< int > > verticesToSendForProc;
2073 for(
int i = 0; i < n; i++ )
2075 int sourceID = TLc.vi_rd[sizeTuple * i + 1];
2076 if( sourcesForTasks.find( sourceID ) != sourcesForTasks.end() )
2079 std::set< int > procs = sourcesForTasks[sourceID];
2080 if( procs.size() < 2 )
MB_CHK_SET_ERR( MB_FAILURE,
" not enough processes involved with a sourceID cell" );
2082 int orgProc = TLc.vi_rd[sizeTuple * i];
2085 std::map< int, int >& availableVerticesFromThisProc = availVertexIndicesPerProcessor[orgProc];
2086 for( std::set< int >::iterator setIt = procs.begin(); setIt != procs.end(); ++setIt )
2088 int procID = *setIt;
2091 if( procID != orgProc )
2094 int n2 = TLc2.get_n();
2095 if( n2 >= sizeOfTLc2 )
MB_CHK_SET_ERR( MB_FAILURE,
" memory overflow" );
2097 std::set< int >& indexVerticesInTLv = verticesToSendForProc[procID];
2098 TLc2.vi_wr[n2 * sizeTuple2] = procID;
2099 TLc2.vi_wr[n2 * sizeTuple2 + 1] = orgProc;
2100 TLc2.vi_wr[n2 * sizeTuple2 + 2] = sourceID;
2101 TLc2.vi_wr[n2 * sizeTuple2 + 3] = TLc.vi_rd[sizeTuple * i + 2];
2103 int nvert = TLc.vi_rd[sizeTuple * i + 3];
2104 TLc2.vi_wr[n2 * sizeTuple2 + 4] = nvert;
2109 for(
int j = 0; j < nvert; j++ )
2111 int vertexIndex = TLc.vi_rd[i * sizeTuple + 4 + j];
2113 if( availableVerticesFromThisProc.find( vertexIndex ) == availableVerticesFromThisProc.end() )
2115 MB_CHK_SET_ERR( MB_FAILURE,
" vertex index not available from processor" );
2117 TLc2.vi_wr[n2 * sizeTuple2 + 5 + j] = vertexIndex;
2118 int indexInTLv = availVertexIndicesPerProcessor[orgProc][vertexIndex];
2119 indexVerticesInTLv.insert( indexInTLv );
2122 for(
int j = nvert; j < globalMaxEdges; j++ )
2124 TLc2.vi_wr[n2 * sizeTuple2 + 5 + j] = 0;
2138 for( std::map<
int, std::set< int > >::iterator it = verticesToSendForProc.begin();
2139 it != verticesToSendForProc.end(); ++it )
2141 const std::set< int >& indexInTLvSet = it->second;
2142 numVerts2 += (int)indexInTLvSet.size();
2144 TLv2.initialize( 3, 0, 0, 3,
2146 TLv2.enableWriteAccess();
2147 for( std::map<
int, std::set< int > >::iterator it = verticesToSendForProc.begin();
2148 it != verticesToSendForProc.end(); ++it )
2150 int sendToProc = it->first;
2151 const std::set< int >& indexInTLvSet = it->second;
2153 for( std::set< int >::iterator itSet = indexInTLvSet.begin(); itSet != indexInTLvSet.end(); ++itSet )
2155 int indexInTLv = *itSet;
2156 int orgProc = TLv.vi_rd[2 * indexInTLv];
2157 int indexVertexInOrgProc = TLv.vi_rd[2 * indexInTLv + 1];
2158 int nv2 = TLv2.get_n();
2159 TLv2.vi_wr[3 * nv2] = sendToProc;
2160 TLv2.vi_wr[3 * nv2 + 1] = orgProc;
2161 TLv2.vi_wr[3 * nv2 + 2] = indexVertexInOrgProc;
2162 for(
int j = 0; j < 3; j++ )
2163 TLv2.vr_wr[3 * nv2 + j] =
2164 TLv.vr_rd[3 * indexInTLv + j];
2169 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv2, 0 );
2170 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLc2, 0 );
2174 std::stringstream ff2;
2175 ff2 <<
"TLc2_" <<
rank <<
".txt";
2176 TLc2.print_to_file( ff2.str().c_str() );
2177 std::stringstream ffv2;
2178 ffv2 <<
"TLv2_" <<
rank <<
".txt";
2179 TLv2.print_to_file( ffv2.str().c_str() );
2188 int nvNew = TLv2.get_n();
2196 std::map< int, std::map< int, EntityHandle > > vertexPerProcAndIndex;
2197 for(
int i = 0; i < nvNew; i++ )
2199 int orgProc = TLv2.vi_rd[3 * i + 1];
2200 int indexInVert = TLv2.vi_rd[3 * i + 2];
2201 vertexPerProcAndIndex[orgProc][indexInVert] = newVerts[i];
2209 int ne = TLc2.get_n();
2210 for(
int i = 0; i < ne; i++ )
2212 int orgProc = TLc2.vi_rd[i * sizeTuple2 + 1];
2213 int sourceID = TLc2.vi_rd[i * sizeTuple2 + 2];
2214 int targetID = TLc2.vi_wr[i * sizeTuple2 + 3];
2215 int nve = TLc2.vi_wr[i * sizeTuple2 + 4];
2216 std::vector< EntityHandle > conn;
2218 for(
int j = 0; j < nve; j++ )
2220 int indexV = TLc2.vi_wr[i * sizeTuple2 + 5 + j];
2221 EntityHandle vh = vertexPerProcAndIndex[orgProc][indexV];
2226 newPolygons.insert( polyNew );
2238 std::stringstream ffs4;
2239 ffs4 <<
"extraIntxCells" <<
rank <<
".h5m";
2259 "Trouble creating GRID_IMASK tag" );
2268 "Trouble getting GRID_IMASK tag" );
2274 "Trouble getting GRID_IMASK tag" );
2283 "Trouble getting GRID_IMASK tag" );
2289 "Trouble getting GRID_IMASK tag" );