1
14
15 #include <string>
16 #include <iostream>
17 #include <cassert>
18 #include <array>
19 #include <numeric>
20 #include <algorithm>
21
22 #include "DebugOutput.hpp"
23 #include "moab/Remapping/TempestRemapper.hpp"
24 #include "moab/ReadUtilIface.hpp"
25
26 #include "moab/MeshTopoUtil.hpp"
27 #include "AEntityFactory.hpp"
28
29
30 #include "moab/IntxMesh/Intx2MeshOnSphere.hpp"
31 #include "moab/IntxMesh/IntxUtils.hpp"
32
33 #include "moab/AdaptiveKDTree.hpp"
34 #include "moab/SpatialLocator.hpp"
35
36
37 #include "moab/Skinner.hpp"
38 #include "MBParallelConventions.h"
39
40 #ifdef MOAB_HAVE_TEMPESTREMAP
41 #include "Announce.h"
42 #include "FiniteElementTools.h"
43 #include "GaussLobattoQuadrature.h"
44 #endif
45
46
47
48 namespace moab
49 {
50
51
52
53 ErrorCode TempestRemapper::initialize( bool initialize_fsets )
54 {
55 ErrorCode rval;
56 if( initialize_fsets )
57 {
58 rval = m_interface->create_meshset( moab::MESHSET_SET, m_source_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
59 rval = m_interface->create_meshset( moab::MESHSET_SET, m_target_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
60 rval = m_interface->create_meshset( moab::MESHSET_SET, m_overlap_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
61 }
62 else
63 {
64 m_source_set = 0;
65 m_target_set = 0;
66 m_overlap_set = 0;
67 }
68
69 is_parallel = false;
70 is_root = true;
71 rank = 0;
72 size = 1;
73 #ifdef MOAB_HAVE_MPI
74 int flagInit;
75 MPI_Initialized( &flagInit );
76 if( flagInit )
77 {
78 assert( m_pcomm != nullptr );
79 rank = m_pcomm->rank();
80 size = m_pcomm->size();
81 is_root = ( rank == 0 );
82 is_parallel = ( size > 1 );
83
84 }
85 AnnounceOnlyOutputOnRankZero();
86 #endif
87
88 m_source = nullptr;
89 m_target = nullptr;
90 m_overlap = nullptr;
91 m_covering_source = nullptr;
92
93 point_cloud_source = false;
94 point_cloud_target = false;
95
96 return MB_SUCCESS;
97 }
98
99
100
101 TempestRemapper::~TempestRemapper()
102 {
103 this->clear();
104 }
105
106 ErrorCode TempestRemapper::clear()
107 {
108
109 if( m_source )
110 {
111 delete m_source;
112 m_source = nullptr;
113 }
114 if( m_target )
115 {
116 delete m_target;
117 m_target = nullptr;
118 }
119 if( m_overlap )
120 {
121 delete m_overlap;
122 m_overlap = nullptr;
123 }
124 if( m_covering_source && size > 1 )
125 {
126 delete m_covering_source;
127 m_covering_source = nullptr;
128 }
129
130 point_cloud_source = false;
131 point_cloud_target = false;
132
133 m_source_entities.clear();
134 m_source_vertices.clear();
135 m_covering_source_entities.clear();
136 m_covering_source_vertices.clear();
137 m_target_entities.clear();
138 m_target_vertices.clear();
139 m_overlap_entities.clear();
140
141
142
143
144
145
146
147 return MB_SUCCESS;
148 }
149
150
151
152 ErrorCode TempestRemapper::LoadMesh( Remapper::IntersectionContext ctx,
153 std::string inputFilename,
154 TempestMeshType type )
155 {
156 if( ctx == Remapper::SourceMesh )
157 {
158 m_source_type = type;
159 return load_tempest_mesh_private( inputFilename, &m_source );
160 }
161 else if( ctx == Remapper::TargetMesh )
162 {
163 m_target_type = type;
164 return load_tempest_mesh_private( inputFilename, &m_target );
165 }
166 else if( ctx != Remapper::DEFAULT )
167 {
168 m_overlap_type = type;
169 return load_tempest_mesh_private( inputFilename, &m_overlap );
170 }
171 else
172 {
173 MB_CHK_SET_ERR( MB_FAILURE, "Invalid IntersectionContext context provided" );
174 }
175 }
176
177 ErrorCode TempestRemapper::load_tempest_mesh_private( std::string inputFilename, Mesh** tempest_mesh )
178 {
179 const bool outputEnabled = ( TempestRemapper::verbose && is_root );
180 if( outputEnabled ) std::cout << "\nLoading TempestRemap Mesh object from file = " << inputFilename << " ...\n";
181
182 {
183 NcError error( NcError::silent_nonfatal );
184
185 try
186 {
187
188 if( outputEnabled ) std::cout << "Loading mesh ...\n";
189 Mesh* mesh = new Mesh( inputFilename );
190 mesh->RemoveZeroEdges();
191 if( outputEnabled ) std::cout << "----------------\n";
192
193
194 if( meshValidate )
195 {
196 if( outputEnabled ) std::cout << "Validating mesh ...\n";
197 mesh->Validate();
198 if( outputEnabled ) std::cout << "-------------------\n";
199 }
200
201
202 if( constructEdgeMap )
203 {
204 if( outputEnabled ) std::cout << "Constructing edge map on mesh ...\n";
205 mesh->ConstructEdgeMap( false );
206 if( outputEnabled ) std::cout << "---------------------------------\n";
207 }
208
209 if( tempest_mesh ) *tempest_mesh = mesh;
210 }
211 catch( Exception& e )
212 {
213 std::cout << "TempestRemap ERROR: " << e.ToString() << "\n";
214 return MB_FAILURE;
215 }
216 catch( ... )
217 {
218 return MB_FAILURE;
219 }
220 }
221 return MB_SUCCESS;
222 }
223
224
225
226 ErrorCode TempestRemapper::ConvertTempestMesh( Remapper::IntersectionContext ctx )
227 {
228 const bool outputEnabled = ( TempestRemapper::verbose && is_root );
229 if( ctx == Remapper::SourceMesh )
230 {
231 if( outputEnabled ) std::cout << "Converting (source) TempestRemap Mesh object to MOAB representation ...\n";
232 return convert_tempest_mesh_private( m_source_type, m_source, m_source_set, m_source_entities,
233 &m_source_vertices );
234 }
235 else if( ctx == Remapper::TargetMesh )
236 {
237 if( outputEnabled ) std::cout << "Converting (target) TempestRemap Mesh object to MOAB representation ...\n";
238 return convert_tempest_mesh_private( m_target_type, m_target, m_target_set, m_target_entities,
239 &m_target_vertices );
240 }
241 else if( ctx != Remapper::DEFAULT )
242 {
243 if( outputEnabled ) std::cout << "Converting (overlap) TempestRemap Mesh object to MOAB representation ...\n";
244 return convert_tempest_mesh_private( m_overlap_type, m_overlap, m_overlap_set, m_overlap_entities, nullptr );
245 }
246 else
247 {
248 MB_CHK_SET_ERR( MB_FAILURE, "Invalid IntersectionContext context provided" );
249 }
250 }
251
252 #define NEW_CONVERT_LOGIC
253
254 #ifdef NEW_CONVERT_LOGIC
255 ErrorCode TempestRemapper::convert_tempest_mesh_private( TempestMeshType ,
256 Mesh* mesh,
257 EntityHandle& mesh_set,
258 Range& entities,
259 Range* vertices )
260 {
261 ErrorCode rval;
262 const bool outputEnabled = ( TempestRemapper::verbose && is_root );
263 const NodeVector& nodes = mesh->nodes;
264 const FaceVector& faces = mesh->faces;
265
266 moab::DebugOutput dbgprint( std::cout, this->rank, 0 );
267 dbgprint.set_prefix( "[TempestToMOAB]: " );
268
269 ReadUtilIface* iface;
270 rval = m_interface->query_interface( iface );MB_CHK_SET_ERR( rval, "Can't get reader interface" );
271
272 Tag gidTag = m_interface->globalId_tag();
273
274
275 std::vector< double* > arrays;
276 std::vector< int > gidsv( nodes.size() );
277 EntityHandle startv;
278 rval = iface->get_node_coords( 3, nodes.size(), 0, startv, arrays );MB_CHK_SET_ERR( rval, "Can't get node coords" );
279 for( unsigned iverts = 0; iverts < nodes.size(); ++iverts )
280 {
281 const Node& node = nodes[iverts];
282 arrays[0][iverts] = node.x;
283 arrays[1][iverts] = node.y;
284 arrays[2][iverts] = node.z;
285 gidsv[iverts] = iverts + 1;
286 }
287 Range mbverts( startv, startv + nodes.size() - 1 );
288 rval = m_interface->add_entities( mesh_set, mbverts );MB_CHK_SET_ERR( rval, "Can't add entities" );
289 rval = m_interface->tag_set_data( gidTag, mbverts, &gidsv[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
290
291 gidsv.clear();
292 entities.clear();
293
294 Tag srcParentTag, tgtParentTag;
295 std::vector< int > srcParent( faces.size(), -1 ), tgtParent( faces.size(), -1 );
296 std::vector< int > gidse( faces.size(), -1 );
297 bool storeParentInfo = ( mesh->vecSourceFaceIx.size() > 0 );
298
299 if( storeParentInfo )
300 {
301 int defaultInt = -1;
302 rval = m_interface->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag,
303 MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" );
304
305 rval = m_interface->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag,
306 MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" );
307 }
308
309
310
311
312
313
314
315 {
316 if( outputEnabled )
317 dbgprint.printf( 0, "..Mesh size: Nodes [%zu] Elements [%zu].\n", nodes.size(), faces.size() );
318 std::vector< EntityHandle > mbcells( faces.size() );
319 unsigned ntris = 0, nquads = 0, npolys = 0;
320 std::vector< EntityHandle > conn( 16 );
321
322 for( unsigned ifaces = 0; ifaces < faces.size(); ++ifaces )
323 {
324 const Face& face = faces[ifaces];
325 const unsigned num_v_per_elem = face.edges.size();
326
327 for( unsigned iedges = 0; iedges < num_v_per_elem; ++iedges )
328 {
329 conn[iedges] = startv + face.edges[iedges].node[0];
330 }
331
332 switch( num_v_per_elem )
333 {
334 case 3:
335
336
337 rval = m_interface->create_element( MBTRI, &conn[0], num_v_per_elem, mbcells[ifaces] );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
338 ntris++;
339 break;
340 case 4:
341
342
343 rval = m_interface->create_element( MBQUAD, &conn[0], num_v_per_elem, mbcells[ifaces] );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
344 nquads++;
345 break;
346 default:
347
348
349
350 rval = m_interface->create_element( MBPOLYGON, &conn[0], num_v_per_elem, mbcells[ifaces] );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
351 npolys++;
352 break;
353 }
354
355 gidse[ifaces] = ifaces + 1;
356
357 if( storeParentInfo )
358 {
359 srcParent[ifaces] = mesh->vecSourceFaceIx[ifaces] + 1;
360 tgtParent[ifaces] = mesh->vecTargetFaceIx[ifaces] + 1;
361 }
362 }
363
364 if( ntris ) dbgprint.printf( 0, "....Triangular Elements [%u].\n", ntris );
365 if( nquads ) dbgprint.printf( 0, "....Quadrangular Elements [%u].\n", nquads );
366 if( npolys ) dbgprint.printf( 0, "....Polygonal Elements [%u].\n", npolys );
367
368 rval = m_interface->add_entities( mesh_set, &mbcells[0], mbcells.size() );MB_CHK_SET_ERR( rval, "Could not add entities" );
369
370 rval = m_interface->tag_set_data( gidTag, &mbcells[0], mbcells.size(), &gidse[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
371 if( storeParentInfo )
372 {
373 rval = m_interface->tag_set_data( srcParentTag, &mbcells[0], mbcells.size(), &srcParent[0] );MB_CHK_SET_ERR( rval, "Can't set tag data" );
374 rval = m_interface->tag_set_data( tgtParentTag, &mbcells[0], mbcells.size(), &tgtParent[0] );MB_CHK_SET_ERR( rval, "Can't set tag data" );
375 }
376
377
378 std::copy( mbcells.begin(), mbcells.end(), range_inserter( entities ) );
379 }
380
381 if( vertices ) *vertices = mbverts;
382
383 return MB_SUCCESS;
384 }
385
386 #else
387 ErrorCode TempestRemapper::convert_tempest_mesh_private( TempestMeshType meshType,
388 Mesh* mesh,
389 EntityHandle& mesh_set,
390 Range& entities,
391 Range* vertices )
392 {
393 ErrorCode rval;
394
395 const bool outputEnabled = ( TempestRemapper::verbose && is_root );
396 const NodeVector& nodes = mesh->nodes;
397 const FaceVector& faces = mesh->faces;
398
399 moab::DebugOutput dbgprint( std::cout, this->rank, 0 );
400 dbgprint.set_prefix( "[TempestToMOAB]: " );
401
402 ReadUtilIface* iface;
403 rval = m_interface->query_interface( iface );MB_CHK_SET_ERR( rval, "Can't get reader interface" );
404
405 Tag gidTag = m_interface->globalId_tag();
406
407
408 std::vector< double* > arrays;
409 std::vector< int > gidsv( nodes.size() );
410 EntityHandle startv;
411 rval = iface->get_node_coords( 3, nodes.size(), 0, startv, arrays );MB_CHK_SET_ERR( rval, "Can't get node coords" );
412 for( unsigned iverts = 0; iverts < nodes.size(); ++iverts )
413 {
414 const Node& node = nodes[iverts];
415 arrays[0][iverts] = node.x;
416 arrays[1][iverts] = node.y;
417 arrays[2][iverts] = node.z;
418 gidsv[iverts] = iverts + 1;
419 }
420 Range mbverts( startv, startv + nodes.size() - 1 );
421 rval = m_interface->add_entities( mesh_set, mbverts );MB_CHK_SET_ERR( rval, "Can't add entities" );
422 rval = m_interface->tag_set_data( gidTag, mbverts, &gidsv[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
423
424 gidsv.clear();
425 entities.clear();
426
427 Tag srcParentTag, tgtParentTag;
428 std::vector< int > srcParent, tgtParent;
429 bool storeParentInfo = ( mesh->vecSourceFaceIx.size() > 0 );
430
431 if( storeParentInfo )
432 {
433 int defaultInt = -1;
434 rval = m_interface->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag,
435 MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" );
436
437 rval = m_interface->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag,
438 MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" );
439 }
440
441
442
443
444
445
446
447 {
448 if( outputEnabled )
449 dbgprint.printf( 0, "..Mesh size: Nodes [%zu] Elements [%zu].\n", nodes.size(), faces.size() );
450 const int NMAXPOLYEDGES = 15;
451 std::vector< unsigned > nPolys( NMAXPOLYEDGES, 0 );
452 std::vector< std::vector< int > > typeNSeqs( NMAXPOLYEDGES );
453 for( unsigned ifaces = 0; ifaces < faces.size(); ++ifaces )
454 {
455 const int iType = faces[ifaces].edges.size();
456 nPolys[iType]++;
457 typeNSeqs[iType].push_back( ifaces );
458 }
459 int iBlock = 0;
460 for( unsigned iType = 0; iType < NMAXPOLYEDGES; ++iType )
461 {
462 if( !nPolys[iType] ) continue;
463
464 const unsigned num_v_per_elem = iType;
465 EntityHandle starte;
466 EntityHandle* conn;
467
468
469 switch( num_v_per_elem )
470 {
471 case 3:
472 if( outputEnabled )
473 dbgprint.printf( 0, "....Block %d: Triangular Elements [%u].\n", iBlock++, nPolys[iType] );
474 rval = iface->get_element_connect( nPolys[iType], num_v_per_elem, MBTRI, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
475 break;
476 case 4:
477 if( outputEnabled )
478 dbgprint.printf( 0, "....Block %d: Quadrilateral Elements [%u].\n", iBlock++, nPolys[iType] );
479 rval = iface->get_element_connect( nPolys[iType], num_v_per_elem, MBQUAD, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
480 break;
481 default:
482 if( outputEnabled )
483 dbgprint.printf( 0, "....Block %d: Polygonal [%u] Elements [%u].\n", iBlock++, iType,
484 nPolys[iType] );
485 rval = iface->get_element_connect( nPolys[iType], num_v_per_elem, MBPOLYGON, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
486 break;
487 }
488
489 Range mbcells( starte, starte + nPolys[iType] - 1 );
490 m_interface->add_entities( mesh_set, mbcells );
491
492 if( storeParentInfo )
493 {
494 srcParent.resize( mbcells.size(), -1 );
495 tgtParent.resize( mbcells.size(), -1 );
496 }
497
498 std::vector< int > gids( typeNSeqs[iType].size() );
499 for( unsigned ifaces = 0, offset = 0; ifaces < typeNSeqs[iType].size(); ++ifaces )
500 {
501 const int fIndex = typeNSeqs[iType][ifaces];
502 const Face& face = faces[fIndex];
503
504 for( unsigned iedges = 0; iedges < face.edges.size(); ++iedges )
505 {
506 conn[offset++] = startv + face.edges[iedges].node[0];
507 }
508
509 if( storeParentInfo )
510 {
511 srcParent[ifaces] = mesh->vecSourceFaceIx[fIndex] + 1;
512 tgtParent[ifaces] = mesh->vecTargetFaceIx[fIndex] + 1;
513 }
514
515 gids[ifaces] = typeNSeqs[iType][ifaces] + 1;
516 }
517 rval = m_interface->tag_set_data( gidTag, mbcells, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
518
519 if( meshType == OVERLAP_FILES )
520 {
521
522 rval = iface->update_adjacencies( starte, nPolys[iType], num_v_per_elem, conn );MB_CHK_SET_ERR( rval, "Can't update adjacencies" );
523
524 Range edges;
525 rval = m_interface->get_adjacencies( mbcells, 1, true, edges, Interface::UNION );MB_CHK_SET_ERR( rval, "Can't get edges" );
526 }
527
528 if( storeParentInfo )
529 {
530 rval = m_interface->tag_set_data( srcParentTag, mbcells, &srcParent[0] );MB_CHK_SET_ERR( rval, "Can't set tag data" );
531 rval = m_interface->tag_set_data( tgtParentTag, mbcells, &tgtParent[0] );MB_CHK_SET_ERR( rval, "Can't set tag data" );
532 }
533 entities.merge( mbcells );
534 }
535 }
536
537 if( vertices ) *vertices = mbverts;
538
539 return MB_SUCCESS;
540 }
541 #endif
542
543
544
545 ErrorCode TempestRemapper::ConvertAllMeshesToTempest()
546 {
547
548
549 if( this->m_source == nullptr )
550 {
551
552 MB_CHK_SET_ERR( this->ConvertMeshToTempest( moab::Remapper::SourceMesh ),
553 "Can't convert source mesh to TempestRemap format" );
554 }
555 if( this->m_covering_source == nullptr )
556 {
557
558 MB_CHK_SET_ERR( this->ConvertMeshToTempest( moab::Remapper::CoveringMesh ),
559 "Can't convert source coverage mesh to TempestRemap format" );
560 }
561 if( this->m_target == nullptr )
562 {
563
564 MB_CHK_SET_ERR( this->ConvertMeshToTempest( moab::Remapper::TargetMesh ),
565 "Can't convert target mesh to TempestRemap format" );
566 }
567
568 return moab::MB_SUCCESS;
569 }
570
571 ErrorCode TempestRemapper::ConvertMeshToTempest( Remapper::IntersectionContext ctx )
572 {
573 const bool outputEnabled = ( TempestRemapper::verbose && is_root );
574
575
576 moab::DebugOutput dbgprint( std::cout, this->rank, 0 );
577 dbgprint.set_prefix( "[MOABToTempest]: " );
578
579 if( ctx == Remapper::SourceMesh )
580 {
581 if( !m_source ) m_source = new Mesh();
582 if( outputEnabled ) dbgprint.printf( 0, "Converting (source) MOAB to TempestRemap Mesh representation ...\n" );
583 MB_CHK_SET_ERR( convert_mesh_to_tempest_private( m_source, m_source_set, m_source_entities,
584 &m_source_vertices ),
585 "Can't convert source mesh to Tempest" );
586 if( m_source_entities.size() == 0 && m_source_vertices.size() != 0 )
587 {
588 this->point_cloud_source = true;
589 }
590 }
591 else if( ctx == Remapper::CoveringMesh )
592 {
593 if( !m_covering_source ) m_covering_source = new Mesh();
594 if( outputEnabled )
595 dbgprint.printf( 0, "Converting (covering source) MOAB to TempestRemap Mesh representation ...\n" );
596 MB_CHK_SET_ERR( convert_mesh_to_tempest_private( m_covering_source, m_covering_source_set,
597 m_covering_source_entities, &m_covering_source_vertices ),
598 "Can't convert convering source mesh to TempestRemap format" );
599 }
600 else if( ctx == Remapper::TargetMesh )
601 {
602 if( !m_target ) m_target = new Mesh();
603 if( outputEnabled ) dbgprint.printf( 0, "Converting (target) MOAB to TempestRemap Mesh representation ...\n" );
604 MB_CHK_SET_ERR( convert_mesh_to_tempest_private( m_target, m_target_set, m_target_entities,
605 &m_target_vertices ),
606 "Can't convert target mesh to Tempest" );
607 if( m_target_entities.size() == 0 && m_target_vertices.size() != 0 ) this->point_cloud_target = true;
608 }
609 else if( ctx == Remapper::OverlapMesh )
610 {
611 if( !m_overlap ) m_overlap = new Mesh();
612 if( outputEnabled ) dbgprint.printf( 0, "Converting (overlap) MOAB to TempestRemap Mesh representation ...\n" );
613 MB_CHK_SET_ERR( ConvertOverlapMeshSourceOrdered(), "Can't convert overlap mesh to Tempest" );
614 }
615 else
616 {
617 MB_CHK_SET_ERR( MB_FAILURE, "Invalid IntersectionContext context provided" );
618 }
619
620 return moab::MB_SUCCESS;
621 }
622
623 ErrorCode TempestRemapper::convert_mesh_to_tempest_private( Mesh* mesh,
624 EntityHandle mesh_set,
625 moab::Range& elems,
626 moab::Range* pverts )
627 {
628 ErrorCode rval;
629 Range verts;
630
631 NodeVector& nodes = mesh->nodes;
632 FaceVector& faces = mesh->faces;
633
634 elems.clear();
635 rval = m_interface->get_entities_by_dimension( mesh_set, 2, elems );MB_CHK_ERR( rval );
636
637 const size_t nelems = elems.size();
638
639
640 faces.resize( nelems );
641
642
643 rval = m_interface->get_connectivity( elems, verts );MB_CHK_ERR( rval );
644 if( verts.size() == 0 )
645 {
646 rval = m_interface->get_entities_by_dimension( mesh_set, 0, verts );MB_CHK_ERR( rval );
647 }
648
649
650 std::map< EntityHandle, int > indxMap;
651 bool useRange = true;
652 if( verts.compactness() > 0.01 )
653 {
654 int j = 0;
655 for( Range::iterator it = verts.begin(); it != verts.end(); it++ )
656 indxMap[*it] = j++;
657 useRange = false;
658 }
659
660 std::vector< int > globIds( nelems );
661 moab::Tag gid = m_interface->globalId_tag();
662 rval = m_interface->tag_get_data( gid, elems, &globIds[0] );MB_CHK_ERR( rval );
663 std::vector< size_t > sortedIdx;
664 if( offlineWorkflow )
665 {
666 sortedIdx.resize( nelems );
667
668 std::iota( sortedIdx.begin(), sortedIdx.end(), 0 );
669
670
671 std::sort( sortedIdx.begin(), sortedIdx.end(),
672 [&globIds]( size_t i1, size_t i2 ) { return globIds[i1] < globIds[i2]; } );
673 }
674
675 for( unsigned iface = 0; iface < nelems; ++iface )
676 {
677 Face& face = faces[iface];
678 EntityHandle ehandle = ( offlineWorkflow ? elems[sortedIdx[iface]] : elems[iface] );
679
680
681 const EntityHandle* connectface;
682 int nnodesf;
683 rval = m_interface->get_connectivity( ehandle, connectface, nnodesf );MB_CHK_ERR( rval );
684
685 while( connectface[nnodesf - 2] == connectface[nnodesf - 1] && nnodesf > 3 )
686 nnodesf--;
687
688 face.edges.resize( nnodesf );
689 for( int iverts = 0; iverts < nnodesf; ++iverts )
690 {
691 int indx = ( useRange ? verts.index( connectface[iverts] ) : indxMap[connectface[iverts]] );
692 assert( indx >= 0 );
693 face.SetNode( iverts, indx );
694 }
695 }
696
697 unsigned nnodes = verts.size();
698 nodes.resize( nnodes );
699
700
701 std::vector< double > coordx( nnodes ), coordy( nnodes ), coordz( nnodes );
702 rval = m_interface->get_coords( verts, &coordx[0], &coordy[0], &coordz[0] );MB_CHK_ERR( rval );
703 for( unsigned inode = 0; inode < nnodes; ++inode )
704 {
705 Node& node = nodes[inode];
706 node.x = coordx[inode];
707 node.y = coordy[inode];
708 node.z = coordz[inode];
709 }
710 coordx.clear();
711 coordy.clear();
712 coordz.clear();
713
714 mesh->RemoveCoincidentNodes();
715 mesh->RemoveZeroEdges();
716
717
718 if( constructEdgeMap ) mesh->ConstructEdgeMap( false );
719
720
721
722
723 if( pverts )
724 {
725 pverts->clear();
726 *pverts = verts;
727 }
728 verts.clear();
729
730 return MB_SUCCESS;
731 }
732
733
734
735 bool IntPairComparator( const std::array< int, 3 >& a, const std::array< int, 3 >& b )
736 {
737 if( std::get< 1 >( a ) == std::get< 1 >( b ) )
738 return std::get< 2 >( a ) < std::get< 2 >( b );
739 else
740 return std::get< 1 >( a ) < std::get< 1 >( b );
741 }
742
743 moab::ErrorCode moab::TempestRemapper::GetOverlapAugmentedEntities( moab::Range& sharedGhostEntities )
744 {
745 sharedGhostEntities.clear();
746 #ifdef MOAB_HAVE_MPI
747 moab::ErrorCode rval;
748
749
750 if( is_parallel )
751 {
752 moab::Range allents;
753 rval = m_interface->get_entities_by_dimension( m_overlap_set, 2, allents );MB_CHK_SET_ERR( rval, "Getting entities dim 2 failed" );
754
755 moab::Range sharedents;
756 moab::Tag ghostTag;
757 std::vector< int > ghFlags( allents.size() );
758 rval = m_interface->tag_get_handle( "ORIG_PROC", ghostTag );MB_CHK_ERR( rval );
759 rval = m_interface->tag_get_data( ghostTag, allents, &ghFlags[0] );MB_CHK_ERR( rval );
760 for( unsigned i = 0; i < allents.size(); ++i )
761 if( ghFlags[i] >= 0 )
762 sharedents.insert( allents[i] );
763
764 allents = subtract( allents, sharedents );
765
766
767
768 moab::Range ownedverts, sharedverts;
769 rval = m_interface->get_connectivity( allents, ownedverts );MB_CHK_SET_ERR( rval, "Deleting entities dim 0 failed" );
770 rval = m_interface->get_connectivity( sharedents, sharedverts );MB_CHK_SET_ERR( rval, "Deleting entities dim 0 failed" );
771 sharedverts = subtract( sharedverts, ownedverts );
772
773
774
775
776 sharedGhostEntities.merge( sharedents );
777
778 }
779 #endif
780 return moab::MB_SUCCESS;
781 }
782
783 ErrorCode TempestRemapper::ConvertOverlapMeshSourceOrdered()
784 {
785 ErrorCode rval;
786
787 m_overlap_entities.clear();
788 rval = m_interface->get_entities_by_dimension( m_overlap_set, 2, m_overlap_entities );MB_CHK_ERR( rval );
789 size_t n_overlap_entitites = m_overlap_entities.size();
790
791
792 if( !m_overlap ) m_overlap = new Mesh();
793
794 std::vector< std::array< int, 3 > > sorted_overlap_order( n_overlap_entitites,
795 std::array< int, 3 >( { -1, -1, -1 } ) );
796 {
797 Tag srcParentTag, tgtParentTag;
798 rval = m_interface->tag_get_handle( "SourceParent", srcParentTag );MB_CHK_ERR( rval );
799 rval = m_interface->tag_get_handle( "TargetParent", tgtParentTag );MB_CHK_ERR( rval );
800
801 m_overlap->vecTargetFaceIx.resize( n_overlap_entitites );
802 m_overlap->vecSourceFaceIx.resize( n_overlap_entitites );
803
804
805 Tag gidtag = m_interface->globalId_tag();
806 std::vector< int > gids_src( m_covering_source_entities.size(), -1 ), gids_tgt( m_target_entities.size(), -1 );
807 MB_CHK_ERR( m_interface->tag_get_data( gidtag, m_covering_source_entities, gids_src.data() ) );
808 MB_CHK_ERR( m_interface->tag_get_data( gidtag, m_target_entities, gids_tgt.data() ) );
809
810
811
812
813
814 auto find_lid = []( std::vector< int >& gids, int gid ) -> int {
815 auto it = std::find( gids.begin(), gids.end(), gid );
816 return ( it != gids.end() ? std::distance( gids.begin(), it ) : -1 );
817 };
818
819 std::vector< int > ghFlags;
820 if( is_parallel )
821 {
822 Tag ghostTag;
823 ghFlags.resize( n_overlap_entitites );
824 MB_CHK_SET_ERR( m_interface->tag_get_handle( "ORIG_PROC", ghostTag ), "Could not find ORIG_PROC tag" );
825 MB_CHK_ERR( m_interface->tag_get_data( ghostTag, m_overlap_entities, ghFlags.data() ) );
826 }
827
828
829 std::vector< int > rbids_src( n_overlap_entitites ), rbids_tgt( n_overlap_entitites );
830 MB_CHK_ERR( m_interface->tag_get_data( srcParentTag, m_overlap_entities, rbids_src.data() ) );
831 MB_CHK_ERR( m_interface->tag_get_data( tgtParentTag, m_overlap_entities, rbids_tgt.data() ) );
832
833 for( size_t ix = 0; ix < n_overlap_entitites; ++ix )
834 {
835 std::get< 0 >( sorted_overlap_order[ix] ) = ix;
836 std::get< 1 >( sorted_overlap_order[ix] ) = find_lid( gids_src, rbids_src[ix] );
837 if( is_parallel && ghFlags[ix] >= 0 )
838 std::get< 2 >( sorted_overlap_order[ix] ) = -1;
839 else
840 std::get< 2 >( sorted_overlap_order[ix] ) = find_lid( gids_tgt, rbids_tgt[ix] );
841 }
842
843
844 std::sort( sorted_overlap_order.begin(), sorted_overlap_order.end(), IntPairComparator );
845
846 for( unsigned ie = 0; ie < n_overlap_entitites; ++ie )
847 {
848
849 m_overlap->vecSourceFaceIx[ie] = std::get< 1 >( sorted_overlap_order[ie] );
850 m_overlap->vecTargetFaceIx[ie] = std::get< 2 >( sorted_overlap_order[ie] );
851 }
852 }
853
854 FaceVector& faces = m_overlap->faces;
855 faces.resize( n_overlap_entitites );
856
857 Range verts;
858
859 MB_CHK_ERR( m_interface->get_connectivity( m_overlap_entities, verts ) );
860
861 std::map< EntityHandle, int > indxMap;
862 {
863 int j = 0;
864 for( Range::iterator it = verts.begin(); it != verts.end(); ++it )
865 indxMap[*it] = j++;
866 }
867
868 for( unsigned ifac = 0; ifac < m_overlap_entities.size(); ++ifac )
869 {
870 const unsigned iface = std::get< 0 >( sorted_overlap_order[ifac] );
871 Face& face = faces[ifac];
872 EntityHandle ehandle = m_overlap_entities[iface];
873
874
875 const EntityHandle* connectface;
876 int nnodesf;
877 MB_CHK_ERR( m_interface->get_connectivity( ehandle, connectface, nnodesf ) );
878
879 face.edges.resize( nnodesf );
880 for( int iverts = 0; iverts < nnodesf; ++iverts )
881 {
882 int indx = indxMap[connectface[iverts]];
883 assert( indx >= 0 );
884 face.SetNode( iverts, indx );
885 }
886 }
887 indxMap.clear();
888 sorted_overlap_order.clear();
889
890 unsigned nnodes = verts.size();
891 NodeVector& nodes = m_overlap->nodes;
892 nodes.resize( nnodes );
893
894
895 std::vector< double > coordx( nnodes ), coordy( nnodes ), coordz( nnodes );
896 rval = m_interface->get_coords( verts, &coordx[0], &coordy[0], &coordz[0] );MB_CHK_ERR( rval );
897 for( unsigned inode = 0; inode < nnodes; ++inode )
898 {
899 Node& node = nodes[inode];
900 node.x = coordx[inode];
901 node.y = coordy[inode];
902 node.z = coordz[inode];
903 }
904 coordx.clear();
905 coordy.clear();
906 coordz.clear();
907 verts.clear();
908
909
910
911
912
913
914
915
916 m_overlap->Validate();
917 return MB_SUCCESS;
918 }
919
920
921
922 moab::ErrorCode moab::TempestRemapper::WriteTempestIntersectionMesh( std::string strOutputFileName,
923 const bool fAllParallel,
924 const bool fInputConcave,
925 const bool fOutputConcave )
926 {
927
928 if( fAllParallel )
929 {
930 if( is_root && size == 1 )
931 {
932 this->m_source->CalculateFaceAreas( fInputConcave );
933 this->m_target->CalculateFaceAreas( fOutputConcave );
934 this->m_overlap->Write( strOutputFileName.c_str(), NcFile::Netcdf4 );
935 }
936 else
937 {
938
939
940
941
942 this->m_source->CalculateFaceAreas( fInputConcave );
943 this->m_covering_source->CalculateFaceAreas( fInputConcave );
944 this->m_target->CalculateFaceAreas( fOutputConcave );
945 this->m_overlap->Write( strOutputFileName.c_str(), NcFile::Netcdf4 );
946 }
947 }
948 else
949 {
950 this->m_source->CalculateFaceAreas( fInputConcave );
951 this->m_target->CalculateFaceAreas( fOutputConcave );
952 this->m_overlap->Write( strOutputFileName.c_str(), NcFile::Netcdf4 );
953 }
954
955 return moab::MB_SUCCESS;
956 }
957
958 void TempestRemapper::SetMeshSet( Remapper::IntersectionContext ctx ,
959 moab::EntityHandle mset,
960 moab::Range* entities )
961 {
962
963 if( ctx == Remapper::SourceMesh )
964 {
965 m_source_set = mset;
966 if( entities ) m_source_entities = *entities;
967 }
968 else if( ctx == Remapper::TargetMesh )
969 {
970 m_target_set = mset;
971 if( entities ) m_target_entities = *entities;
972 }
973 else if( ctx == Remapper::CoveringMesh )
974 {
975 m_covering_source_set = mset;
976 if( entities ) m_covering_source_entities = *entities;
977 }
978 else
979 {
980
981 return;
982 }
983 }
984
985
986
987 #ifndef MOAB_HAVE_MPI
988 ErrorCode TempestRemapper::assign_vertex_element_IDs( Tag idtag,
989 EntityHandle this_set,
990 const int dimension,
991 const int start_id )
992 {
993 assert( idtag );
994
995 ErrorCode rval;
996 Range entities;
997 rval = m_interface->get_entities_by_dimension( this_set, dimension, entities );MB_CHK_SET_ERR( rval, "Failed to get entities" );
998
999 if( entities.size() == 0 ) return moab::MB_SUCCESS;
1000
1001 int idoffset = start_id;
1002 std::vector< int > gid( entities.size() );
1003 for( unsigned i = 0; i < entities.size(); ++i )
1004 gid[i] = idoffset++;
1005
1006 rval = m_interface->tag_set_data( idtag, entities, &gid[0] );MB_CHK_ERR( rval );
1007
1008 return moab::MB_SUCCESS;
1009 }
1010 #endif
1011
1012
1013
1014
1015 bool operator<( Node const& lhs, Node const& rhs )
1016 {
1017 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 );
1018 }
1019
1020 ErrorCode TempestRemapper::GenerateCSMeshMetadata( const int ntot_elements,
1021 moab::Range& ents,
1022 moab::Range* secondary_ents,
1023 const std::string& dofTagName,
1024 int nP )
1025 {
1026 const int csResolution = std::sqrt( ntot_elements / 6.0 );
1027 if( csResolution * csResolution * 6 != ntot_elements ) return MB_INVALID_SIZE;
1028
1029
1030
1031 Mesh csMesh;
1032 if( GenerateCSMesh( csMesh, csResolution, "", "NetCDF4" ) )
1033 MB_CHK_SET_ERR( moab::MB_FAILURE,
1034 "Failed to generate CS mesh through TempestRemap" );
1035
1036
1037 if( this->GenerateMeshMetadata( csMesh, ntot_elements, ents, secondary_ents, dofTagName, nP ) )
1038 MB_CHK_SET_ERR( moab::MB_FAILURE, "Failed in call to GenerateMeshMetadata" );
1039
1040 return moab::MB_SUCCESS;
1041 }
1042
1043 ErrorCode TempestRemapper::GenerateMeshMetadata( Mesh& csMesh,
1044 const int ntot_elements,
1045 moab::Range& ents,
1046 moab::Range* secondary_ents,
1047 const std::string dofTagName,
1048 int nP )
1049 {
1050 moab::ErrorCode rval;
1051
1052 Tag dofTag;
1053 bool created = false;
1054 rval = m_interface->tag_get_handle( dofTagName.c_str(), nP * nP, MB_TYPE_INTEGER, dofTag,
1055 MB_TAG_DENSE | MB_TAG_CREAT, 0, &created );MB_CHK_SET_ERR( rval, "Failed creating DoF tag" );
1056
1057
1058 int nElements = static_cast< int >( csMesh.faces.size() );
1059
1060 if( nElements != ntot_elements ) return MB_INVALID_SIZE;
1061
1062
1063 DataArray3D< int > dataGLLnodes;
1064 dataGLLnodes.Allocate( nP, nP, nElements );
1065
1066 std::map< Node, int > mapNodes;
1067 std::map< Node, moab::EntityHandle > mapLocalMBNodes;
1068
1069
1070 DataArray1D< double > dG;
1071 DataArray1D< double > dW;
1072 GaussLobattoQuadrature::GetPoints( nP, 0.0, 1.0, dG, dW );
1073
1074 moab::Range entities( ents );
1075 if( secondary_ents ) entities.insert( secondary_ents->begin(), secondary_ents->end() );
1076 double elcoords[3];
1077 for( unsigned iel = 0; iel < entities.size(); ++iel )
1078 {
1079 EntityHandle eh = entities[iel];
1080 rval = m_interface->get_coords( &eh, 1, elcoords );
1081 Node elCentroid( elcoords[0], elcoords[1], elcoords[2] );
1082 mapLocalMBNodes.insert( std::pair< Node, moab::EntityHandle >( elCentroid, eh ) );
1083 }
1084
1085
1086
1087
1088
1089
1090
1091 int* dofIDs = new int[nP * nP];
1092
1093
1094 for( int k = 0; k < nElements; k++ )
1095 {
1096 const Face& face = csMesh.faces[k];
1097 const NodeVector& nodes = csMesh.nodes;
1098
1099 if( face.edges.size() != 4 )
1100 {
1101 _EXCEPTIONT( "Mesh must only contain quadrilateral elements" );
1102 }
1103
1104 Node centroid;
1105 centroid.x = centroid.y = centroid.z = 0.0;
1106 for( unsigned l = 0; l < face.edges.size(); ++l )
1107 {
1108 centroid.x += nodes[face[l]].x;
1109 centroid.y += nodes[face[l]].y;
1110 centroid.z += nodes[face[l]].z;
1111 }
1112 const double factor = 1.0 / face.edges.size();
1113 centroid.x *= factor;
1114 centroid.y *= factor;
1115 centroid.z *= factor;
1116
1117 bool locElem = false;
1118 EntityHandle current_eh;
1119 if( mapLocalMBNodes.find( centroid ) != mapLocalMBNodes.end() )
1120 {
1121 locElem = true;
1122 current_eh = mapLocalMBNodes[centroid];
1123 }
1124
1125 for( int j = 0; j < nP; j++ )
1126 {
1127 for( int i = 0; i < nP; i++ )
1128 {
1129
1130 Node nodeGLL;
1131 Node dDx1G;
1132 Node dDx2G;
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 const double& dAlpha = dG[i];
1143 const double& dBeta = dG[j];
1144
1145
1146 double dXc = nodes[face[0]].x * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1147 nodes[face[1]].x * dAlpha * ( 1.0 - dBeta ) + nodes[face[2]].x * dAlpha * dBeta +
1148 nodes[face[3]].x * ( 1.0 - dAlpha ) * dBeta;
1149
1150 double dYc = nodes[face[0]].y * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1151 nodes[face[1]].y * dAlpha * ( 1.0 - dBeta ) + nodes[face[2]].y * dAlpha * dBeta +
1152 nodes[face[3]].y * ( 1.0 - dAlpha ) * dBeta;
1153
1154 double dZc = nodes[face[0]].z * ( 1.0 - dAlpha ) * ( 1.0 - dBeta ) +
1155 nodes[face[1]].z * dAlpha * ( 1.0 - dBeta ) + nodes[face[2]].z * dAlpha * dBeta +
1156 nodes[face[3]].z * ( 1.0 - dAlpha ) * dBeta;
1157
1158 double dR = sqrt( dXc * dXc + dYc * dYc + dZc * dZc );
1159
1160
1161 nodeGLL.x = dXc / dR;
1162 nodeGLL.y = dYc / dR;
1163 nodeGLL.z = dZc / dR;
1164
1165
1166 std::map< Node, int >::const_iterator iter = mapNodes.find( nodeGLL );
1167 if( iter == mapNodes.end() )
1168 {
1169
1170 int ixNode = static_cast< int >( mapNodes.size() );
1171 mapNodes.insert( std::pair< Node, int >( nodeGLL, ixNode ) );
1172 dataGLLnodes[j][i][k] = ixNode + 1;
1173 }
1174 else
1175 {
1176 dataGLLnodes[j][i][k] = iter->second + 1;
1177 }
1178
1179 dofIDs[j * nP + i] = dataGLLnodes[j][i][k];
1180 }
1181 }
1182
1183 if( locElem )
1184 {
1185 rval = m_interface->tag_set_data( dofTag, ¤t_eh, 1, dofIDs );MB_CHK_SET_ERR( rval, "Failed to tag_set_data for DoFs" );
1186 }
1187 }
1188
1189
1190 delete[] dofIDs;
1191 mapLocalMBNodes.clear();
1192 mapNodes.clear();
1193
1194 return moab::MB_SUCCESS;
1195 }
1196
1197
1198
1199
1200 ErrorCode TempestRemapper::ConstructCoveringSet( double tolerance,
1201 double radius_src,
1202 double radius_tgt,
1203 double boxeps,
1204 bool regional_mesh,
1205 bool gnomonic,
1206 int nb_ghost_layers )
1207 {
1208 ErrorCode rval;
1209
1210 rrmgrids = regional_mesh;
1211 moab::Range local_verts;
1212
1213
1214 mbintx = new moab::Intx2MeshOnSphere( m_interface, moab::IntxAreaUtils::GaussQuadrature );
1215
1216 mbintx->set_error_tolerance( tolerance );
1217 mbintx->set_radius_source_mesh( radius_src );
1218 mbintx->set_radius_destination_mesh( radius_tgt );
1219 mbintx->set_box_error( boxeps );
1220 #ifdef MOAB_HAVE_MPI
1221 mbintx->set_parallel_comm( m_pcomm );
1222 #endif
1223
1224
1225 rval = mbintx->FindMaxEdges( m_source_set, m_target_set );MB_CHK_ERR( rval );
1226
1227 this->max_source_edges = mbintx->max_edges_1;
1228 this->max_target_edges = mbintx->max_edges_2;
1229
1230
1231 #ifdef MOAB_HAVE_MPI
1232 if( is_parallel )
1233 {
1234 rval = mbintx->build_processor_euler_boxes( m_target_set, local_verts, gnomonic );MB_CHK_ERR( rval );
1235
1236 rval = m_interface->create_meshset( moab::MESHSET_SET, m_covering_source_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
1237
1238 rval = mbintx->construct_covering_set( m_source_set, m_covering_source_set, gnomonic, nb_ghost_layers );MB_CHK_ERR( rval );
1239 #ifdef MOAB_DBG
1240 std::stringstream filename;
1241 filename << "covering" << rank << ".h5m";
1242 rval = m_interface->write_file( filename.str().c_str(), 0, 0, &m_covering_source_set, 1 );MB_CHK_ERR( rval );
1243 std::stringstream targetFile;
1244 targetFile << "target" << rank << ".h5m";
1245 rval = m_interface->write_file( targetFile.str().c_str(), 0, 0, &m_target_set, 1 );MB_CHK_ERR( rval );
1246 #endif
1247 }
1248 else
1249 {
1250 #endif
1251 if( rrmgrids )
1252 {
1253 rval = m_interface->create_meshset( moab::MESHSET_SET, m_covering_source_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
1254
1255 double tolerance = 1e-6, btolerance = 1e-3;
1256 moab::AdaptiveKDTree tree( m_interface );
1257 moab::Range targetVerts;
1258
1259 rval = m_interface->get_connectivity( m_target_entities, targetVerts, true );MB_CHK_ERR( rval );
1260
1261 rval = tree.build_tree( m_source_entities, &m_source_set );MB_CHK_ERR( rval );
1262
1263 for( unsigned ie = 0; ie < targetVerts.size(); ++ie )
1264 {
1265 EntityHandle el = targetVerts[ie], leaf;
1266 double point[3];
1267
1268
1269 rval = m_interface->get_coords( &el, 1, point );MB_CHK_ERR( rval );
1270
1271
1272
1273 rval = tree.point_search( point, leaf, tolerance, btolerance );MB_CHK_ERR( rval );
1274
1275 if( leaf == 0 )
1276 {
1277 leaf = m_source_set;
1278 }
1279
1280 std::vector< moab::EntityHandle > leaf_elems;
1281
1282
1283 rval = m_interface->get_entities_by_dimension( leaf, 2, leaf_elems );MB_CHK_ERR( rval );
1284
1285 if( !leaf_elems.size() )
1286 {
1287
1288 continue;
1289 }
1290
1291
1292
1293 std::vector< double > centroids( leaf_elems.size() * 3 );
1294 rval = m_interface->get_coords( &leaf_elems[0], leaf_elems.size(), ¢roids[0] );MB_CHK_ERR( rval );
1295
1296 double dist = 1e5;
1297 int pinelem = -1;
1298 for( size_t il = 0; il < leaf_elems.size(); ++il )
1299 {
1300 const double* centroid = ¢roids[il * 3];
1301 const double locdist = std::pow( point[0] - centroid[0], 2 ) +
1302 std::pow( point[1] - centroid[1], 2 ) +
1303 std::pow( point[2] - centroid[2], 2 );
1304
1305 if( locdist < dist )
1306 {
1307 dist = locdist;
1308 pinelem = il;
1309 m_covering_source_entities.insert( leaf_elems[il] );
1310 }
1311 }
1312
1313 if( pinelem < 0 )
1314 {
1315 std::cout << ie
1316 << ": [Error] - Could not find a minimum distance within the leaf "
1317 "nodes. Dist = "
1318 << dist << std::endl;
1319 }
1320 }
1321
1322 std::cout << "[INFO] - Total covering source entities = " << m_covering_source_entities.size() << std::endl;
1323 rval = m_interface->add_entities( m_covering_source_set, m_covering_source_entities );MB_CHK_ERR( rval );
1324 }
1325 else
1326 {
1327 m_covering_source_set = m_source_set;
1328 m_covering_source = m_source;
1329 m_covering_source_entities = m_source_entities;
1330
1331 m_covering_source_vertices = m_source_vertices;
1332
1333 }
1334 #ifdef MOAB_HAVE_MPI
1335 }
1336 #endif
1337
1338
1339 MB_CHK_ERR( ConvertAllMeshesToTempest() );
1340
1341 return rval;
1342 }
1343
1344 ErrorCode TempestRemapper::ComputeOverlapMesh( bool kdtree_search, bool use_tempest )
1345 {
1346 ErrorCode rval;
1347 const bool outputEnabled = ( this->rank == 0 );
1348 moab::DebugOutput dbgprint( std::cout, this->rank, 0 );
1349 dbgprint.set_prefix( "[ComputeOverlapMesh]: " );
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362 if( use_tempest )
1363 {
1364
1365
1366 assert( m_covering_source != nullptr );
1367 assert( m_target != nullptr );
1368 if( m_overlap != nullptr ) delete m_overlap;
1369 bool concaveMeshA = false, concaveMeshB = false;
1370
1371 m_overlap = new Mesh();
1372
1373 if( GenerateOverlapWithMeshes( *m_covering_source, *m_target, *m_overlap, "" , "Netcdf4",
1374 "exact", concaveMeshA, concaveMeshB, true, false ) )
1375 MB_CHK_SET_ERR( MB_FAILURE, "TempestRemap: cannot compute the intersection of meshes on the sphere" );
1376 }
1377 else
1378 {
1379
1380 if( kdtree_search )
1381 {
1382 if( outputEnabled ) dbgprint.printf( 0, "Computing intersection mesh with the Kd-tree search algorithm" );
1383 rval = mbintx->intersect_meshes_kdtree( m_covering_source_set, m_target_set, m_overlap_set );MB_CHK_SET_ERR( rval, "Can't compute the intersection of meshes on the sphere with brute-force" );
1384 }
1385 else
1386 {
1387 if( outputEnabled )
1388 dbgprint.printf( 0, "Computing intersection mesh with the advancing-front propagation algorithm" );
1389 rval = mbintx->intersect_meshes( m_covering_source_set, m_target_set, m_overlap_set );MB_CHK_SET_ERR( rval, "Can't compute the intersection of meshes on the sphere" );
1390 }
1391
1392 #ifdef MOAB_HAVE_MPI
1393 if( is_parallel || rrmgrids )
1394 {
1395 #ifdef VERBOSE
1396 std::stringstream ffc, fft, ffo;
1397 ffc << "cover_" << rank << ".h5m";
1398 fft << "target_" << rank << ".h5m";
1399 ffo << "intx_" << rank << ".h5m";
1400 rval = m_interface->write_mesh( ffc.str().c_str(), &m_covering_source_set, 1 );MB_CHK_ERR( rval );
1401 rval = m_interface->write_mesh( fft.str().c_str(), &m_target_set, 1 );MB_CHK_ERR( rval );
1402 rval = m_interface->write_mesh( ffo.str().c_str(), &m_overlap_set, 1 );MB_CHK_ERR( rval );
1403 #endif
1404
1405
1406
1407 if( !point_cloud_target )
1408 {
1409 Range covEnts;
1410 rval = m_interface->get_entities_by_dimension( m_covering_source_set, 2, covEnts );MB_CHK_ERR( rval );
1411
1412 std::map< int, int > loc_gid_to_lid_covsrc;
1413 std::vector< int > gids( covEnts.size(), -1 );
1414
1415 Tag gidtag = m_interface->globalId_tag();
1416 rval = m_interface->tag_get_data( gidtag, covEnts, gids.data() );MB_CHK_ERR( rval );
1417
1418 for( unsigned ie = 0; ie < gids.size(); ++ie )
1419 {
1420 assert( gids[ie] > 0 );
1421 loc_gid_to_lid_covsrc[gids[ie]] = ie;
1422 }
1423
1424 Range intxCov, intxCells;
1425 Tag srcParentTag;
1426 rval = m_interface->tag_get_handle( "SourceParent", srcParentTag );MB_CHK_ERR( rval );
1427 rval = m_interface->get_entities_by_dimension( m_overlap_set, 2, intxCells );MB_CHK_ERR( rval );
1428 for( Range::iterator it = intxCells.begin(); it != intxCells.end(); it++ )
1429 {
1430 EntityHandle intxCell = *it;
1431 int srcParent = -1;
1432 rval = m_interface->tag_get_data( srcParentTag, &intxCell, 1, &srcParent );MB_CHK_ERR( rval );
1433
1434 assert( srcParent >= 0 );
1435 intxCov.insert( covEnts[loc_gid_to_lid_covsrc[srcParent]] );
1436 }
1437
1438 Range notNeededCovCells = moab::subtract( covEnts, intxCov );
1439
1440
1441 covEnts = moab::subtract( covEnts, notNeededCovCells );
1442
1443
1444 if( false )
1445 {
1446
1447 Core* mb = dynamic_cast< Core* >( m_interface );
1448 AEntityFactory* adj_fact = mb->a_entity_factory();
1449 if( !adj_fact->vert_elem_adjacencies() )
1450 adj_fact->create_vert_elem_adjacencies();
1451 else
1452 {
1453 for( Range::iterator it = covEnts.begin(); it != covEnts.end(); ++it )
1454 {
1455 EntityHandle eh = *it;
1456 const EntityHandle* conn = nullptr;
1457 int num_nodes = 0;
1458 rval = mb->get_connectivity( eh, conn, num_nodes );MB_CHK_ERR( rval );
1459 adj_fact->notify_create_entity( eh, conn, num_nodes );
1460 }
1461 }
1462
1463
1464 Skinner skinner( mb );
1465 Range skin;
1466 rval = skinner.find_skin( m_covering_source_set, covEnts, false, skin );MB_CHK_SET_ERR( rval, "Unable to find skin" );
1467 for( Range::iterator it = skin.begin(); it != skin.end(); ++it )
1468 {
1469 const EntityHandle* conn = nullptr;
1470 int len = 0;
1471 rval = mb->get_connectivity( *it, conn, len, false );MB_CHK_ERR( rval );
1472 for( int ie = 0; ie < len; ++ie )
1473 {
1474 std::vector< EntityHandle > adjacent_entities;
1475 rval = adj_fact->get_adjacencies( conn[ie], 2, false, adjacent_entities );MB_CHK_ERR( rval );
1476 for( auto ent : adjacent_entities )
1477 notNeededCovCells.erase( ent );
1478 }
1479 }
1480
1481 rval = m_interface->write_mesh(
1482 std::string( "sourcecoveragemesh_p" + std::to_string( rank ) + ".h5m" ).c_str(),
1483 &m_covering_source_set, 1 );MB_CHK_ERR( rval );
1484 }
1485
1486
1487
1488
1489
1490
1491
1492 #ifdef VERBOSE
1493 std::cout << " total participating elements in the covering set: " << intxCov.size() << "\n";
1494 std::cout << " remove from coverage set elements that are not intersected: " << notNeededCovCells.size()
1495 << "\n";
1496 #endif
1497 if( size > 1 )
1498 {
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510 MB_CHK_ERR( AugmentOverlapSet() );
1511 }
1512 }
1513 }
1514 #endif
1515
1516
1517 {
1518 IntxAreaUtils areaAdaptor;
1519 MB_CHK_ERR( IntxUtils::fix_degenerate_quads( m_interface, m_overlap_set ) );
1520 MB_CHK_ERR( areaAdaptor.positive_orientation( m_interface, m_overlap_set, 1.0 ) );
1521 }
1522
1523
1524 delete mbintx;
1525 }
1526
1527
1528 MB_CHK_SET_ERR( ConvertOverlapMeshSourceOrdered(), "Can't convert overlap TempestRemap mesh to MOAB format" );
1529
1530 return MB_SUCCESS;
1531 }
1532
1533 #ifdef MOAB_HAVE_MPI
1534
1535
1536
1537 ErrorCode TempestRemapper::AugmentOverlapSet()
1538 {
1539
1552
1553
1554 ErrorCode rval;
1555
1556 Skinner skinner( m_interface );
1557
1558
1559 Range boundaryEdges;
1560 MB_CHK_ERR( skinner.find_skin( 0, this->m_target_entities, false, boundaryEdges ) );
1561
1562
1563
1564 Range boundaryCells;
1565 MB_CHK_ERR( m_interface->get_adjacencies( boundaryEdges, 2, false, boundaryCells, Interface::UNION ) );
1566 boundaryCells = intersect( boundaryCells, this->m_target_entities );
1567
1568 #ifdef MOAB_DBG
1569 EntityHandle tmpSet;
1570 MB_CHK_SET_ERR( m_interface->create_meshset( MESHSET_SET, tmpSet ), "Can't create temporary set" );
1571
1572 MB_CHK_SET_ERR( m_interface->add_entities( tmpSet, boundaryCells ), "Can't add entities" );
1573 MB_CHK_SET_ERR( m_interface->add_entities( tmpSet, boundaryEdges ), "Can't add edges" );
1574 std::stringstream ffs;
1575 ffs << "boundaryCells_0" << rank << ".h5m";
1576 MB_CHK_ERR( m_interface->write_mesh( ffs.str().c_str(), &tmpSet, 1 ) );
1577 #endif
1578
1579
1580
1581 Tag gid = m_interface->globalId_tag();
1582 std::set< int > targetBoundaryIds;
1583 for( Range::iterator it = boundaryCells.begin(); it != boundaryCells.end(); it++ )
1584 {
1585 int tid;
1586 EntityHandle targetCell = *it;
1587 MB_CHK_SET_ERR( m_interface->tag_get_data( gid, &targetCell, 1, &tid ),
1588 "Can't get global id tag on target cell" );
1589 if( tid < 0 ) std::cout << " incorrect id for a target cell\n";
1590 targetBoundaryIds.insert( tid );
1591 }
1592
1593 Range overlapCells;
1594 MB_CHK_ERR( m_interface->get_entities_by_dimension( m_overlap_set, 2, overlapCells ) );
1595
1596 std::set< int > affectedSourceCellsIds;
1597 Tag targetParentTag, sourceParentTag;
1598 MB_CHK_ERR( m_interface->tag_get_handle( "TargetParent", targetParentTag ) );
1599 MB_CHK_ERR( m_interface->tag_get_handle( "SourceParent", sourceParentTag ) );
1600 for( Range::iterator it = overlapCells.begin(); it != overlapCells.end(); it++ )
1601 {
1602 EntityHandle intxCell = *it;
1603 int targetParentID, sourceParentID;
1604 MB_CHK_ERR( m_interface->tag_get_data( targetParentTag, &intxCell, 1, &targetParentID ) );
1605 if( targetBoundaryIds.find( targetParentID ) != targetBoundaryIds.end() )
1606 {
1607
1608 MB_CHK_ERR( m_interface->tag_get_data( sourceParentTag, &intxCell, 1, &sourceParentID ) );
1609 affectedSourceCellsIds.insert( sourceParentID );
1610 }
1611 }
1612
1613
1614
1615
1616
1617
1618 std::map< int, EntityHandle > affectedCovCellFromID;
1619
1620
1621
1622
1623
1624 std::set< EntityHandle > affectedCovCells;
1625
1626 Range covCells;
1627 MB_CHK_ERR( m_interface->get_entities_by_dimension( m_covering_source_set, 2, covCells ) );
1628
1629 for( Range::iterator it = covCells.begin(); it != covCells.end(); it++ )
1630 {
1631 EntityHandle covCell = *it;
1632 int covID;
1633 MB_CHK_ERR( m_interface->tag_get_data( gid, &covCell, 1, &covID ) );
1634 if( affectedSourceCellsIds.find( covID ) != affectedSourceCellsIds.end() )
1635 {
1636
1637 affectedCovCellFromID[covID] = covCell;
1638 affectedCovCells.insert( covCell );
1639 }
1640 }
1641
1642
1643
1644
1645 Tag sendProcTag;
1646 MB_CHK_ERR( m_interface->tag_get_handle( "sending_processor", 1, MB_TYPE_INTEGER, sendProcTag ) );
1647
1648
1649 std::map< int, std::set< EntityHandle > > overlapCellsForTask;
1650
1651
1652 std::set< EntityHandle > overlapCellsToSend;
1653
1654 for( Range::iterator it = overlapCells.begin(); it != overlapCells.end(); it++ )
1655 {
1656 EntityHandle intxCell = *it;
1657 int sourceParentID;
1658 MB_CHK_ERR( m_interface->tag_get_data( sourceParentTag, &intxCell, 1, &sourceParentID ) );
1659
1660 if( affectedSourceCellsIds.find( sourceParentID ) != affectedSourceCellsIds.end() )
1661 {
1662 int orgTask = -1;
1663 EntityHandle covCell = affectedCovCellFromID[sourceParentID];
1664 MB_CHK_ERR( m_interface->tag_get_data( sendProcTag, &covCell, 1, &orgTask ) );
1665
1666 overlapCellsForTask[orgTask].insert( intxCell );
1667
1668 overlapCellsToSend.insert( intxCell );
1669 }
1670 }
1671
1672
1673
1674
1675
1676 int maxEdges = 0;
1677 for( std::set< EntityHandle >::iterator it = overlapCellsToSend.begin(); it != overlapCellsToSend.end(); it++ )
1678 {
1679 EntityHandle intxCell = *it;
1680 int nnodes;
1681 const EntityHandle* conn;
1682 MB_CHK_ERR( m_interface->get_connectivity( intxCell, conn, nnodes ) );
1683 if( maxEdges < nnodes ) maxEdges = nnodes;
1684 }
1685
1686
1687 int globalMaxEdges;
1688 if( m_pcomm )
1689 MPI_Allreduce( &maxEdges, &globalMaxEdges, 1, MPI_INT, MPI_MAX, m_pcomm->comm() );
1690 else
1691 globalMaxEdges = maxEdges;
1692
1693 #ifdef MOAB_DBG
1694 if( is_root ) std::cout << "maximum number of edges for polygons to send is " << globalMaxEdges << "\n";
1695 #endif
1696
1697 #ifdef MOAB_DBG
1698 EntityHandle tmpSet2;
1699 MB_CHK_SET_ERR( m_interface->create_meshset( MESHSET_SET, tmpSet2 ), "Can't create temporary set2" );
1700
1701 for( std::set< EntityHandle >::iterator it = overlapCellsToSend.begin(); it != overlapCellsToSend.end(); it++ )
1702 {
1703 EntityHandle intxCell = *it;
1704 MB_CHK_SET_ERR( m_interface->add_entities( tmpSet2, &intxCell, 1 ), "Can't add entities" );
1705 }
1706 for( std::set< EntityHandle >::iterator it = affectedCovCells.begin(); it != affectedCovCells.end(); it++ )
1707 {
1708 EntityHandle covCell = *it;
1709 MB_CHK_SET_ERR( m_interface->add_entities( tmpSet2, &covCell, 1 ), "Can't add entities" );
1710 }
1711 std::stringstream ffs2;
1712
1713 ffs2 << "affectedCells_" << m_pcomm->rank() << ".h5m";
1714 rval = m_interface->write_mesh( ffs2.str().c_str(), &tmpSet2, 1 );MB_CHK_ERR( rval );
1715 #endif
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726 std::map< int, std::set< EntityHandle > > verticesOverlapForTask;
1727
1728 std::set< EntityHandle > allVerticesToSend;
1729 std::map< EntityHandle, int > allVerticesToSendMap;
1730 int numVerts = 0;
1731 int numOverlapCells = 0;
1732 for( std::map< int, std::set< EntityHandle > >::iterator it = overlapCellsForTask.begin();
1733 it != overlapCellsForTask.end(); it++ )
1734 {
1735 int sendToProc = it->first;
1736 std::set< EntityHandle >& overlapCellsToSend2 = it->second;
1737
1738 std::set< EntityHandle > vertices;
1739 for( std::set< EntityHandle >::iterator set_it = overlapCellsToSend2.begin();
1740 set_it != overlapCellsToSend2.end(); ++set_it )
1741 {
1742 int nnodes_local = 0;
1743 const EntityHandle* conn1 = nullptr;
1744 rval = m_interface->get_connectivity( *set_it, conn1, nnodes_local );MB_CHK_ERR( rval );
1745 for( int k = 0; k < nnodes_local; k++ )
1746 vertices.insert( conn1[k] );
1747 }
1748 verticesOverlapForTask[sendToProc] = vertices;
1749 numVerts += (int)vertices.size();
1750 numOverlapCells += (int)overlapCellsToSend2.size();
1751 allVerticesToSend.insert( vertices.begin(), vertices.end() );
1752 }
1753
1754 int j = 0;
1755 for( std::set< EntityHandle >::iterator vert_it = allVerticesToSend.begin(); vert_it != allVerticesToSend.end();
1756 vert_it++, j++ )
1757 {
1758 EntityHandle vert = *vert_it;
1759 allVerticesToSendMap[vert] = j;
1760 }
1761
1762
1763
1764 TupleList TLv;
1765 TLv.initialize( 2, 0, 0, 3, numVerts );
1766 TLv.enableWriteAccess();
1767
1768 for( std::map< int, std::set< EntityHandle > >::iterator it = verticesOverlapForTask.begin();
1769 it != verticesOverlapForTask.end(); it++ )
1770 {
1771 int sendToProc = it->first;
1772 std::set< EntityHandle >& vertices = it->second;
1773 int i = 0;
1774 for( std::set< EntityHandle >::iterator it2 = vertices.begin(); it2 != vertices.end(); it2++, i++ )
1775 {
1776 int n = TLv.get_n();
1777 TLv.vi_wr[2 * n] = sendToProc;
1778 EntityHandle v = *it2;
1779 int indexInAllVert = allVerticesToSendMap[v];
1780 TLv.vi_wr[2 * n + 1] = indexInAllVert;
1781
1782 double coords[3];
1783 rval = m_interface->get_coords( &v, 1, coords );MB_CHK_ERR( rval );
1784 TLv.vr_wr[3 * n] = coords[0];
1785 TLv.vr_wr[3 * n + 1] = coords[1];
1786 TLv.vr_wr[3 * n + 2] = coords[2];
1787 TLv.inc_n();
1788 }
1789 }
1790
1791 TupleList TLc;
1792 int sizeTuple = 4 + globalMaxEdges;
1793
1794 TLc.initialize( sizeTuple, 0, 0, 0,
1795 numOverlapCells );
1796
1797 TLc.enableWriteAccess();
1798
1799 for( std::map< int, std::set< EntityHandle > >::iterator it = overlapCellsForTask.begin();
1800 it != overlapCellsForTask.end(); it++ )
1801 {
1802 int sendToProc = it->first;
1803 std::set< EntityHandle >& overlapCellsToSend2 = it->second;
1804
1805 for( std::set< EntityHandle >::iterator it2 = overlapCellsToSend2.begin(); it2 != overlapCellsToSend2.end();
1806 it2++ )
1807 {
1808 EntityHandle intxCell = *it2;
1809 int sourceParentID, targetParentID;
1810 rval = m_interface->tag_get_data( targetParentTag, &intxCell, 1, &targetParentID );MB_CHK_ERR( rval );
1811 rval = m_interface->tag_get_data( sourceParentTag, &intxCell, 1, &sourceParentID );MB_CHK_ERR( rval );
1812 int n = TLc.get_n();
1813 TLc.vi_wr[sizeTuple * n] = sendToProc;
1814 TLc.vi_wr[sizeTuple * n + 1] = sourceParentID;
1815 TLc.vi_wr[sizeTuple * n + 2] = targetParentID;
1816 int nnodes;
1817 const EntityHandle* conn = nullptr;
1818 rval = m_interface->get_connectivity( intxCell, conn, nnodes );MB_CHK_ERR( rval );
1819 TLc.vi_wr[sizeTuple * n + 3] = nnodes;
1820 for( int i = 0; i < nnodes; i++ )
1821 {
1822 int indexVertex = allVerticesToSendMap[conn[i]];
1823 ;
1824 if( -1 == indexVertex ) MB_CHK_SET_ERR( MB_FAILURE, "Can't find vertex in range of vertices to send" );
1825 TLc.vi_wr[sizeTuple * n + 4 + i] = indexVertex;
1826 }
1827
1828 for( int i = nnodes; i < globalMaxEdges; i++ )
1829 TLc.vi_wr[sizeTuple * n + 4 + i] = 0;
1830
1831 TLc.inc_n();
1832 }
1833 }
1834
1835
1836
1837 #ifdef MOAB_DBG
1838 std::stringstream ff1;
1839 ff1 << "TLc_" << rank << ".txt";
1840 TLc.print_to_file( ff1.str().c_str() );
1841 std::stringstream ffv;
1842 ffv << "TLv_" << rank << ".txt";
1843 TLv.print_to_file( ffv.str().c_str() );
1844 #endif
1845 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 );
1846 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLc, 0 );
1847
1848 #ifdef MOAB_DBG
1849 TLc.print_to_file( ff1.str().c_str() );
1850 TLv.print_to_file( ffv.str().c_str() );
1851 #endif
1852
1853
1854
1855 TupleList::buffer buffer;
1856 buffer.buffer_init( sizeTuple * TLc.get_n() * 2 );
1857 TLc.sort( 1, &buffer );
1858 #ifdef MOAB_DBG
1859 TLc.print_to_file( ff1.str().c_str() );
1860 #endif
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870 std::map< int, std::map< int, int > > availVertexIndicesPerProcessor;
1871 int nv = TLv.get_n();
1872 for( int i = 0; i < nv; i++ )
1873 {
1874
1875 int orgProc = TLv.vi_rd[2 * i];
1876 int indexVert = TLv.vi_rd[2 * i + 1];
1877 availVertexIndicesPerProcessor[orgProc][indexVert] = i;
1878 }
1879
1880
1881
1882
1883
1884
1885
1886
1887 int n = TLc.get_n();
1888 std::map< int, int > currentProcsCount;
1889
1890
1891
1892 std::map< int, std::set< int > > sourcesForTasks;
1893 int sizeOfTLc2 = 0;
1894 if( n > 0 )
1895 {
1896 int currentSourceID = TLc.vi_rd[sizeTuple * 0 + 1];
1897 int proc0 = TLc.vi_rd[sizeTuple * 0];
1898 currentProcsCount[proc0] = 1;
1899
1900 for( int i = 1; i < n; i++ )
1901 {
1902 int proc = TLc.vi_rd[sizeTuple * i];
1903 int sourceID = TLc.vi_rd[sizeTuple * i + 1];
1904 if( sourceID == currentSourceID )
1905 {
1906 if( currentProcsCount.find( proc ) == currentProcsCount.end() )
1907 {
1908 currentProcsCount[proc] = 1;
1909 }
1910 else
1911 currentProcsCount[proc]++;
1912 }
1913 if( sourceID != currentSourceID || ( ( n - 1 ) == i ) )
1914 {
1915
1916
1917 if( currentProcsCount.size() > 1 )
1918 {
1919 #ifdef VERBOSE
1920 std::cout << " source element " << currentSourceID << " intersects with "
1921 << currentProcsCount.size() << " target partitions\n";
1922 for( std::map< int, int >::iterator it = currentProcsCount.begin(); it != currentProcsCount.end();
1923 it++ )
1924 {
1925 int procID = it->first;
1926 int numOverCells = it->second;
1927 std::cout << " task:" << procID << " " << numOverCells << " cells\n";
1928 }
1929
1930 #endif
1931
1932 for( std::map< int, int >::iterator it1 = currentProcsCount.begin(); it1 != currentProcsCount.end();
1933 it1++ )
1934 {
1935 int proc1 = it1->first;
1936 sourcesForTasks[currentSourceID].insert( proc1 );
1937 for( std::map< int, int >::iterator it2 = currentProcsCount.begin();
1938 it2 != currentProcsCount.end(); it2++ )
1939 {
1940 int proc2 = it2->first;
1941 if( proc1 != proc2 ) sizeOfTLc2 += it2->second;
1942 }
1943 }
1944
1945 }
1946 if( sourceID != currentSourceID )
1947 {
1948 currentSourceID = sourceID;
1949 currentProcsCount.clear();
1950 currentProcsCount[proc] = 1;
1951 }
1952 }
1953 }
1954 }
1955
1956
1957
1958 #ifdef MOAB_DBG
1959 std::cout << " need to initialize TLc2 with " << sizeOfTLc2 << " cells\n ";
1960 #endif
1961
1962 TupleList TLc2;
1963 int sizeTuple2 = 5 + globalMaxEdges;
1964
1965
1966 TLc2.initialize( sizeTuple2, 0, 0, 0, sizeOfTLc2 );
1967 TLc2.enableWriteAccess();
1968
1969
1970 std::map< int, std::set< int > > verticesToSendForProc;
1971
1972 for( int i = 0; i < n; i++ )
1973 {
1974 int sourceID = TLc.vi_rd[sizeTuple * i + 1];
1975 if( sourcesForTasks.find( sourceID ) != sourcesForTasks.end() )
1976 {
1977
1978 std::set< int > procs = sourcesForTasks[sourceID];
1979 if( procs.size() < 2 ) MB_CHK_SET_ERR( MB_FAILURE, " not enough processes involved with a sourceID cell" );
1980
1981 int orgProc = TLc.vi_rd[sizeTuple * i];
1982
1983
1984 std::map< int, int >& availableVerticesFromThisProc = availVertexIndicesPerProcessor[orgProc];
1985 for( std::set< int >::iterator setIt = procs.begin(); setIt != procs.end(); setIt++ )
1986 {
1987 int procID = *setIt;
1988
1989
1990 if( procID != orgProc )
1991 {
1992
1993 int n2 = TLc2.get_n();
1994 if( n2 >= sizeOfTLc2 ) MB_CHK_SET_ERR( MB_FAILURE, " memory overflow" );
1995
1996 std::set< int >& indexVerticesInTLv = verticesToSendForProc[procID];
1997 TLc2.vi_wr[n2 * sizeTuple2] = procID;
1998 TLc2.vi_wr[n2 * sizeTuple2 + 1] = orgProc;
1999 TLc2.vi_wr[n2 * sizeTuple2 + 2] = sourceID;
2000 TLc2.vi_wr[n2 * sizeTuple2 + 3] = TLc.vi_rd[sizeTuple * i + 2];
2001
2002 int nvert = TLc.vi_rd[sizeTuple * i + 3];
2003 TLc2.vi_wr[n2 * sizeTuple2 + 4] = nvert;
2004
2005
2006
2007
2008 for( int j = 0; j < nvert; j++ )
2009 {
2010 int vertexIndex = TLc.vi_rd[i * sizeTuple + 4 + j];
2011
2012 if( availableVerticesFromThisProc.find( vertexIndex ) == availableVerticesFromThisProc.end() )
2013 {
2014 MB_CHK_SET_ERR( MB_FAILURE, " vertex index not available from processor" );
2015 }
2016 TLc2.vi_wr[n2 * sizeTuple2 + 5 + j] = vertexIndex;
2017 int indexInTLv = availVertexIndicesPerProcessor[orgProc][vertexIndex];
2018 indexVerticesInTLv.insert( indexInTLv );
2019 }
2020
2021 for( int j = nvert; j < globalMaxEdges; j++ )
2022 {
2023 TLc2.vi_wr[n2 * sizeTuple2 + 5 + j] = 0;
2024 }
2025 TLc2.inc_n();
2026 }
2027 }
2028 }
2029 }
2030
2031
2032
2033
2034 TupleList TLv2;
2035 int numVerts2 = 0;
2036
2037 for( std::map< int, std::set< int > >::iterator it = verticesToSendForProc.begin();
2038 it != verticesToSendForProc.end(); it++ )
2039 {
2040 std::set< int >& indexInTLvSet = it->second;
2041 numVerts2 += (int)indexInTLvSet.size();
2042 }
2043 TLv2.initialize( 3, 0, 0, 3,
2044 numVerts2 );
2045 TLv2.enableWriteAccess();
2046 for( std::map< int, std::set< int > >::iterator it = verticesToSendForProc.begin();
2047 it != verticesToSendForProc.end(); it++ )
2048 {
2049 int sendToProc = it->first;
2050 std::set< int >& indexInTLvSet = it->second;
2051
2052 for( std::set< int >::iterator itSet = indexInTLvSet.begin(); itSet != indexInTLvSet.end(); itSet++ )
2053 {
2054 int indexInTLv = *itSet;
2055 int orgProc = TLv.vi_rd[2 * indexInTLv];
2056 int indexVertexInOrgProc = TLv.vi_rd[2 * indexInTLv + 1];
2057 int nv2 = TLv2.get_n();
2058 TLv2.vi_wr[3 * nv2] = sendToProc;
2059 TLv2.vi_wr[3 * nv2 + 1] = orgProc;
2060 TLv2.vi_wr[3 * nv2 + 2] = indexVertexInOrgProc;
2061 for( int j = 0; j < 3; j++ )
2062 TLv2.vr_wr[3 * nv2 + j] =
2063 TLv.vr_rd[3 * indexInTLv + j];
2064 TLv2.inc_n();
2065 }
2066 }
2067
2068 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv2, 0 );
2069 ( m_pcomm->proc_config().crystal_router() )->gs_transfer( 1, TLc2, 0 );
2070
2071
2072 #ifdef MOAB_DBG
2073 std::stringstream ff2;
2074 ff2 << "TLc2_" << rank << ".txt";
2075 TLc2.print_to_file( ff2.str().c_str() );
2076 std::stringstream ffv2;
2077 ffv2 << "TLv2_" << rank << ".txt";
2078 TLv2.print_to_file( ffv2.str().c_str() );
2079 #endif
2080
2081
2082 Tag ghostTag;
2083 int orig_proc = -1;
2084 rval = m_interface->tag_get_handle( "ORIG_PROC", 1, MB_TYPE_INTEGER, ghostTag, MB_TAG_DENSE | MB_TAG_CREAT,
2085 &orig_proc );MB_CHK_ERR( rval );
2086
2087 int nvNew = TLv2.get_n();
2088
2089
2090 if( 0 == nvNew ) return MB_SUCCESS;
2091
2092 Range newVerts;
2093 rval = m_interface->create_vertices( &( TLv2.vr_rd[0] ), nvNew, newVerts );MB_CHK_ERR( rval );
2094
2095 std::map< int, std::map< int, EntityHandle > > vertexPerProcAndIndex;
2096 for( int i = 0; i < nvNew; i++ )
2097 {
2098 int orgProc = TLv2.vi_rd[3 * i + 1];
2099 int indexInVert = TLv2.vi_rd[3 * i + 2];
2100 vertexPerProcAndIndex[orgProc][indexInVert] = newVerts[i];
2101 }
2102
2103
2104
2105
2106
2107 Range newPolygons;
2108 int ne = TLc2.get_n();
2109 for( int i = 0; i < ne; i++ )
2110 {
2111 int orgProc = TLc2.vi_rd[i * sizeTuple2 + 1];
2112 int sourceID = TLc2.vi_rd[i * sizeTuple2 + 2];
2113 int targetID = TLc2.vi_wr[i * sizeTuple2 + 3];
2114 int nve = TLc2.vi_wr[i * sizeTuple2 + 4];
2115 std::vector< EntityHandle > conn;
2116 conn.resize( nve );
2117 for( int j = 0; j < nve; j++ )
2118 {
2119 int indexV = TLc2.vi_wr[i * sizeTuple2 + 5 + j];
2120 EntityHandle vh = vertexPerProcAndIndex[orgProc][indexV];
2121 conn[j] = vh;
2122 }
2123 EntityHandle polyNew;
2124 rval = m_interface->create_element( MBPOLYGON, &conn[0], nve, polyNew );MB_CHK_ERR( rval );
2125 newPolygons.insert( polyNew );
2126 rval = m_interface->tag_set_data( targetParentTag, &polyNew, 1, &targetID );MB_CHK_ERR( rval );
2127 rval = m_interface->tag_set_data( sourceParentTag, &polyNew, 1, &sourceID );MB_CHK_ERR( rval );
2128 rval = m_interface->tag_set_data( ghostTag, &polyNew, 1, &orgProc );MB_CHK_ERR( rval );
2129 }
2130
2131 #ifdef MOAB_DBG
2132 EntityHandle tmpSet3;
2133 rval = m_interface->create_meshset( MESHSET_SET, tmpSet3 );MB_CHK_SET_ERR( rval, "Can't create temporary set3" );
2134
2135 rval = m_interface->add_entities( tmpSet3, newPolygons );MB_CHK_SET_ERR( rval, "Can't add entities" );
2136
2137 std::stringstream ffs4;
2138 ffs4 << "extraIntxCells" << rank << ".h5m";
2139 rval = m_interface->write_mesh( ffs4.str().c_str(), &tmpSet3, 1 );MB_CHK_ERR( rval );
2140 #endif
2141
2142
2143
2144 rval = m_interface->add_entities( m_overlap_set, newPolygons );MB_CHK_ERR( rval );
2145 return MB_SUCCESS;
2146 }
2147 #endif
2148
2149 #undef MOAB_DBG
2150
2151 ErrorCode TempestRemapper::GetIMasks( Remapper::IntersectionContext ctx, std::vector< int >& masks )
2152 {
2153 Tag maskTag;
2154
2155 int def_val = 1;
2156 ErrorCode rval =
2157 m_interface->tag_get_handle( "GRID_IMASK", 1, MB_TYPE_INTEGER, maskTag, MB_TAG_DENSE | MB_TAG_CREAT, &def_val );MB_CHK_SET_ERR( rval, "Trouble creating GRID_IMASK tag" );
2158
2159 switch( ctx )
2160 {
2161 case Remapper::SourceMesh: {
2162 if( point_cloud_source )
2163 {
2164 masks.resize( m_source_vertices.size() );
2165 rval = m_interface->tag_get_data( maskTag, m_source_vertices, &masks[0] );MB_CHK_SET_ERR( rval, "Trouble getting GRID_IMASK tag" );
2166 }
2167 else
2168 {
2169 masks.resize( m_source_entities.size() );
2170 rval = m_interface->tag_get_data( maskTag, m_source_entities, &masks[0] );MB_CHK_SET_ERR( rval, "Trouble getting GRID_IMASK tag" );
2171 }
2172 return MB_SUCCESS;
2173 }
2174 case Remapper::TargetMesh: {
2175 if( point_cloud_target )
2176 {
2177 masks.resize( m_target_vertices.size() );
2178 rval = m_interface->tag_get_data( maskTag, m_target_vertices, &masks[0] );MB_CHK_SET_ERR( rval, "Trouble getting GRID_IMASK tag" );
2179 }
2180 else
2181 {
2182 masks.resize( m_target_entities.size() );
2183 rval = m_interface->tag_get_data( maskTag, m_target_entities, &masks[0] );MB_CHK_SET_ERR( rval, "Trouble getting GRID_IMASK tag" );
2184 }
2185 return MB_SUCCESS;
2186 }
2187 case Remapper::CoveringMesh:
2188 case Remapper::OverlapMesh:
2189 default:
2190 return MB_SUCCESS;
2191 }
2192 }
2193
2194 }