![]() |
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), mahadevan@anl.gov
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 ///
00069 /// Initialize the TempestRemapper object internal datastructures including the mesh sets
00070 /// and TempestRemap mesh references.
00071 ///
00072 virtual ErrorCode initialize( bool initialize_fsets = true );
00073
00074 ///
00075 /// Deallocate and clear any memory initialized in the TempestRemapper object
00076 ///
00077 virtual ErrorCode clear();
00078
00079 ///
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 ///
00083 moab::ErrorCode GenerateMesh( Remapper::IntersectionContext ctx, TempestMeshType type );
00084
00085 ///
00086 /// Load a mesh from disk of given type and store it under the context specified by the
00087 /// user.
00088 ///
00089 moab::ErrorCode LoadMesh( Remapper::IntersectionContext ctx, std::string inputFilename, TempestMeshType type );
00090
00091 ///
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 ///
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 ///
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 ///
00109 moab::ErrorCode ComputeOverlapMesh( bool kdtree_search = true, bool use_tempest = false );
00110
00111 /* Converters between MOAB and Tempest representations */
00112
00113 ///
00114 /// Convert the TempestRemap mesh object to a corresponding MOAB mesh representation
00115 /// according to the intersection context.
00116 ///
00117 moab::ErrorCode ConvertTempestMesh( Remapper::IntersectionContext ctx );
00118
00119 ///
00120 /// Convert the MOAB mesh representation to a corresponding TempestRemap mesh object
00121 /// according to the intersection context.
00122 ///
00123 moab::ErrorCode ConvertMeshToTempest( Remapper::IntersectionContext ctx );
00124
00125 ///
00126 /// Get the TempestRemap mesh object according to the intersection context.
00127 ///
00128 Mesh* GetMesh( Remapper::IntersectionContext ctx );
00129
00130 ///
00131 /// Set the TempestRemap mesh object according to the intersection context.
00132 ///
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 ///
00139 /// Get the covering mesh (TempestRemap) object.
00140 ///
00141 Mesh* GetCoveringMesh();
00142
00143 ///
00144 /// Get the MOAB mesh set corresponding to the intersection context.
00145 ///
00146 moab::EntityHandle& GetMeshSet( Remapper::IntersectionContext ctx );
00147
00148 ///
00149 /// Const overload. Get the MOAB mesh set corresponding to the intersection context.
00150 ///
00151 moab::EntityHandle GetMeshSet( Remapper::IntersectionContext ctx ) const;
00152
00153 ///
00154 /// Get the mesh element entities corresponding to the intersection context.
00155 ///
00156 moab::Range& GetMeshEntities( Remapper::IntersectionContext ctx );
00157
00158 ///
00159 /// Const overload. Get the mesh element entities corresponding to the intersection context.
00160 ///
00161 const moab::Range& GetMeshEntities( Remapper::IntersectionContext ctx ) const;
00162
00163 ///
00164 /// Get the mesh vertices corresponding to the intersection context. Useful for point-cloud
00165 /// meshes
00166 ///
00167 moab::Range& GetMeshVertices( Remapper::IntersectionContext ctx );
00168
00169 ///
00170 /// Const overload. Get the mesh vertices corresponding to the intersection context. Useful
00171 /// for point-cloud meshes.
00172 ///
00173 const moab::Range& GetMeshVertices( Remapper::IntersectionContext ctx ) const;
00174
00175 ///
00176 /// Get access to the underlying source covering set if available. Else return the source
00177 /// set.
00178 ///
00179 moab::EntityHandle& GetCoveringSet();
00180
00181 ///
00182 /// Set the mesh type corresponding to the intersection context
00183 ///
00184 void SetMeshType( Remapper::IntersectionContext ctx,
00185 TempestMeshType type,
00186 const std::vector< int >* metadata = nullptr );
00187
00188 ///
00189 /// Get the mesh type corresponding to the intersection context
00190 ///
00191 TempestMeshType GetMeshType( Remapper::IntersectionContext ctx ) const;
00192
00193 ///
00194 /// Get the global ID corresponding to the local entity ID according to the context (source,
00195 /// target, intersection)
00196 ///
00197 int GetGlobalID( Remapper::IntersectionContext ctx, int localID );
00198
00199 ///
00200 /// Get the local ID corresponding to the global entity ID according to the context (source,
00201 /// target, intersection)
00202 ///
00203 int GetLocalID( Remapper::IntersectionContext ctx, int globalID );
00204
00205 ///
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 ///
00210 moab::ErrorCode WriteTempestIntersectionMesh( std::string strOutputFileName,
00211 const bool fAllParallel,
00212 const bool fInputConcave,
00213 const bool fOutputConcave );
00214
00215 ///
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 ///
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 ///
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 ///
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 ///
00239 /// Compute the local and global IDs for elements in source/target/coverage meshes.
00240 ///
00241 moab::ErrorCode ComputeGlobalLocalMaps();
00242
00243 ///
00244 /// Get all the ghosted overlap entities that were accumulated to enable conservation in
00245 /// parallel
00246 ///
00247 moab::ErrorCode GetOverlapAugmentedEntities( moab::Range& sharedGhostEntities );
00248
00249 #ifndef MOAB_HAVE_MPI
00250 ///
00251 /// Internal method to assign vertex and element global IDs if one does not exist already
00252 ///
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 //
00259 /// Get the masks that could have been defined
00260 ///
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