Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
Remapper.hpp
Go to the documentation of this file.
1 /*
2  * =====================================================================================
3  *
4  * Filename: Remapper.hpp
5  *
6  * Description: Interface to the a general remapping capability on arbitrary topology
7  * that performs both mesh intersection between a source and target grid,
8  * with arbitrary decompositions. The intersections can then be used to
9  * either evaluate interpolation weights or to perform high-order
10  * conservative remapping of solutions defined on the source grid.
11  *
12  * Author: Vijay S. Mahadevan (vijaysm), [email protected]
13  *
14  * =====================================================================================
15  */
16 
17 #ifndef MB_REMAPPER_HPP
18 #define MB_REMAPPER_HPP
19 
20 #include <string>
21 
22 #include "moab/Interface.hpp"
23 #ifdef MOAB_HAVE_MPI
24 #include "moab/ParallelComm.hpp"
25 #endif
26 
27 // Tempest includes
28 #ifdef MOAB_HAVE_TEMPESTREMAP
29 #include "netcdfcpp.h"
30 #include "TempestRemapAPI.h"
31 #else
32 #error "This tool depends on TempestRemap library. Reconfigure using --with-tempestremap"
33 #endif
34 
35 namespace moab
36 {
37 
38 class Remapper
39 {
40  public:
41 #ifdef MOAB_HAVE_MPI
42  Remapper( moab::Interface* mbInt, moab::ParallelComm* pcomm = NULL ) : m_interface( mbInt ), m_pcomm( pcomm )
43 #else
44  Remapper( moab::Interface* mbInt ) : m_interface( mbInt )
45 #endif
46  {
47  }
48 
49  virtual ~Remapper()
50  {
51 #ifdef MOAB_HAVE_MPI
52  m_pcomm = NULL;
53 #endif
54  m_interface = NULL;
55  }
56 
58  {
59  DEFAULT = -1, // default context
60  SourceMesh = 0, // source mesh
61  TargetMesh = 1, // target mesh
62  OverlapMesh = 2, // overlap/intersection mesh
63  CoveringMesh = 3, // source mesh covering target mesh
64  SourceMeshWithGhosts = 4, // mesh with extra ghost layers to compute coverage in high order case or bilin
65  TargetMeshWithGhosts = 5 // mesh with extra ghost layers to impose target data limiting
66  };
67 
69  {
70  return m_interface;
71  }
72 
73 #ifdef MOAB_HAVE_MPI
74  moab::ParallelComm* get_parallel_communicator()
75  {
76  return m_pcomm;
77  }
78 
79  /// <summary>
80  /// ghost layers
81  /// </summary>
82  moab::ErrorCode GhostLayers( moab::EntityHandle& meshset, const int ngh_layers, moab::EntityHandle& set_with_ghosts )
83  {
84  // meshset contains the mesh set distributed already
85  //
86  moab::ErrorCode rval = m_interface->create_meshset( MESHSET_SET, set_with_ghosts );MB_CHK_ERR( rval );
87  // copy original content of mesh set here; we will use it later for local area, for example
88  // it will not have any ghosts in it
89  moab::Range orgEnts;
90  rval = m_interface->get_entities_by_handle( meshset, orgEnts );MB_CHK_ERR( rval );
91  rval = m_interface->add_entities( set_with_ghosts, orgEnts );MB_CHK_ERR( rval );
92  rval = m_pcomm->exchange_ghost_cells( 2, 0, 1, 0, true, true, &set_with_ghosts );MB_CHK_ERR( rval );
93  for( int i = 2; i <= ngh_layers; i++ )
94  {
95  rval = m_pcomm->correct_thin_ghost_layers();MB_CHK_ERR( rval );
96  rval = m_pcomm->exchange_ghost_cells( 2, 0, i, 0, true, true, &set_with_ghosts );MB_CHK_ERR( rval );
97  }
98 
99  // need to set global id tags
100  // need also to propagate global id to ghost cells; it is not done by default :(
103  rval = m_interface->get_entities_by_dimension( set_with_ghosts, 2, entities );MB_CHK_ERR( rval );
104 
105  moab::Tag doftag;
106  rval = m_interface->tag_get_handle( "GLOBAL_DOFS", doftag );
107  if ( rval == MB_SUCCESS )
108  {
109  moab::Range quads = entities.subset_by_type(moab::MBQUAD);
110  rval = m_pcomm->exchange_tags( doftag, quads );MB_CHK_ERR( rval );
111  }
112 
113  // get all vertices too, need to exchange global ids for vertices too
114  moab::Range vertices;
115  rval = m_interface->get_connectivity( entities, vertices );MB_CHK_ERR( rval );
116  entities.merge( vertices );
117  rval = m_pcomm->exchange_tags( gtag, entities );MB_CHK_ERR( rval );
118  return rval;
119  }
120 
121 #endif
122 
123  ErrorCode LoadNativeMesh( std::string filename,
124  moab::EntityHandle& meshset,
125  std::vector< int >& metadata,
126  const char* readopts = 0 )
127  {
128 #ifdef MOAB_HAVE_MPI
129  std::string opts = "";
130  if( readopts )
131  {
132  if( opts.size() )
133  opts = opts + ";" + std::string( readopts );
134  else
135  opts = std::string( readopts );
136  }
137 
138  if( !m_pcomm->rank() ) std::cout << "Reading file (" << filename << ") with options = [" << opts << "]\n";
139 #else
140  const std::string opts = std::string( ( readopts ? readopts : "" ) );
141  std::cout << "Reading file (" << filename << ") with options = [" << opts << "]\n";
142 #endif
143  moab::ErrorCode rval = m_interface->load_file( filename.c_str(), &meshset, opts.c_str() );MB_CHK_ERR( rval );
144 
145  Tag rectilinearTag;
146  rval = m_interface->tag_get_handle( "ClimateMetadata", rectilinearTag );
147 
148  if( rval != MB_FAILURE && rval != MB_TAG_NOT_FOUND && rval != MB_ALREADY_ALLOCATED &&
149  rectilinearTag != nullptr )
150  {
151  int dimSizes[3];
152  rval = m_interface->tag_get_data( rectilinearTag, &meshset, 1,
153  dimSizes ); // MB_CHK_SET_ERR( rval, "Error geting tag data" );
154  metadata.clear();
155  metadata.push_back( dimSizes[0] );
156  metadata.push_back( dimSizes[1] );
157  metadata.push_back( dimSizes[2] );
158  }
159 
160  return MB_SUCCESS;
161  }
162 
163  protected:
164  // member data
166 
167 #ifdef MOAB_HAVE_MPI
168  ParallelComm* m_pcomm;
169 #endif
170 };
171 
172 } // namespace moab
173 
174 #endif /* MB_REMAPPER_HPP */