Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /* 00002 * ===================================================================================== 00003 * 00004 * Filename: TempestRemapper.hpp 00005 * 00006 * Description: Interface to the TempestRemap library to enable intersection and 00007 * high-order conservative remapping of climate solution from 00008 * arbitrary resolution of source and target grids on the sphere. 00009 * 00010 * Author: Vijay S. Mahadevan (vijaysm), [email protected] 00011 * 00012 * ===================================================================================== 00013 */ 00014 00015 #ifndef MB_TEMPESTREMAPPER_HPP 00016 #define MB_TEMPESTREMAPPER_HPP 00017 00018 #include "moab/Remapping/Remapper.hpp" 00019 #include "moab/IntxMesh/Intx2MeshOnSphere.hpp" 00020 #include "moab/IntxMesh/IntxUtils.hpp" 00021 00022 // Tempest includes 00023 #ifdef MOAB_HAVE_TEMPESTREMAP 00024 #include "netcdfcpp.h" 00025 #include "TempestRemapAPI.h" 00026 #else 00027 #error "This tool depends on TempestRemap library. Reconfigure using --with-tempestremap" 00028 #endif 00029 00030 namespace moab 00031 { 00032 00033 // Forward declare our friend, the mapper 00034 class TempestOnlineMap; 00035 00036 class TempestRemapper : public Remapper 00037 { 00038 public: 00039 #ifdef MOAB_HAVE_MPI 00040 TempestRemapper( moab::Interface* mbInt, moab::ParallelComm* pcomm = NULL ) 00041 : Remapper( mbInt, pcomm ), 00042 #else 00043 TempestRemapper( moab::Interface* mbInt ) 00044 : Remapper( mbInt ), 00045 #endif 00046 meshValidate( false ), constructEdgeMap( false ), m_source_type( DEFAULT ), m_target_type( DEFAULT ) 00047 { 00048 } 00049 00050 virtual ~TempestRemapper(); 00051 00052 // Mesh type with a correspondence to Tempest/Climate formats 00053 enum TempestMeshType 00054 { 00055 DEFAULT = -1, 00056 CS = 0, 00057 RLL = 1, 00058 ICO = 2, 00059 ICOD = 3, 00060 OVERLAP_FILES = 4, 00061 OVERLAP_MEMORY = 5, 00062 OVERLAP_MOAB = 6 00063 }; 00064 00065 friend class TempestOnlineMap; 00066 00067 public: 00068 /// <summary> 00069 /// Initialize the TempestRemapper object internal datastructures including the mesh sets 00070 /// and TempestRemap mesh references. 00071 /// </summary> 00072 virtual ErrorCode initialize( bool initialize_fsets = true ); 00073 00074 /// <summary> 00075 /// Deallocate and clear any memory initialized in the TempestRemapper object 00076 /// </summary> 00077 virtual ErrorCode clear(); 00078 00079 /// <summary> 00080 /// Generate a mesh in memory of given type (CS/RLL/ICO/MPAS(structured)) and store it 00081 /// under the context specified by the user. 00082 /// </summary> 00083 moab::ErrorCode GenerateMesh( Remapper::IntersectionContext ctx, TempestMeshType type ); 00084 00085 /// <summary> 00086 /// Load a mesh from disk of given type and store it under the context specified by the 00087 /// user. 00088 /// </summary> 00089 moab::ErrorCode LoadMesh( Remapper::IntersectionContext ctx, std::string inputFilename, TempestMeshType type ); 00090 00091 /// <summary> 00092 /// Construct a source covering mesh such that it completely encompasses the target grid in 00093 /// parallel. This operation is critical to ensure that the parallel advancing-front 00094 /// intersection algorithm can the intersection mesh only locally without any process 00095 /// communication. 00096 /// </summary> 00097 moab::ErrorCode ConstructCoveringSet( double tolerance = 1e-8, 00098 double radius_src = 1.0, 00099 double radius_tgt = 1.0, 00100 double boxeps = 0.1, 00101 bool regional_mesh = false ); 00102 00103 /// <summary> 00104 /// Compute the intersection mesh between the source and target grids that have been 00105 /// instantiated in the Remapper. This function invokes the parallel advancing-front 00106 /// intersection algorithm internally for spherical meshes and can handle arbitrary 00107 /// unstructured grids (CS, RLL, ICO, MPAS) with and without holes. 00108 /// </summary> 00109 moab::ErrorCode ComputeOverlapMesh( bool kdtree_search = true, bool use_tempest = false ); 00110 00111 /* Converters between MOAB and Tempest representations */ 00112 00113 /// <summary> 00114 /// Convert the TempestRemap mesh object to a corresponding MOAB mesh representation 00115 /// according to the intersection context. 00116 /// </summary> 00117 moab::ErrorCode ConvertTempestMesh( Remapper::IntersectionContext ctx ); 00118 00119 /// <summary> 00120 /// Convert the MOAB mesh representation to a corresponding TempestRemap mesh object 00121 /// according to the intersection context. 00122 /// </summary> 00123 moab::ErrorCode ConvertMeshToTempest( Remapper::IntersectionContext ctx ); 00124 00125 /// <summary> 00126 /// Get the TempestRemap mesh object according to the intersection context. 00127 /// </summary> 00128 Mesh* GetMesh( Remapper::IntersectionContext ctx ); 00129 00130 /// <summary> 00131 /// Set the TempestRemap mesh object according to the intersection context. 00132 /// </summary> 00133 void SetMesh( Remapper::IntersectionContext ctx, Mesh* mesh, bool overwrite = true ); 00134 00135 void SetMeshSet( Remapper::IntersectionContext ctx /* Remapper::CoveringMesh*/, 00136 moab::EntityHandle mset, 00137 moab::Range& entities ); 00138 /// <summary> 00139 /// Get the covering mesh (TempestRemap) object. 00140 /// </summary> 00141 Mesh* GetCoveringMesh(); 00142 00143 /// <summary> 00144 /// Get the MOAB mesh set corresponding to the intersection context. 00145 /// </summary> 00146 moab::EntityHandle& GetMeshSet( Remapper::IntersectionContext ctx ); 00147 00148 /// <summary> 00149 /// Const overload. Get the MOAB mesh set corresponding to the intersection context. 00150 /// </summary> 00151 moab::EntityHandle GetMeshSet( Remapper::IntersectionContext ctx ) const; 00152 00153 /// <summary> 00154 /// Get the mesh element entities corresponding to the intersection context. 00155 /// </summary> 00156 moab::Range& GetMeshEntities( Remapper::IntersectionContext ctx ); 00157 00158 /// <summary> 00159 /// Const overload. Get the mesh element entities corresponding to the intersection context. 00160 /// </summary> 00161 const moab::Range& GetMeshEntities( Remapper::IntersectionContext ctx ) const; 00162 00163 /// <summary> 00164 /// Get the mesh vertices corresponding to the intersection context. Useful for point-cloud 00165 /// meshes 00166 /// </summary> 00167 moab::Range& GetMeshVertices( Remapper::IntersectionContext ctx ); 00168 00169 /// <summary> 00170 /// Const overload. Get the mesh vertices corresponding to the intersection context. Useful 00171 /// for point-cloud meshes. 00172 /// </summary> 00173 const moab::Range& GetMeshVertices( Remapper::IntersectionContext ctx ) const; 00174 00175 /// <summary> 00176 /// Get access to the underlying source covering set if available. Else return the source 00177 /// set. 00178 /// </summary> 00179 moab::EntityHandle& GetCoveringSet(); 00180 00181 /// <summary> 00182 /// Set the mesh type corresponding to the intersection context 00183 /// </summary> 00184 void SetMeshType( Remapper::IntersectionContext ctx, 00185 TempestMeshType type, 00186 const std::vector< int >* metadata = nullptr ); 00187 00188 /// <summary> 00189 /// Get the mesh type corresponding to the intersection context 00190 /// </summary> 00191 TempestMeshType GetMeshType( Remapper::IntersectionContext ctx ) const; 00192 00193 /// <summary> 00194 /// Get the global ID corresponding to the local entity ID according to the context (source, 00195 /// target, intersection) 00196 /// </summary> 00197 int GetGlobalID( Remapper::IntersectionContext ctx, int localID ); 00198 00199 /// <summary> 00200 /// Get the local ID corresponding to the global entity ID according to the context (source, 00201 /// target, intersection) 00202 /// </summary> 00203 int GetLocalID( Remapper::IntersectionContext ctx, int globalID ); 00204 00205 /// <summary> 00206 /// Gather the overlap mesh and asssociated source/target data and write it out to disk 00207 /// using the TempestRemap output interface. This information can then be used with the 00208 /// "GenerateOfflineMap" tool in TempestRemap as needed. 00209 /// </summary> 00210 moab::ErrorCode WriteTempestIntersectionMesh( std::string strOutputFileName, 00211 const bool fAllParallel, 00212 const bool fInputConcave, 00213 const bool fOutputConcave ); 00214 00215 /// <summary> 00216 /// Generate the necessary metadata and specifically the GLL node numbering for DoFs for a 00217 /// CS mesh. This negates the need for running external code like HOMME to output the 00218 /// numbering needed for computing maps. The functionality is used through the `mbconvert` 00219 /// tool to compute processor-invariant Global DoF IDs at GLL nodes. 00220 /// </summary> 00221 moab::ErrorCode GenerateCSMeshMetadata( const int ntot_elements, 00222 moab::Range& entities, 00223 moab::Range* secondary_entities, 00224 const std::string& dofTagName, 00225 int nP ); 00226 00227 /// <summary> 00228 /// Generate the necessary metadata for DoF node numbering in a given mesh. 00229 /// Currently, only the functionality to generate numbering on CS grids is supported. 00230 /// </summary> 00231 moab::ErrorCode GenerateMeshMetadata( Mesh& mesh, 00232 const int ntot_elements, 00233 moab::Range& entities, 00234 moab::Range* secondary_entities, 00235 const std::string dofTagName, 00236 int nP ); 00237 00238 /// <summary> 00239 /// Compute the local and global IDs for elements in source/target/coverage meshes. 00240 /// </summary> 00241 moab::ErrorCode ComputeGlobalLocalMaps(); 00242 00243 /// <summary> 00244 /// Get all the ghosted overlap entities that were accumulated to enable conservation in 00245 /// parallel 00246 /// </summary> 00247 moab::ErrorCode GetOverlapAugmentedEntities( moab::Range& sharedGhostEntities ); 00248 00249 #ifndef MOAB_HAVE_MPI 00250 /// <summary> 00251 /// Internal method to assign vertex and element global IDs if one does not exist already 00252 /// </summary> 00253 moab::ErrorCode assign_vertex_element_IDs( Tag idtag, 00254 EntityHandle this_set, 00255 const int dimension = 2, 00256 const int start_id = 1 ); 00257 #endif 00258 // <summary> 00259 /// Get the masks that could have been defined 00260 /// </summary> 00261 ErrorCode GetIMasks( Remapper::IntersectionContext ctx, std::vector< int >& masks ); 00262 00263 // used in debugging 00264 std::string get_intx_name() { return intx_name;} 00265 void set_intx_name(std::string in) { intx_name = in;} 00266 00267 public: // public members 00268 bool meshValidate; // Validate the mesh after loading from file 00269 00270 bool constructEdgeMap; // Construct the edge map within the TempestRemap datastructures 00271 00272 static const bool verbose = true; 00273 00274 private: 00275 moab::ErrorCode convert_overlap_mesh_sorted_by_source(); 00276 00277 // private methods 00278 moab::ErrorCode load_tempest_mesh_private( std::string inputFilename, Mesh** tempest_mesh ); 00279 00280 moab::ErrorCode convert_mesh_to_tempest_private( Mesh* mesh, 00281 moab::EntityHandle meshset, 00282 moab::Range& entities, 00283 moab::Range* pverts ); 00284 00285 moab::ErrorCode convert_tempest_mesh_private( TempestMeshType type, 00286 Mesh* mesh, 00287 moab::EntityHandle& meshset, 00288 moab::Range& entities, 00289 moab::Range* vertices ); 00290 00291 moab::ErrorCode augment_overlap_set(); 00292 00293 /* Source meshset, mesh and entity references */ 00294 Mesh* m_source; 00295 TempestMeshType m_source_type; 00296 moab::Range m_source_entities; 00297 moab::Range m_source_vertices; 00298 moab::EntityHandle m_source_set; 00299 int max_source_edges; 00300 bool point_cloud_source; 00301 std::vector< int > m_source_metadata; 00302 00303 /* Target meshset, mesh and entity references */ 00304 Mesh* m_target; 00305 TempestMeshType m_target_type; 00306 moab::Range m_target_entities; 00307 moab::Range m_target_vertices; 00308 moab::EntityHandle m_target_set; 00309 int max_target_edges; 00310 bool point_cloud_target; 00311 std::vector< int > m_target_metadata; 00312 00313 /* Overlap meshset, mesh and entity references */ 00314 Mesh* m_overlap; 00315 TempestMeshType m_overlap_type; 00316 moab::Range m_overlap_entities; 00317 moab::EntityHandle m_overlap_set; 00318 std::vector< std::pair< int, int > > m_sorted_overlap_order; 00319 00320 /* Intersection context on a sphere */ 00321 moab::Intx2MeshOnSphere* mbintx; 00322 00323 /* Parallel - migrated mesh that is in the local view */ 00324 Mesh* m_covering_source; 00325 moab::EntityHandle m_covering_source_set; 00326 moab::Range m_covering_source_entities; 00327 moab::Range m_covering_source_vertices; 00328 00329 /* local to glboal and global to local ID maps */ 00330 std::map< int, int > gid_to_lid_src, gid_to_lid_covsrc, gid_to_lid_tgt; 00331 std::map< int, int > lid_to_gid_src, lid_to_gid_covsrc, lid_to_gid_tgt; 00332 00333 IntxAreaUtils::AreaMethod m_area_method; 00334 00335 bool rrmgrids; 00336 bool is_parallel, is_root; 00337 int rank, size; 00338 std::string intx_name; 00339 }; 00340 00341 // Inline functions 00342 inline Mesh* TempestRemapper::GetMesh( Remapper::IntersectionContext ctx ) 00343 { 00344 switch( ctx ) 00345 { 00346 case Remapper::SourceMesh: 00347 return m_source; 00348 case Remapper::TargetMesh: 00349 return m_target; 00350 case Remapper::OverlapMesh: 00351 return m_overlap; 00352 case Remapper::CoveringMesh: 00353 return m_covering_source; 00354 case Remapper::DEFAULT: 00355 default: 00356 return NULL; 00357 } 00358 } 00359 00360 inline void TempestRemapper::SetMesh( Remapper::IntersectionContext ctx, Mesh* mesh, bool overwrite ) 00361 { 00362 switch( ctx ) 00363 { 00364 case Remapper::SourceMesh: 00365 if( !overwrite && m_source ) return; 00366 if( overwrite && m_source ) delete m_source; 00367 m_source = mesh; 00368 break; 00369 case Remapper::TargetMesh: 00370 if( !overwrite && m_target ) return; 00371 if( overwrite && m_target ) delete m_target; 00372 m_target = mesh; 00373 break; 00374 case Remapper::OverlapMesh: 00375 if( !overwrite && m_overlap ) return; 00376 if( overwrite && m_overlap ) delete m_overlap; 00377 m_overlap = mesh; 00378 break; 00379 case Remapper::CoveringMesh: 00380 if( !overwrite && m_covering_source ) return; 00381 if( overwrite && m_covering_source ) delete m_covering_source; 00382 m_covering_source = mesh; 00383 break; 00384 case Remapper::DEFAULT: 00385 default: 00386 break; 00387 } 00388 } 00389 00390 inline moab::EntityHandle& TempestRemapper::GetMeshSet( Remapper::IntersectionContext ctx ) 00391 { 00392 switch( ctx ) 00393 { 00394 case Remapper::SourceMesh: 00395 return m_source_set; 00396 case Remapper::TargetMesh: 00397 return m_target_set; 00398 case Remapper::OverlapMesh: 00399 return m_overlap_set; 00400 case Remapper::CoveringMesh: 00401 return m_covering_source_set; 00402 case Remapper::DEFAULT: 00403 default: 00404 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_set ); 00405 } 00406 } 00407 00408 inline moab::EntityHandle TempestRemapper::GetMeshSet( Remapper::IntersectionContext ctx ) const 00409 { 00410 switch( ctx ) 00411 { 00412 case Remapper::SourceMesh: 00413 return m_source_set; 00414 case Remapper::TargetMesh: 00415 return m_target_set; 00416 case Remapper::OverlapMesh: 00417 return m_overlap_set; 00418 case Remapper::CoveringMesh: 00419 return m_covering_source_set; 00420 case Remapper::DEFAULT: 00421 default: 00422 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_set ); 00423 } 00424 } 00425 00426 inline moab::Range& TempestRemapper::GetMeshEntities( Remapper::IntersectionContext ctx ) 00427 { 00428 switch( ctx ) 00429 { 00430 case Remapper::SourceMesh: 00431 return m_source_entities; 00432 case Remapper::TargetMesh: 00433 return m_target_entities; 00434 case Remapper::OverlapMesh: 00435 return m_overlap_entities; 00436 case Remapper::CoveringMesh: 00437 return m_covering_source_entities; 00438 case Remapper::DEFAULT: 00439 default: 00440 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_entities ); 00441 } 00442 } 00443 00444 inline const moab::Range& TempestRemapper::GetMeshEntities( Remapper::IntersectionContext ctx ) const 00445 { 00446 switch( ctx ) 00447 { 00448 case Remapper::SourceMesh: 00449 return m_source_entities; 00450 case Remapper::TargetMesh: 00451 return m_target_entities; 00452 case Remapper::OverlapMesh: 00453 return m_overlap_entities; 00454 case Remapper::CoveringMesh: 00455 return m_covering_source_entities; 00456 case Remapper::DEFAULT: 00457 default: 00458 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_entities ); 00459 } 00460 } 00461 00462 inline moab::Range& TempestRemapper::GetMeshVertices( Remapper::IntersectionContext ctx ) 00463 { 00464 switch( ctx ) 00465 { 00466 case Remapper::SourceMesh: 00467 return m_source_vertices; 00468 case Remapper::TargetMesh: 00469 return m_target_vertices; 00470 case Remapper::CoveringMesh: 00471 return m_covering_source_vertices; 00472 case Remapper::DEFAULT: 00473 default: 00474 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_source_vertices ); 00475 } 00476 } 00477 00478 inline const moab::Range& TempestRemapper::GetMeshVertices( Remapper::IntersectionContext ctx ) const 00479 { 00480 switch( ctx ) 00481 { 00482 case Remapper::SourceMesh: 00483 return m_source_vertices; 00484 case Remapper::TargetMesh: 00485 return m_target_vertices; 00486 case Remapper::CoveringMesh: 00487 return m_covering_source_vertices; 00488 case Remapper::DEFAULT: 00489 default: 00490 MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_source_vertices ); 00491 } 00492 } 00493 00494 inline void TempestRemapper::SetMeshType( Remapper::IntersectionContext ctx, 00495 TempestRemapper::TempestMeshType type, 00496 const std::vector< int >* metadata ) 00497 { 00498 switch( ctx ) 00499 { 00500 case Remapper::SourceMesh: 00501 m_source_type = type; 00502 if( metadata ) 00503 { 00504 m_source_metadata.resize( metadata->size() ); 00505 std::copy( metadata->begin(), metadata->end(), m_source_metadata.begin() ); 00506 } 00507 break; 00508 case Remapper::TargetMesh: 00509 m_target_type = type; 00510 if( metadata ) 00511 { 00512 m_target_metadata.resize( metadata->size() ); 00513 std::copy( metadata->begin(), metadata->end(), m_target_metadata.begin() ); 00514 } 00515 break; 00516 case Remapper::OverlapMesh: 00517 m_overlap_type = type; 00518 break; 00519 case Remapper::DEFAULT: 00520 default: 00521 break; 00522 } 00523 } 00524 00525 inline TempestRemapper::TempestMeshType TempestRemapper::GetMeshType( Remapper::IntersectionContext ctx ) const 00526 { 00527 switch( ctx ) 00528 { 00529 case Remapper::SourceMesh: 00530 return m_source_type; 00531 case Remapper::TargetMesh: 00532 return m_target_type; 00533 case Remapper::OverlapMesh: 00534 return m_overlap_type; 00535 case Remapper::DEFAULT: 00536 default: 00537 return TempestRemapper::DEFAULT; 00538 } 00539 } 00540 00541 inline Mesh* TempestRemapper::GetCoveringMesh() 00542 { 00543 return m_covering_source; 00544 } 00545 00546 inline moab::EntityHandle& TempestRemapper::GetCoveringSet() 00547 { 00548 return m_covering_source_set; 00549 } 00550 00551 inline int TempestRemapper::GetGlobalID( Remapper::IntersectionContext ctx, int localID ) 00552 { 00553 switch( ctx ) 00554 { 00555 case Remapper::SourceMesh: 00556 return lid_to_gid_src[localID]; 00557 case Remapper::TargetMesh: 00558 return lid_to_gid_tgt[localID]; 00559 case Remapper::CoveringMesh: 00560 return lid_to_gid_covsrc[localID]; 00561 case Remapper::OverlapMesh: 00562 case Remapper::DEFAULT: 00563 default: 00564 return -1; 00565 } 00566 } 00567 00568 inline int TempestRemapper::GetLocalID( Remapper::IntersectionContext ctx, int globalID ) 00569 { 00570 switch( ctx ) 00571 { 00572 case Remapper::SourceMesh: 00573 return gid_to_lid_src[globalID]; 00574 case Remapper::TargetMesh: 00575 return gid_to_lid_tgt[globalID]; 00576 case Remapper::CoveringMesh: 00577 return gid_to_lid_covsrc[globalID]; 00578 case Remapper::DEFAULT: 00579 case Remapper::OverlapMesh: 00580 default: 00581 return -1; 00582 } 00583 } 00584 00585 } // namespace moab 00586 00587 #endif // MB_TEMPESTREMAPPER_HPP