Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
TempestOnlineMap.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file TempestOnlineMap.h
4 /// \author Vijay Mahadevan
5 /// \version November 20, 2017
6 ///
7 
8 #ifndef _TEMPESTONLINEMAP_H_
9 #define _TEMPESTONLINEMAP_H_
10 
11 #include "moab/MOABConfig.h"
12 #ifndef MOAB_HAVE_TEMPESTREMAP
13 #error Re-configure with TempestRemap
14 #endif
15 
17 
18 // Tempest includes
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
21 #pragma GCC diagnostic ignored "-Wunused-variable"
22 #include "OfflineMap.h"
23 
24 #ifdef MOAB_HAVE_EIGEN3
25 // #ifdef MOAB_HAVE_BLAS
26 // #define EIGEN_USE_BLAS
27 // #endif
28 // #define EIGEN_DONT_PARALLELIZE
29 // #define EIGEN_DONT_VECTORIZE
30 // #define EIGEN_STRONG_INLINE
31 #define EIGEN_DEFAULT_TO_ROW_MAJOR
32 #define EIGEN_RUNTIME_NO_MALLOC
33 // #define EIGEN_UNROLLING_LIMIT 0
34 #include <Eigen/Sparse>
35 #endif
36 
37 #include <unordered_set>
38 
39 #pragma GCC diagnostic pop
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 
43 #if !defined( RECTANGULAR_TRUNCATION ) && !defined( TRIANGULAR_TRUNCATION )
44 #define RECTANGULAR_TRUNCATION
45 // #define TRIANGULAR_TRUNCATION
46 #endif
47 
48 ///////////////////////////////////////////////////////////////////////////////
49 
50 // Forward declarations
51 class Mesh;
52 
53 ///////////////////////////////////////////////////////////////////////////////
54 
55 namespace moab
56 {
57 
58 /// <summary>
59 /// An offline map between two Meshes.
60 /// </summary>
61 class TempestOnlineMap : public OfflineMap
62 {
63 
64  public:
65  /// <summary>
66  /// Generate the metadata associated with the offline map.
67  /// </summary>
69 
70  /// <summary>
71  /// Define a virtual destructor.
72  /// </summary>
73  virtual ~TempestOnlineMap();
74 
75  public:
76  // Input / Output types
78  {
83  };
84 
85  // Type of limiter
86  enum CAASType
87  {
88  CAAS_NONE = 0,
92  CAAS_QLT = 4
93  };
94 
95  /// <summary>
96  /// Generate the offline map, given the source and target mesh and discretization details.
97  /// This method generates the mapping between the two meshes based on the overlap and stores
98  /// the result in the SparseMatrix.
99  /// </summary>
100  moab::ErrorCode GenerateRemappingWeights( std::string strInputType,
101  std::string strOutputType,
102  const GenerateOfflineMapAlgorithmOptions& mapOptions,
103  const std::string& srcDofTagName = "GLOBAL_ID",
104  const std::string& tgtDofTagName = "GLOBAL_ID" );
105 
106  /// <summary>
107  /// Generate the metadata associated with the offline map.
108  /// </summary>
109  // moab::ErrorCode GenerateMetaData();
110 
111  /// <summary>
112  /// Read the OfflineMap from a NetCDF file.
113  /// </summary>
114  moab::ErrorCode ReadParallelMap( const char* strSource,
115  const std::vector< int >& tgt_dof_ids,
116  std::vector< double >& areaA,
117  int& nA,
118  std::vector< double >& areaB,
119  int& nB );
120 
121  /// <summary>
122  /// Write the TempestOnlineMap to a parallel NetCDF file.
123  /// </summary>
124  moab::ErrorCode WriteParallelMap( const std::string& strTarget,
125  const std::map< std::string, std::string >& attrMap );
126 
127  /// <summary>
128  /// Determine if the map is first-order accurate.
129  /// </summary>
130  virtual int IsConsistent( double dTolerance );
131 
132  /// <summary>
133  /// Determine if the map is conservative.
134  /// </summary>
135  virtual int IsConservative( double dTolerance );
136 
137  /// <summary>
138  /// Determine if the map is monotone.
139  /// </summary>
140  virtual int IsMonotone( double dTolerance );
141 
142  /// <summary>
143  /// If we computed the reduction, get the vector representing the source areas for all entities
144  /// in the mesh
145  /// </summary>
146  const DataArray1D< double >& GetGlobalSourceAreas() const;
147 
148  /// <summary>
149  /// If we computed the reduction, get the vector representing the target areas for all entities
150  /// in the mesh
151  /// </summary>
152  const DataArray1D< double >& GetGlobalTargetAreas() const;
153 
154  /// <summary>
155  /// Print information and metadata about the remapping weights.
156  /// </summary>
157  void PrintMapStatistics();
158 
159  private:
160  /// <summary>
161  /// Compute the remapping weights as a permutation matrix that relates DoFs on the source
162  /// mesh
163  /// to DoFs on the target mesh.
164  /// </summary>
165  moab::ErrorCode LinearRemapNN_MOAB( bool use_GID_matching = false, bool strict_check = false );
166 
167  /// <summary>
168  /// Compute the remapping weights for a FV field defined on the source to a
169  /// FV field defined on the target mesh.
170  /// </summary>
171  void LinearRemapFVtoFV_Tempest_MOAB( int nOrder );
172 
173  /// <summary>
174  /// Generate the OfflineMap for linear conserative element-average
175  /// spectral element to element average remapping.
176  /// </summary>
177  void LinearRemapSE0_Tempest_MOAB( const DataArray3D< int >& dataGLLNodes,
178  const DataArray3D< double >& dataGLLJacobian );
179 
180  /// <summary>
181  /// Generate the OfflineMap for cubic conserative element-average
182  /// spectral element to element average remapping.
183  /// </summary>
184  void LinearRemapSE4_Tempest_MOAB( const DataArray3D< int >& dataGLLNodes,
185  const DataArray3D< double >& dataGLLJacobian,
186  int nMonotoneType,
187  bool fContinuousIn,
188  bool fNoConservation );
189 
190  /// <summary>
191  /// Generate the OfflineMap for remapping from finite volumes to finite
192  /// elements.
193  /// </summary>
194  void LinearRemapFVtoGLL_MOAB( const DataArray3D< int >& dataGLLNodes,
195  const DataArray3D< double >& dataGLLJacobian,
196  const DataArray1D< double >& dataGLLNodalArea,
197  int nOrder,
198  int nMonotoneType,
199  bool fContinuous,
200  bool fNoConservation );
201 
202  /// <summary>
203  /// Generate the OfflineMap for remapping from finite elements to finite
204  /// elements.
205  /// </summary>
206  void LinearRemapGLLtoGLL2_MOAB( const DataArray3D< int >& dataGLLNodesIn,
207  const DataArray3D< double >& dataGLLJacobianIn,
208  const DataArray3D< int >& dataGLLNodesOut,
209  const DataArray3D< double >& dataGLLJacobianOut,
210  const DataArray1D< double >& dataNodalAreaOut,
211  int nPin,
212  int nPout,
213  int nMonotoneType,
214  bool fContinuousIn,
215  bool fContinuousOut,
216  bool fNoConservation );
217 
218  /// <summary>
219  /// Generate the OfflineMap for remapping from finite elements to finite
220  /// elements (pointwise interpolation).
221  /// </summary>
222  void LinearRemapGLLtoGLL2_Pointwise_MOAB( const DataArray3D< int >& dataGLLNodesIn,
223  const DataArray3D< double >& dataGLLJacobianIn,
224  const DataArray3D< int >& dataGLLNodesOut,
225  const DataArray3D< double >& dataGLLJacobianOut,
226  const DataArray1D< double >& dataNodalAreaOut,
227  int nPin,
228  int nPout,
229  int nMonotoneType,
230  bool fContinuousIn,
231  bool fContinuousOut );
232 
233  /// <summary>
234  /// Copy the local matrix from Tempest SparseMatrix representation (ELL)
235  /// to the parallel CSR Eigen Matrix for scalable application of matvec
236  /// needed for projections.
237  /// </summary>
238 #ifdef MOAB_HAVE_EIGEN3
239  void copy_tempest_sparsemat_to_eigen3();
240 #endif
241 
242  /// <summary>
243  /// Parallel I/O with HDF5 to write out the remapping weights from multiple processors.
244  /// </summary>
245  moab::ErrorCode WriteSCRIPMapFile( const std::string& strOutputFile,
246  const std::map< std::string, std::string >& attrMap );
247 
248  /// <summary>
249  /// Parallel I/O with NetCDF to write out the SCRIP file from multiple processors.
250  /// </summary>
251  moab::ErrorCode WriteHDF5MapFile( const std::string& filename );
252 
253  public:
254  /// <summary>
255  /// Store the tag names associated with global DoF ids for source and target meshes to be used for mapping.
256  /// <param name="srcDofTagName">The tag name associated with global DoF ids for the source mesh</param>
257  /// <param name="tgtDofTagName">The tag name associated with global DoF ids for the target mesh</param>
258  /// </summary>
259  moab::ErrorCode SetDOFmapTags( const std::string srcDofTagName, const std::string tgtDofTagName );
260 
261  /// <summary>
262  /// @brief Compute the association between the solution tag global DoF numbering and
263  /// the local matrix numbering so that matvec operations can be performed
264  /// consistently.
265  /// <param name="srcType">The discretization type of the source mesh</param>
266  /// <param name="srcOrder">The order of the discretization on the source mesh</param>
267  /// <param name="isSrcContinuous">The continuity of the discretization on the source mesh</param>
268  /// <param name="srcdataGLLNodes">The GLL nodes on the source mesh</param>
269  /// <param name="srcdataGLLNodesSrc">The GLL nodes on the source mesh</param>
270  /// <param name="destType">The discretization type of the destination mesh</param>
271  /// <param name="destOrder">The order of the discretization on the destination mesh</param>
272  /// <param name="isTgtContinuous">The continuity of the discretization on the destination mesh</param>
273  /// <param name="tgtdataGLLNodes">The GLL nodes on the destination mesh</param>
274  /// </summary>
276  int srcOrder,
277  bool isSrcContinuous,
278  DataArray3D< int >* srcdataGLLNodes,
279  DataArray3D< int >* srcdataGLLNodesSrc,
280  DiscretizationType destType,
281  int destOrder,
282  bool isTgtContinuous,
283  DataArray3D< int >* tgtdataGLLNodes );
284 
285  /// <summary>
286  /// @brief ApplyBoundsLimiting - Apply bounds limiting to the data field
287  /// @param dataInDouble - input data field
288  /// @param dataOutDouble - output data field
289  /// @param caasType - type of limiter
290  /// @param caasIteration - iteration number of limiter
291  /// @return - pair of mass defect pre and post limiter application
292  /// </summary>
293  std::pair< double, double > ApplyBoundsLimiting( std::vector< double >& dataInDouble,
294  std::vector< double >& dataOutDouble,
295  CAASType caasType = CAAS_GLOBAL,
296  int caasIteration = 0,
297  double mismatch = 0.0 );
298 
299  /// @brief
300  /// @param vecAdjFaces
301  /// @param nrings
302  /// @param entities
303  /// @param useMOABAdjacencies
304  /// @param trMesh
305  /// @return
306  void ComputeAdjacencyRelations( std::vector< std::unordered_set< int > >& vecAdjFaces,
307  int nrings,
308  const Range& entities,
309  bool useMOABAdjacencies = true,
310  Mesh* trMesh = nullptr );
311 
312 #ifdef MOAB_HAVE_EIGEN3
313 
314  typedef Eigen::Matrix< double, 1, Eigen::Dynamic > WeightDRowVector;
315  typedef Eigen::Matrix< double, Eigen::Dynamic, 1 > WeightDColVector;
316  typedef Eigen::SparseVector< double > WeightSVector;
317  typedef Eigen::SparseMatrix< double, Eigen::RowMajor > WeightRMatrix;
318  typedef Eigen::SparseMatrix< double, Eigen::ColMajor > WeightCMatrix;
319 
320  typedef WeightDRowVector WeightRowVector;
321  typedef WeightDColVector WeightColVector;
322  typedef WeightRMatrix WeightMatrix;
323 
324  /// <summary>
325  /// Get the raw reference to the Eigen weight matrix representing the projection from source to
326  /// destination mesh.
327  /// </summary>
328  WeightMatrix& GetWeightMatrix();
329 
330  /// <summary>
331  /// Get the row vector that is amenable for application of A*x operation.
332  /// </summary>
333  WeightRowVector& GetRowVector();
334 
335  /// <summary>
336  /// Get the column vector that is amenable for application of A^T*x operation.
337  /// </summary>
338  WeightColVector& GetColVector();
339 
340 #endif
341 
342  /// <summary>
343  /// Get the number of total Degrees-Of-Freedom defined on the source mesh.
344  /// </summary>
346 
347  /// <summary>
348  /// Get the number of total Degrees-Of-Freedom defined on the destination mesh.
349  /// </summary>
351 
352  /// <summary>
353  /// Get the number of local Degrees-Of-Freedom defined on the source mesh.
354  /// </summary>
356 
357  /// <summary>
358  /// Get the number of local Degrees-Of-Freedom defined on the destination mesh.
359  /// </summary>
361 
362  /// <summary>
363  /// Get the number of Degrees-Of-Freedom per element on the source mesh.
364  /// </summary>
366 
367  /// <summary>
368  /// Get the number of Degrees-Of-Freedom per element on the destination mesh.
369  /// </summary>
371 
372  /// <summary>
373  /// Set the number of Degrees-Of-Freedom per element on the source mesh.
374  /// </summary>
375  void SetSourceNDofsPerElement( int ns );
376 
377  /// <summary>
378  /// Get the number of Degrees-Of-Freedom per element on the destination mesh.
379  /// </summary>
380  void SetDestinationNDofsPerElement( int nt );
381 
382  /// <summary>
383  /// Get the global Degrees-Of-Freedom ID on the destination mesh.
384  /// </summary>
385  int GetRowGlobalDoF( int localID ) const;
386 
387  /// <summary>
388  /// Get the index of globaRowDoF.
389  /// </summary>
390  inline int GetIndexOfRowGlobalDoF( int globalRowDoF ) const;
391 
392  /// <summary>
393  /// Get the global Degrees-Of-Freedom ID on the source mesh.
394  /// </summary>
395  int GetColGlobalDoF( int localID ) const;
396 
397  /// <summary>
398  /// Get the index of globaColDoF.
399  /// </summary>
400  inline int GetIndexOfColGlobalDoF( int globalColDoF ) const;
401 
402  /// <summary>
403  /// Apply the weight matrix onto the source vector (tag) provided as input, and return the
404  /// column vector (solution projection) in a tag, after the map application
405  /// Compute: \p tgtVals = A(S->T) * \srcVals, or
406  /// if (transpose) \p tgtVals = [A(T->S)]^T * \srcVals
407  /// </summary>
408  moab::ErrorCode ApplyWeights( moab::Tag srcSolutionTag,
409  moab::Tag tgtSolutionTag,
410  bool transpose = false,
411  CAASType caasType = CAAS_NONE,
412  double default_projection = 0.0 );
413 
414  typedef double ( *sample_function )( double, double );
415 
416  /// <summary>
417  /// Define an analytical solution over the given (source or target) mesh, as specificed in
418  /// the context. This routine will define a tag that is compatible with the specified
419  /// discretization method type and order and sample the solution exactly using the
420  /// analytical function provided by the user.
421  /// </summary>
423  const std::string& solnName,
425  sample_function testFunction,
426  moab::Tag* clonedSolnTag = NULL,
427  std::string cloneSolnName = "" );
428 
429  /// <summary>
430  /// Compute the error between a sampled (exact) solution and a projected solution in various
431  /// error norms.
432  /// </summary>
434  moab::Tag& exactTag,
435  moab::Tag& approxTag,
436  std::map< std::string, double >& metrics,
437  bool verbose = true );
438 
439  moab::ErrorCode fill_row_ids( std::vector< int >& ids_of_interest )
440  {
441  ids_of_interest.reserve( row_gdofmap.size() );
442  // need to add 1
443  for( auto it = row_gdofmap.begin(); it != row_gdofmap.end(); it++ )
444  ids_of_interest.push_back( *it + 1 );
445 
446  return moab::MB_SUCCESS;
447  }
448 
449  moab::ErrorCode fill_col_ids( std::vector< int >& ids_of_interest )
450  {
451  ids_of_interest.reserve( col_gdofmap.size() );
452  // need to add 1
453  for( auto it = col_gdofmap.begin(); it != col_gdofmap.end(); it++ )
454  ids_of_interest.push_back( *it + 1 );
455  return moab::MB_SUCCESS;
456  }
457 
458  moab::ErrorCode set_col_dc_dofs( std::vector< int >& values_entities );
459 
460  moab::ErrorCode set_row_dc_dofs( std::vector< int >& values_entities );
461 
462  // hack
463  void SetMeshInput( Mesh* imesh )
464  {
465  m_meshInput = imesh;
466  };
467 
468  private:
469  template < typename SparseMatrixType >
470  void serializeSparseMatrix( const SparseMatrixType& mat, const std::string& filename );
471 
472  void setup_sizes_dimensions();
473 
474  void CAASLimiter( std::vector< double >& dataCorrectedField,
475  std::vector< double >& dataLowerBound,
476  std::vector< double >& dataUpperBound,
477  double& dMass );
478  double QLTLimiter( int caasIteration,
479  std::vector< double >& dataCorrectedField,
480  std::vector< double >& dataLowerBound,
481  std::vector< double >& dataUpperBound,
482  std::vector< double >& dMassDefect );
483 
484  /// <summary>
485  /// Apply the weight matrix onto the source vector provided as input, and return the column
486  /// vector (solution projection) after the map application
487  /// Compute: \p tgtVals = A(S->T) * \srcVals, or
488  /// if (transpose) \p tgtVals = [A(T->S)]^T * \srcVals
489  /// </summary>
490  moab::ErrorCode ApplyWeights( std::vector< double >& srcVals,
491  std::vector< double >& tgtVals,
492  bool transpose = false );
493 
494 #ifdef MOAB_HAVE_MPI
495  int rearrange_arrays_by_dofs( const std::vector< unsigned int >& gdofmap,
496  DataArray1D< double >& vecFaceArea,
497  DataArray1D< double >& dCenterLon,
498  DataArray1D< double >& dCenterLat,
499  DataArray2D< double >& dVertexLat,
500  DataArray2D< double >& dVertexLon,
501  std::vector< int >& masks,
502  unsigned& N, // this will be output too now
503  int nv,
504  int& maxdof );
505 #endif
506 
507  /// <summary>
508  /// The fundamental remapping operator object.
509  /// </summary>
511 
512 #ifdef MOAB_HAVE_EIGEN3
513 
514  WeightMatrix m_weightMatrix;
515  WeightRowVector m_rowVector;
516  WeightColVector m_colVector;
517 
518 #endif
519 
520  /// <summary>
521  /// The reference to the moab::Core object that contains source/target and overlap sets.
522  /// </summary>
524 
525 #ifdef MOAB_HAVE_MPI
526  /// <summary>
527  /// The reference to the parallel communicator object used by the Core object.
528  /// </summary>
529  moab::ParallelComm* m_pcomm;
530 #endif
531 
532  /// <summary>
533  /// The original tag data and local to global DoF mapping to associate matrix values to
534  /// solution <summary>
536  std::vector< unsigned > row_gdofmap, col_gdofmap, srccol_gdofmap;
537 
538  // make it int, because it can be -1 in new logic
540 
541  std::map< int, int > rowMap, colMap;
543 
547 
548  // Key details about the current map
553 
554  Mesh* m_meshInput;
558 
560  int rank, size;
561 };
562 
563 ///////////////////////////////////////////////////////////////////////////////
564 
565 inline int moab::TempestOnlineMap::GetRowGlobalDoF( int localRowID ) const
566 {
567  return row_gdofmap[localRowID];
568 }
569 
570 inline int moab::TempestOnlineMap::GetIndexOfRowGlobalDoF( int globalRowDoF ) const /* 0 based */
571 {
572  return globalRowDoF + 1;
573 }
574 ///////////////////////////////////////////////////////////////////////////////
575 
576 inline int moab::TempestOnlineMap::GetColGlobalDoF( int localColID ) const
577 {
578  return col_gdofmap[localColID];
579 }
580 
581 inline int moab::TempestOnlineMap::GetIndexOfColGlobalDoF( int globalColDoF ) const /* 0 based */
582 {
583  return globalColDoF + 1; // temporary
584 }
585 ///////////////////////////////////////////////////////////////////////////////
586 
588 {
589  return m_nDofsPEl_Src;
590 }
591 
592 ///////////////////////////////////////////////////////////////////////////////
593 
595 {
596  return m_nDofsPEl_Dest;
597 }
598 
599 // setters for m_nDofsPEl_Src, m_nDofsPEl_Dest
601 {
602  m_nDofsPEl_Src = ns;
603 }
604 
606 {
607  m_nDofsPEl_Dest = nt;
608 }
609 
610 ///////////////////////////////////////////////////////////////////////////////
611 #ifdef MOAB_HAVE_EIGEN3
612 
614 {
615  return m_weightMatrix.cols(); // return the global number of rows from the weight matrix
616 }
617 
618 // ///////////////////////////////////////////////////////////////////////////////
619 
621 {
622  return m_weightMatrix.rows(); // return the global number of columns from the weight matrix
623 }
624 
625 ///////////////////////////////////////////////////////////////////////////////
626 
628 {
629  return m_weightMatrix.cols(); // return the local number of rows from the weight matrix
630 }
631 
632 ///////////////////////////////////////////////////////////////////////////////
633 
635 {
636  return m_weightMatrix.rows(); // return the local number of columns from the weight matrix
637 }
638 
639 ///////////////////////////////////////////////////////////////////////////////
640 
641 inline moab::TempestOnlineMap::WeightMatrix& moab::TempestOnlineMap::GetWeightMatrix()
642 {
643  assert( m_weightMatrix.rows() != 0 && m_weightMatrix.cols() != 0 );
644  return m_weightMatrix;
645 }
646 
647 ///////////////////////////////////////////////////////////////////////////////
648 
649 inline moab::TempestOnlineMap::WeightRowVector& moab::TempestOnlineMap::GetRowVector()
650 {
651  assert( m_rowVector.size() != 0 );
652  return m_rowVector;
653 }
654 
655 ///////////////////////////////////////////////////////////////////////////////
656 
657 inline moab::TempestOnlineMap::WeightColVector& moab::TempestOnlineMap::GetColVector()
658 {
659  assert( m_colVector.size() != 0 );
660  return m_colVector;
661 }
662 
663 ///////////////////////////////////////////////////////////////////////////////
664 
665 #endif
666 
667 } // namespace moab
668 
669 #endif