Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
TempestRemapper.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines