Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
TempestRemapper.hpp
Go to the documentation of this file.
1 /*
2  * =====================================================================================
3  *
4  * Filename: TempestRemapper.hpp
5  *
6  * Description: Interface to the TempestRemap library to enable intersection and
7  * high-order conservative remapping of climate solution from
8  * arbitrary resolution of source and target grids on the sphere.
9  *
10  * Author: Vijay S. Mahadevan (vijaysm), [email protected]
11  *
12  * =====================================================================================
13  */
14 
15 #ifndef MB_TEMPESTREMAPPER_HPP
16 #define MB_TEMPESTREMAPPER_HPP
17 
21 
22 // Tempest includes
23 #ifdef MOAB_HAVE_TEMPESTREMAP
24 #include "netcdfcpp.h"
25 #include "TempestRemapAPI.h"
26 #else
27 #error "This tool depends on TempestRemap library. Reconfigure using --with-tempestremap"
28 #endif
29 
30 namespace moab
31 {
32 
33 // Forward declare our friend, the mapper
34 class TempestOnlineMap;
35 
36 class TempestRemapper : public Remapper
37 {
38  public:
39 #ifdef MOAB_HAVE_MPI
40  TempestRemapper( moab::Interface* mbInt, moab::ParallelComm* pcomm = NULL, bool offlineMode = false )
41  : Remapper( mbInt, pcomm ),
42 #else
43  TempestRemapper( moab::Interface* mbInt, bool offlineMode = false )
44  : Remapper( mbInt ),
45 #endif
46  offlineWorkflow( offlineMode ), meshValidate( false ), constructEdgeMap( false ), m_source_type( DEFAULT ),
48  {
49  }
50 
51  virtual ~TempestRemapper();
52 
53  // Mesh type with a correspondence to Tempest/Climate formats
55  {
56  DEFAULT = -1,
57  CS = 0,
58  RLL = 1,
59  ICO = 2,
60  ICOD = 3,
63  OVERLAP_MOAB = 6
64  };
65 
66  friend class TempestOnlineMap;
67 
68  public:
69  /// <summary>
70  /// Initialize the TempestRemapper object internal datastructures including the mesh sets
71  /// and TempestRemap mesh references.
72  /// </summary>
73  virtual ErrorCode initialize( bool initialize_fsets = true );
74 
75  /// <summary>
76  /// Deallocate and clear any memory initialized in the TempestRemapper object
77  /// </summary>
78  virtual ErrorCode clear();
79 
80  /// <summary>
81  /// Generate a mesh in memory of given type (CS/RLL/ICO/MPAS(structured)) and store it
82  /// under the context specified by the user.
83  /// </summary>
85 
86  /// <summary>
87  /// Load a mesh from disk of given type and store it under the context specified by the
88  /// user.
89  /// </summary>
90  moab::ErrorCode LoadMesh( Remapper::IntersectionContext ctx, std::string inputFilename, TempestMeshType type );
91 
92  /// <summary>
93  /// Construct a source covering mesh such that it completely encompasses the target grid in
94  /// parallel. This operation is critical to ensure that the parallel advancing-front
95  /// intersection algorithm can the intersection mesh only locally without any process
96  /// communication.
97  /// </summary>
99  double radius_src = 1.0,
100  double radius_tgt = 1.0,
101  double boxeps = 0.1,
102  bool regional_mesh = false,
103  bool gnomonic = true );
104 
105  /// <summary>
106  /// Compute the intersection mesh between the source and target grids that have been
107  /// instantiated in the Remapper. This function invokes the parallel advancing-front
108  /// intersection algorithm internally for spherical meshes and can handle arbitrary
109  /// unstructured grids (CS, RLL, ICO, MPAS) with and without holes.
110  /// </summary>
111  moab::ErrorCode ComputeOverlapMesh( bool kdtree_search = true, bool use_tempest = false );
112 
113  /* Converters between MOAB and Tempest representations */
114 
115  /// <summary>
116  /// Convert the TempestRemap mesh object to a corresponding MOAB mesh representation
117  /// according to the intersection context.
118  /// </summary>
120 
121  /// <summary>
122  /// Convert the MOAB mesh representation to a corresponding TempestRemap mesh object
123  /// according to the intersection context.
124  /// </summary>
126 
127  /// <summary>
128  /// Get the TempestRemap mesh object according to the intersection context.
129  /// </summary>
131 
132  /// <summary>
133  /// Set the TempestRemap mesh object according to the intersection context.
134  /// </summary>
135  void SetMesh( Remapper::IntersectionContext ctx, Mesh* mesh, bool overwrite = true );
136 
137  void SetMeshSet( Remapper::IntersectionContext ctx /* Remapper::CoveringMesh*/,
138  moab::EntityHandle mset,
140  /// <summary>
141  /// Get the covering mesh (TempestRemap) object.
142  /// </summary>
143  Mesh* GetCoveringMesh();
144 
145  /// <summary>
146  /// Get the MOAB mesh set corresponding to the intersection context.
147  /// </summary>
149 
150  /// <summary>
151  /// Const overload. Get the MOAB mesh set corresponding to the intersection context.
152  /// </summary>
154 
155  /// <summary>
156  /// Get the mesh element entities corresponding to the intersection context.
157  /// </summary>
159 
160  /// <summary>
161  /// Const overload. Get the mesh element entities corresponding to the intersection context.
162  /// </summary>
164 
165  /// <summary>
166  /// Get the mesh vertices corresponding to the intersection context. Useful for point-cloud
167  /// meshes
168  /// </summary>
170 
171  /// <summary>
172  /// Const overload. Get the mesh vertices corresponding to the intersection context. Useful
173  /// for point-cloud meshes.
174  /// </summary>
176 
177  /// <summary>
178  /// Get access to the underlying source covering set if available. Else return the source
179  /// set.
180  /// </summary>
182 
183  /// <summary>
184  /// Set the mesh type corresponding to the intersection context
185  /// </summary>
186  void SetMeshType( Remapper::IntersectionContext ctx, const std::vector< int >& metadata );
187 
188  /// <summary>
189  /// Get the mesh type corresponding to the intersection context
190  /// </summary>
192 
193  /// <summary>
194  /// Get the global ID corresponding to the local entity ID according to the context (source,
195  /// target, intersection)
196  /// </summary>
197  int GetGlobalID( Remapper::IntersectionContext ctx, int localID );
198 
199  /// <summary>
200  /// Get the local ID corresponding to the global entity ID according to the context (source,
201  /// target, intersection)
202  /// </summary>
203  int GetLocalID( Remapper::IntersectionContext ctx, int globalID );
204 
205  /// <summary>
206  /// Gather the overlap mesh and asssociated source/target data and write it out to disk
207  /// using the TempestRemap output interface. This information can then be used with the
208  /// "GenerateOfflineMap" tool in TempestRemap as needed.
209  /// </summary>
210  moab::ErrorCode WriteTempestIntersectionMesh( std::string strOutputFileName,
211  const bool fAllParallel,
212  const bool fInputConcave,
213  const bool fOutputConcave );
214 
215  /// <summary>
216  /// Generate the necessary metadata and specifically the GLL node numbering for DoFs for a
217  /// CS mesh. This negates the need for running external code like HOMME to output the
218  /// numbering needed for computing maps. The functionality is used through the `mbconvert`
219  /// tool to compute processor-invariant Global DoF IDs at GLL nodes.
220  /// </summary>
221  moab::ErrorCode GenerateCSMeshMetadata( const int ntot_elements,
223  moab::Range* secondary_entities,
224  const std::string& dofTagName,
225  int nP );
226 
227  /// <summary>
228  /// Generate the necessary metadata for DoF node numbering in a given mesh.
229  /// Currently, only the functionality to generate numbering on CS grids is supported.
230  /// </summary>
232  const int ntot_elements,
234  moab::Range* secondary_entities,
235  const std::string dofTagName,
236  int nP );
237 
238  /// <summary>
239  /// Compute the local and global IDs for elements in source/target/coverage meshes.
240  /// </summary>
242 
243  /// <summary>
244  /// Get all the ghosted overlap entities that were accumulated to enable conservation in
245  /// parallel
246  /// </summary>
248 
249 #ifndef MOAB_HAVE_MPI
250  /// <summary>
251  /// Internal method to assign vertex and element global IDs if one does not exist already
252  /// </summary>
254  EntityHandle this_set,
255  const int dimension = 2,
256  const int start_id = 1 );
257 #endif
258  // <summary>
259  /// Get the masks that could have been defined
260  /// </summary>
261  ErrorCode GetIMasks( Remapper::IntersectionContext ctx, std::vector< int >& masks );
262 
263  public: // public members
264  const bool offlineWorkflow; // check whether we are in an offline workflow context (mbtempest)
265  bool meshValidate; // Validate the mesh after loading from file
266 
267  bool constructEdgeMap; // Construct the edge map within the TempestRemap datastructures
268 
269  static const bool verbose = true;
270 
271  private:
273 
274  // private methods
275  moab::ErrorCode load_tempest_mesh_private( std::string inputFilename, Mesh** tempest_mesh );
276 
278  moab::EntityHandle meshset,
280  moab::Range* pverts );
281 
283  Mesh* mesh,
284  moab::EntityHandle& meshset,
286  moab::Range* vertices );
287 
289 
290  /* Source meshset, mesh and entity references */
291  Mesh* m_source;
298  std::vector< int > m_source_metadata;
299 
300  /* Target meshset, mesh and entity references */
301  Mesh* m_target;
308  std::vector< int > m_target_metadata;
309 
310  /* Overlap meshset, mesh and entity references */
311  Mesh* m_overlap;
315  std::vector< std::pair< int, int > > m_sorted_overlap_order;
316 
317  /* Intersection context on a sphere */
319 
320  /* Parallel - migrated mesh that is in the local view */
325 
326  /* local to glboal and global to local ID maps */
329 
331 
332  bool rrmgrids;
334  int rank, size;
335 };
336 
337 // Inline functions
339 {
340  switch( ctx )
341  {
343  return m_source;
345  return m_target;
347  return m_overlap;
349  return m_covering_source;
350  case Remapper::DEFAULT:
351  default:
352  return NULL;
353  }
354 }
355 
356 inline void TempestRemapper::SetMesh( Remapper::IntersectionContext ctx, Mesh* mesh, bool overwrite )
357 {
358  switch( ctx )
359  {
361  if( !overwrite && m_source ) return;
362  if( overwrite && m_source ) delete m_source;
363  m_source = mesh;
364  break;
366  if( !overwrite && m_target ) return;
367  if( overwrite && m_target ) delete m_target;
368  m_target = mesh;
369  break;
371  if( !overwrite && m_overlap ) return;
372  if( overwrite && m_overlap ) delete m_overlap;
373  m_overlap = mesh;
374  break;
376  if( !overwrite && m_covering_source ) return;
377  if( overwrite && m_covering_source ) delete m_covering_source;
378  m_covering_source = mesh;
379  break;
380  case Remapper::DEFAULT:
381  default:
382  break;
383  }
384 }
385 
387 {
388  switch( ctx )
389  {
391  return m_source_set;
393  return m_target_set;
395  return m_overlap_set;
397  return m_covering_source_set;
398  case Remapper::DEFAULT:
399  default:
400  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_set );
401  }
402 }
403 
405 {
406  switch( ctx )
407  {
409  return m_source_set;
411  return m_target_set;
413  return m_overlap_set;
415  return m_covering_source_set;
416  case Remapper::DEFAULT:
417  default:
418  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_set );
419  }
420 }
421 
423 {
424  switch( ctx )
425  {
427  return m_source_entities;
429  return m_target_entities;
431  return m_overlap_entities;
434  case Remapper::DEFAULT:
435  default:
436  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_entities );
437  }
438 }
439 
441 {
442  switch( ctx )
443  {
445  return m_source_entities;
447  return m_target_entities;
449  return m_overlap_entities;
452  case Remapper::DEFAULT:
453  default:
454  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_overlap_entities );
455  }
456 }
457 
459 {
460  switch( ctx )
461  {
463  return m_source_vertices;
465  return m_target_vertices;
468  case Remapper::DEFAULT:
469  default:
470  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_source_vertices );
471  }
472 }
473 
475 {
476  switch( ctx )
477  {
479  return m_source_vertices;
481  return m_target_vertices;
484  case Remapper::DEFAULT:
485  default:
486  MB_SET_ERR_RET_VAL( "Invalid context passed to GetMeshSet", m_source_vertices );
487  }
488 }
489 
490 inline void TempestRemapper::SetMeshType( Remapper::IntersectionContext ctx, const std::vector< int >& metadata )
491 {
492  switch( ctx )
493  {
495  m_source_type = static_cast< moab::TempestRemapper::TempestMeshType >( metadata[0] );
496  if( metadata[0] == 1 ) // RLL mesh
497  {
498  m_source_metadata.resize( 2 );
499  m_source_metadata[0] = metadata[1];
500  m_source_metadata[1] = metadata[2];
501  }
502  else
503  {
504  m_source_metadata.resize( 1 );
505  m_source_metadata[0] = metadata[1];
506  }
507  break;
509  m_target_type = static_cast< moab::TempestRemapper::TempestMeshType >( metadata[0] );
510  if( metadata[0] == 1 ) // RLL mesh
511  {
512  m_target_metadata.resize( 2 );
513  m_target_metadata[0] = metadata[1];
514  m_target_metadata[1] = metadata[2];
515  }
516  else
517  {
518  m_target_metadata.resize( 1 );
519  m_target_metadata[0] = metadata[1];
520  }
521  break;
524  default:
525  break;
526  }
527 }
528 
530 {
531  switch( ctx )
532  {
534  return m_source_type;
536  return m_target_type;
538  return m_overlap_type;
539  case Remapper::DEFAULT:
540  default:
542  }
543 }
544 
546 {
547  return m_covering_source;
548 }
549 
551 {
552  return m_covering_source_set;
553 }
554 
556 {
557  switch( ctx )
558  {
560  return lid_to_gid_src[localID];
562  return lid_to_gid_tgt[localID];
564  return lid_to_gid_covsrc[localID];
566  case Remapper::DEFAULT:
567  default:
568  return -1;
569  }
570 }
571 
573 {
574  switch( ctx )
575  {
577  return gid_to_lid_src[globalID];
579  return gid_to_lid_tgt[globalID];
581  return gid_to_lid_covsrc[globalID];
582  case Remapper::DEFAULT:
584  default:
585  return -1;
586  }
587 }
588 
589 } // namespace moab
590 
591 #endif // MB_TEMPESTREMAPPER_HPP