![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 ///////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// \file TempestOnlineMap.h
00004 /// \author Vijay Mahadevan
00005 /// \version November 20, 2017
00006 ///
00007
00008 #ifndef _TEMPESTONLINEMAP_H_
00009 #define _TEMPESTONLINEMAP_H_
00010
00011 #include "moab/MOABConfig.h"
00012
00013 // Tempest includes
00014 #ifdef MOAB_HAVE_TEMPESTREMAP
00015 #include "moab/Remapping/TempestRemapper.hpp"
00016 #include "OfflineMap.h"
00017 #else
00018 #error Re-configure with TempestRemap
00019 #endif
00020
00021 #include
00022 #include
00023
00024 #ifdef MOAB_HAVE_EIGEN3
00025 #include
00026 #endif
00027
00028 ///////////////////////////////////////////////////////////////////////////////
00029
00030 #if !defined( RECTANGULAR_TRUNCATION ) && !defined( TRIANGULAR_TRUNCATION )
00031 #define RECTANGULAR_TRUNCATION
00032 // #define TRIANGULAR_TRUNCATION
00033 #endif
00034
00035 ///////////////////////////////////////////////////////////////////////////////
00036
00037 // Forward declarations
00038 class Mesh;
00039
00040 ///////////////////////////////////////////////////////////////////////////////
00041
00042 namespace moab
00043 {
00044
00045 ///
00046 /// An offline map between two Meshes.
00047 ///
00048 class TempestOnlineMap : public OfflineMap
00049 {
00050
00051 public:
00052 ///
00053 /// Generate the metadata associated with the offline map.
00054 ///
00055 TempestOnlineMap( moab::TempestRemapper* remapper );
00056
00057 ///
00058 /// Define a virtual destructor.
00059 ///
00060 virtual ~TempestOnlineMap();
00061
00062 public:
00063 // Input / Output types
00064 enum DiscretizationType
00065 {
00066 DiscretizationType_FV,
00067 DiscretizationType_CGLL,
00068 DiscretizationType_DGLL,
00069 DiscretizationType_PCLOUD
00070 };
00071
00072 ///
00073 /// Generate the offline map, given the source and target mesh and discretization details.
00074 /// This method generates the mapping between the two meshes based on the overlap and stores
00075 /// the result in the SparseMatrix.
00076 ///
00077 moab::ErrorCode GenerateRemappingWeights( std::string strInputType,
00078 std::string strOutputType,
00079 const GenerateOfflineMapAlgorithmOptions& mapOptions,
00080 const std::string& srcDofTagName = "GLOBAL_ID",
00081 const std::string& tgtDofTagName = "GLOBAL_ID" );
00082
00083 ///
00084 /// Generate the metadata associated with the offline map.
00085 ///
00086 // moab::ErrorCode GenerateMetaData();
00087
00088 ///
00089 /// Read the OfflineMap from a NetCDF file.
00090 ///
00091 moab::ErrorCode ReadParallelMap( const char* strSource,
00092 const std::vector< int >& owned_dof_ids,
00093 bool row_major_ownership = true );
00094
00095 ///
00096 /// Write the TempestOnlineMap to a parallel NetCDF file.
00097 ///
00098 moab::ErrorCode WriteParallelMap( const std::string& strTarget );
00099
00100 ///
00101 /// Determine if the map is first-order accurate.
00102 ///
00103 virtual int IsConsistent( double dTolerance );
00104
00105 ///
00106 /// Determine if the map is conservative.
00107 ///
00108 virtual int IsConservative( double dTolerance );
00109
00110 ///
00111 /// Determine if the map is monotone.
00112 ///
00113 virtual int IsMonotone( double dTolerance );
00114
00115 ///
00116 /// If we computed the reduction, get the vector representing the source areas for all entities
00117 /// in the mesh
00118 ///
00119 const DataArray1D< double >& GetGlobalSourceAreas() const;
00120
00121 ///
00122 /// If we computed the reduction, get the vector representing the target areas for all entities
00123 /// in the mesh
00124 ///
00125 const DataArray1D< double >& GetGlobalTargetAreas() const;
00126
00127 private:
00128 ///
00129 /// Compute the remapping weights as a permutation matrix that relates DoFs on the source
00130 /// mesh
00131 /// to DoFs on the target mesh.
00132 ///
00133 moab::ErrorCode LinearRemapNN_MOAB( bool use_GID_matching = false, bool strict_check = false );
00134
00135 ///
00136 /// Compute the remapping weights for a FV field defined on the source to a
00137 /// FV field defined on the target mesh.
00138 ///
00139 void LinearRemapFVtoFV_Tempest_MOAB( int nOrder );
00140
00141 ///
00142 /// Generate the OfflineMap for linear conserative element-average
00143 /// spectral element to element average remapping.
00144 ///
00145 void LinearRemapSE0_Tempest_MOAB( const DataArray3D< int >& dataGLLNodes,
00146 const DataArray3D< double >& dataGLLJacobian );
00147
00148 ///
00149 /// Generate the OfflineMap for cubic conserative element-average
00150 /// spectral element to element average remapping.
00151 ///
00152 void LinearRemapSE4_Tempest_MOAB( const DataArray3D< int >& dataGLLNodes,
00153 const DataArray3D< double >& dataGLLJacobian,
00154 int nMonotoneType,
00155 bool fContinuousIn,
00156 bool fNoConservation );
00157
00158 ///
00159 /// Generate the OfflineMap for remapping from finite volumes to finite
00160 /// elements.
00161 ///
00162 void LinearRemapFVtoGLL_MOAB( const DataArray3D< int >& dataGLLNodes,
00163 const DataArray3D< double >& dataGLLJacobian,
00164 const DataArray1D< double >& dataGLLNodalArea,
00165 int nOrder,
00166 int nMonotoneType,
00167 bool fContinuous,
00168 bool fNoConservation );
00169
00170 ///
00171 /// Generate the OfflineMap for remapping from finite elements to finite
00172 /// elements.
00173 ///
00174 void LinearRemapGLLtoGLL2_MOAB( const DataArray3D< int >& dataGLLNodesIn,
00175 const DataArray3D< double >& dataGLLJacobianIn,
00176 const DataArray3D< int >& dataGLLNodesOut,
00177 const DataArray3D< double >& dataGLLJacobianOut,
00178 const DataArray1D< double >& dataNodalAreaOut,
00179 int nPin,
00180 int nPout,
00181 int nMonotoneType,
00182 bool fContinuousIn,
00183 bool fContinuousOut,
00184 bool fNoConservation );
00185
00186 ///
00187 /// Generate the OfflineMap for remapping from finite elements to finite
00188 /// elements (pointwise interpolation).
00189 ///
00190 void LinearRemapGLLtoGLL2_Pointwise_MOAB( const DataArray3D< int >& dataGLLNodesIn,
00191 const DataArray3D< double >& dataGLLJacobianIn,
00192 const DataArray3D< int >& dataGLLNodesOut,
00193 const DataArray3D< double >& dataGLLJacobianOut,
00194 const DataArray1D< double >& dataNodalAreaOut,
00195 int nPin,
00196 int nPout,
00197 int nMonotoneType,
00198 bool fContinuousIn,
00199 bool fContinuousOut );
00200
00201 ///
00202 /// Copy the local matrix from Tempest SparseMatrix representation (ELL)
00203 /// to the parallel CSR Eigen Matrix for scalable application of matvec
00204 /// needed for projections.
00205 ///
00206 #ifdef MOAB_HAVE_EIGEN3
00207 void copy_tempest_sparsemat_to_eigen3();
00208 #endif
00209
00210 ///
00211 /// Parallel I/O with HDF5 to write out the remapping weights from multiple processors.
00212 ///
00213 moab::ErrorCode WriteSCRIPMapFile( const std::string& strOutputFile );
00214
00215 ///
00216 /// Parallel I/O with NetCDF to write out the SCRIP file from multiple processors.
00217 ///
00218 moab::ErrorCode WriteHDF5MapFile( const std::string& filename );
00219
00220 public:
00221 ///
00222 /// Store the tag names associated with global DoF ids for source and target meshes
00223 ///
00224 moab::ErrorCode SetDOFmapTags( const std::string srcDofTagName, const std::string tgtDofTagName );
00225
00226 ///
00227 /// Compute the association between the solution tag global DoF numbering and
00228 /// the local matrix numbering so that matvec operations can be performed
00229 /// consistently.
00230 ///
00231 moab::ErrorCode SetDOFmapAssociation( DiscretizationType srcType,
00232 bool isSrcContinuous,
00233 DataArray3D< int >* srcdataGLLNodes,
00234 DataArray3D< int >* srcdataGLLNodesSrc,
00235 DiscretizationType destType,
00236 bool isDestContinuous,
00237 DataArray3D< int >* tgtdataGLLNodes );
00238
00239 #ifdef MOAB_HAVE_EIGEN3
00240
00241 typedef Eigen::Matrix< double, 1, Eigen::Dynamic > WeightDRowVector;
00242 typedef Eigen::Matrix< double, Eigen::Dynamic, 1 > WeightDColVector;
00243 typedef Eigen::SparseVector< double > WeightSVector;
00244 typedef Eigen::SparseMatrix< double, Eigen::RowMajor > WeightRMatrix;
00245 typedef Eigen::SparseMatrix< double, Eigen::ColMajor > WeightCMatrix;
00246
00247 typedef WeightDRowVector WeightRowVector;
00248 typedef WeightDColVector WeightColVector;
00249 typedef WeightRMatrix WeightMatrix;
00250
00251 ///
00252 /// Get the raw reference to the Eigen weight matrix representing the projection from source to
00253 /// destination mesh.
00254 ///
00255 WeightMatrix& GetWeightMatrix();
00256
00257 ///
00258 /// Get the row vector that is amenable for application of A*x operation.
00259 ///
00260 WeightRowVector& GetRowVector();
00261
00262 ///
00263 /// Get the column vector that is amenable for application of A^T*x operation.
00264 ///
00265 WeightColVector& GetColVector();
00266
00267 #endif
00268
00269 ///
00270 /// Get the number of total Degrees-Of-Freedom defined on the source mesh.
00271 ///
00272 int GetSourceGlobalNDofs();
00273
00274 ///
00275 /// Get the number of total Degrees-Of-Freedom defined on the destination mesh.
00276 ///
00277 int GetDestinationGlobalNDofs();
00278
00279 ///
00280 /// Get the number of local Degrees-Of-Freedom defined on the source mesh.
00281 ///
00282 int GetSourceLocalNDofs();
00283
00284 ///
00285 /// Get the number of local Degrees-Of-Freedom defined on the destination mesh.
00286 ///
00287 int GetDestinationLocalNDofs();
00288
00289 ///
00290 /// Get the number of Degrees-Of-Freedom per element on the source mesh.
00291 ///
00292 int GetSourceNDofsPerElement();
00293
00294 ///
00295 /// Get the number of Degrees-Of-Freedom per element on the destination mesh.
00296 ///
00297 int GetDestinationNDofsPerElement();
00298
00299 ///
00300 /// Set the number of Degrees-Of-Freedom per element on the source mesh.
00301 ///
00302 void SetSourceNDofsPerElement( int ns );
00303
00304 ///
00305 /// Get the number of Degrees-Of-Freedom per element on the destination mesh.
00306 ///
00307 void SetDestinationNDofsPerElement( int nt );
00308
00309 ///
00310 /// Get the global Degrees-Of-Freedom ID on the destination mesh.
00311 ///
00312 int GetRowGlobalDoF( int localID ) const;
00313
00314 ///
00315 /// Get the index of globaRowDoF.
00316 ///
00317 inline int GetIndexOfRowGlobalDoF( int globalRowDoF ) const;
00318
00319 ///
00320 /// Get the global Degrees-Of-Freedom ID on the source mesh.
00321 ///
00322 int GetColGlobalDoF( int localID ) const;
00323
00324 ///
00325 /// Get the index of globaColDoF.
00326 ///
00327 inline int GetIndexOfColGlobalDoF( int globalColDoF ) const;
00328
00329 ///
00330 /// Apply the weight matrix onto the source vector provided as input, and return the column
00331 /// vector (solution projection) after the map application
00332 /// Compute: \p tgtVals = A(S->T) * \srcVals, or
00333 /// if (transpose) \p tgtVals = [A(T->S)]^T * \srcVals
00334 ///
00335 moab::ErrorCode ApplyWeights( std::vector< double >& srcVals,
00336 std::vector< double >& tgtVals,
00337 bool transpose = false );
00338
00339 ///
00340 /// Apply the weight matrix onto the source vector (tag) provided as input, and return the
00341 /// column vector (solution projection) in a tag, after the map application
00342 /// Compute: \p tgtVals = A(S->T) * \srcVals, or
00343 /// if (transpose) \p tgtVals = [A(T->S)]^T * \srcVals
00344 ///
00345 moab::ErrorCode ApplyWeights( moab::Tag srcSolutionTag, moab::Tag tgtSolutionTag, bool transpose = false );
00346
00347 typedef double ( *sample_function )( double, double );
00348
00349 ///
00350 /// Define an analytical solution over the given (source or target) mesh, as specificed in
00351 /// the context. This routine will define a tag that is compatible with the specified
00352 /// discretization method type and order and sample the solution exactly using the
00353 /// analytical function provided by the user.
00354 ///
00355 moab::ErrorCode DefineAnalyticalSolution( moab::Tag& exactSolnTag,
00356 const std::string& solnName,
00357 Remapper::IntersectionContext ctx,
00358 sample_function testFunction,
00359 moab::Tag* clonedSolnTag = NULL,
00360 std::string cloneSolnName = "" );
00361
00362 ///
00363 /// Compute the error between a sampled (exact) solution and a projected solution in various
00364 /// error norms.
00365 ///
00366 moab::ErrorCode ComputeMetrics( Remapper::IntersectionContext ctx,
00367 moab::Tag& exactTag,
00368 moab::Tag& approxTag,
00369 std::map< std::string, double >& metrics,
00370 bool verbose = true );
00371
00372 moab::ErrorCode fill_row_ids( std::vector< int >& ids_of_interest )
00373 {
00374 ids_of_interest.reserve( row_gdofmap.size() );
00375 // need to add 1
00376 for( auto it = row_gdofmap.begin(); it != row_gdofmap.end(); it++ )
00377 ids_of_interest.push_back( *it + 1 );
00378
00379 return moab::MB_SUCCESS;
00380 }
00381
00382 moab::ErrorCode fill_col_ids( std::vector< int >& ids_of_interest )
00383 {
00384 ids_of_interest.reserve( col_gdofmap.size() );
00385 // need to add 1
00386 for( auto it = col_gdofmap.begin(); it != col_gdofmap.end(); it++ )
00387 ids_of_interest.push_back( *it + 1 );
00388 return moab::MB_SUCCESS;
00389 }
00390
00391 moab::ErrorCode set_col_dc_dofs( std::vector< int >& values_entities );
00392
00393 moab::ErrorCode set_row_dc_dofs( std::vector< int >& values_entities );
00394
00395 private:
00396 void setup_sizes_dimensions();
00397
00398 #ifdef MOAB_HAVE_MPI
00399 // nv becomes in/out too, because it could be 0 on input, in some cases (empty partitions)
00400 int rearrange_arrays_by_dofs( const std::vector< unsigned int >& gdofmap,
00401 DataArray1D< double >& vecFaceArea,
00402 DataArray1D< double >& dCenterLon,
00403 DataArray1D< double >& dCenterLat,
00404 DataArray2D< double >& dVertexLat,
00405 DataArray2D< double >& dVertexLon,
00406 std::vector< int >& masks,
00407 unsigned& N, // this will be output too now
00408 int& nv,
00409 int& maxdof );
00410 #endif
00411
00412 ///
00413 /// The fundamental remapping operator object.
00414 ///
00415 moab::TempestRemapper* m_remapper;
00416
00417 #ifdef MOAB_HAVE_EIGEN3
00418
00419 WeightMatrix m_weightMatrix;
00420 WeightRowVector m_rowVector;
00421 WeightColVector m_colVector;
00422
00423 #endif
00424
00425 ///
00426 /// The reference to the moab::Core object that contains source/target and overlap sets.
00427 ///
00428 moab::Interface* m_interface;
00429
00430 #ifdef MOAB_HAVE_MPI
00431 ///
00432 /// The reference to the parallel communicator object used by the Core object.
00433 ///
00434 moab::ParallelComm* m_pcomm;
00435 #endif
00436
00437 ///
00438 /// The original tag data and local to global DoF mapping to associate matrix values to
00439 /// solution
00440 moab::Tag m_dofTagSrc, m_dofTagDest;
00441 std::vector< unsigned > row_gdofmap, col_gdofmap, srccol_gdofmap;
00442
00443 // make it int, because it can be -1 in new logic
00444 std::vector< int > row_dtoc_dofmap, col_dtoc_dofmap, srccol_dtoc_dofmap;
00445
00446 std::map< int, int > rowMap, colMap;
00447
00448 DataArray3D< int > dataGLLNodesSrc, dataGLLNodesSrcCov, dataGLLNodesDest;
00449 DiscretizationType m_srcDiscType, m_destDiscType;
00450 int m_nTotDofs_Src, m_nTotDofs_SrcCov, m_nTotDofs_Dest;
00451
00452 // Key details about the current map
00453 int m_nDofsPEl_Src, m_nDofsPEl_Dest;
00454 DiscretizationType m_eInputType, m_eOutputType;
00455 bool m_bConserved;
00456 int m_iMonotonicity;
00457
00458 Mesh* m_meshInput;
00459 Mesh* m_meshInputCov;
00460 Mesh* m_meshOutput;
00461 Mesh* m_meshOverlap;
00462
00463 bool is_parallel, is_root;
00464 int rank, size, root_proc;
00465 };
00466
00467 ///////////////////////////////////////////////////////////////////////////////
00468
00469 inline int moab::TempestOnlineMap::GetRowGlobalDoF( int localRowID ) const
00470 {
00471 return row_gdofmap[localRowID];
00472 }
00473
00474 inline int moab::TempestOnlineMap::GetIndexOfRowGlobalDoF( int globalRowDoF ) const /* 0 based */
00475 {
00476 return globalRowDoF + 1;
00477 }
00478 ///////////////////////////////////////////////////////////////////////////////
00479
00480 inline int moab::TempestOnlineMap::GetColGlobalDoF( int localColID ) const
00481 {
00482 return col_gdofmap[localColID];
00483 }
00484
00485 inline int moab::TempestOnlineMap::GetIndexOfColGlobalDoF( int globalColDoF ) const /* 0 based */
00486 {
00487 return globalColDoF + 1; // temporary
00488 }
00489 ///////////////////////////////////////////////////////////////////////////////
00490
00491 inline int moab::TempestOnlineMap::GetSourceNDofsPerElement()
00492 {
00493 return m_nDofsPEl_Src;
00494 }
00495
00496 ///////////////////////////////////////////////////////////////////////////////
00497
00498 inline int moab::TempestOnlineMap::GetDestinationNDofsPerElement()
00499 {
00500 return m_nDofsPEl_Dest;
00501 }
00502
00503 // setters for m_nDofsPEl_Src, m_nDofsPEl_Dest
00504 inline void moab::TempestOnlineMap::SetSourceNDofsPerElement( int ns )
00505 {
00506 m_nDofsPEl_Src = ns;
00507 }
00508
00509 inline void moab::TempestOnlineMap::SetDestinationNDofsPerElement( int nt )
00510 {
00511 m_nDofsPEl_Dest = nt;
00512 }
00513
00514 ///////////////////////////////////////////////////////////////////////////////
00515 #ifdef MOAB_HAVE_EIGEN3
00516
00517 inline int moab::TempestOnlineMap::GetSourceGlobalNDofs()
00518 {
00519 return m_weightMatrix.cols(); // return the global number of rows from the weight matrix
00520 }
00521
00522 // ///////////////////////////////////////////////////////////////////////////////
00523
00524 inline int moab::TempestOnlineMap::GetDestinationGlobalNDofs()
00525 {
00526 return m_weightMatrix.rows(); // return the global number of columns from the weight matrix
00527 }
00528
00529 ///////////////////////////////////////////////////////////////////////////////
00530
00531 inline int moab::TempestOnlineMap::GetSourceLocalNDofs()
00532 {
00533 return m_weightMatrix.cols(); // return the local number of rows from the weight matrix
00534 }
00535
00536 ///////////////////////////////////////////////////////////////////////////////
00537
00538 inline int moab::TempestOnlineMap::GetDestinationLocalNDofs()
00539 {
00540 return m_weightMatrix.rows(); // return the local number of columns from the weight matrix
00541 }
00542
00543 ///////////////////////////////////////////////////////////////////////////////
00544
00545 inline moab::TempestOnlineMap::WeightMatrix& moab::TempestOnlineMap::GetWeightMatrix()
00546 {
00547 assert( m_weightMatrix.rows() != 0 && m_weightMatrix.cols() != 0 );
00548 return m_weightMatrix;
00549 }
00550
00551 ///////////////////////////////////////////////////////////////////////////////
00552
00553 inline moab::TempestOnlineMap::WeightRowVector& moab::TempestOnlineMap::GetRowVector()
00554 {
00555 assert( m_rowVector.size() != 0 );
00556 return m_rowVector;
00557 }
00558
00559 ///////////////////////////////////////////////////////////////////////////////
00560
00561 inline moab::TempestOnlineMap::WeightColVector& moab::TempestOnlineMap::GetColVector()
00562 {
00563 assert( m_colVector.size() != 0 );
00564 return m_colVector;
00565 }
00566
00567 ///////////////////////////////////////////////////////////////////////////////
00568
00569 #endif
00570
00571 } // namespace moab
00572
00573 #endif