Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /* 00002 * ===================================================================================== 00003 * 00004 * Filename: TempestOnlineMap.hpp 00005 * 00006 * Description: Interface to the TempestRemap library to compute the consistent, 00007 * and accurate high-order conservative remapping weights for overlap 00008 * grids on the sphere in climate simulations. 00009 * 00010 * Author: Vijay S. Mahadevan (vijaysm), [email protected] 00011 * 00012 * ===================================================================================== 00013 */ 00014 00015 #include "Announce.h" 00016 #include "DataArray3D.h" 00017 #include "FiniteElementTools.h" 00018 #include "TriangularQuadrature.h" 00019 #include "GaussQuadrature.h" 00020 #include "GaussLobattoQuadrature.h" 00021 #include "SparseMatrix.h" 00022 #include "STLStringHelper.h" 00023 #include "LinearRemapFV.h" 00024 00025 #include "moab/Remapping/TempestOnlineMap.hpp" 00026 #include "DebugOutput.hpp" 00027 #include "moab/TupleList.hpp" 00028 00029 #include <fstream> 00030 #include <cmath> 00031 #include <cstdlib> 00032 00033 #ifdef MOAB_HAVE_NETCDFPAR 00034 #include "netcdfcpp_par.hpp" 00035 #else 00036 #include "netcdfcpp.h" 00037 #endif 00038 00039 /////////////////////////////////////////////////////////////////////////////// 00040 00041 // #define VERBOSE 00042 // #define VVERBOSE 00043 // #define CHECK_INCREASING_DOF 00044 00045 /////////////////////////////////////////////////////////////////////////////// 00046 00047 #define MPI_CHK_ERR( err ) \ 00048 if( err ) \ 00049 { \ 00050 std::cout << "MPI Failure. ErrorCode (" << ( err ) << ") "; \ 00051 std::cout << "\nMPI Aborting... \n"; \ 00052 return moab::MB_FAILURE; \ 00053 } 00054 00055 moab::TempestOnlineMap::TempestOnlineMap( moab::TempestRemapper* remapper ) : OfflineMap(), m_remapper( remapper ) 00056 { 00057 // Get the references for the MOAB core objects 00058 m_interface = m_remapper->get_interface(); 00059 #ifdef MOAB_HAVE_MPI 00060 m_pcomm = m_remapper->get_parallel_communicator(); 00061 #endif 00062 00063 // Update the references to the meshes 00064 m_meshInput = remapper->GetMesh( moab::Remapper::SourceMesh ); 00065 m_meshInputCov = remapper->GetCoveringMesh(); 00066 m_meshOutput = remapper->GetMesh( moab::Remapper::TargetMesh ); 00067 m_meshOverlap = remapper->GetMesh( moab::Remapper::OverlapMesh ); 00068 00069 is_parallel = false; 00070 is_root = true; 00071 rank = 0; 00072 root_proc = rank; 00073 size = 1; 00074 #ifdef MOAB_HAVE_MPI 00075 int flagInit; 00076 MPI_Initialized( &flagInit ); 00077 if( flagInit ) 00078 { 00079 is_parallel = true; 00080 assert( m_pcomm != NULL ); 00081 rank = m_pcomm->rank(); 00082 size = m_pcomm->size(); 00083 is_root = ( rank == 0 ); 00084 } 00085 #endif 00086 00087 // Compute and store the total number of source and target DoFs corresponding 00088 // to number of rows and columns in the mapping. 00089 00090 // Initialize dimension information from file 00091 this->setup_sizes_dimensions(); 00092 00093 // Build a matrix of source and target discretization so that we know how to assign 00094 // the global DoFs in parallel for the mapping weights 00095 // For example, FV->FV: rows X cols = faces_source X faces_target 00096 } 00097 00098 void moab::TempestOnlineMap::setup_sizes_dimensions() 00099 { 00100 if( m_meshInputCov ) 00101 { 00102 std::vector< std::string > dimNames; 00103 std::vector< int > dimSizes; 00104 if( m_remapper->m_source_type == moab::TempestRemapper::RLL && m_remapper->m_source_metadata.size() ) 00105 { 00106 dimNames.push_back( "lat" ); 00107 dimNames.push_back( "lon" ); 00108 dimSizes.resize( 2, 0 ); 00109 dimSizes[0] = m_remapper->m_source_metadata[1]; 00110 dimSizes[1] = m_remapper->m_source_metadata[2]; 00111 } 00112 else 00113 { 00114 dimNames.push_back( "num_elem" ); 00115 dimSizes.push_back( m_meshInputCov->faces.size() ); 00116 } 00117 00118 this->InitializeSourceDimensions( dimNames, dimSizes ); 00119 } 00120 00121 if( m_meshOutput ) 00122 { 00123 std::vector< std::string > dimNames; 00124 std::vector< int > dimSizes; 00125 if( m_remapper->m_target_type == moab::TempestRemapper::RLL && m_remapper->m_target_metadata.size() ) 00126 { 00127 dimNames.push_back( "lat" ); 00128 dimNames.push_back( "lon" ); 00129 dimSizes.resize( 2, 0 ); 00130 dimSizes[0] = m_remapper->m_target_metadata[1]; 00131 dimSizes[1] = m_remapper->m_target_metadata[2]; 00132 } 00133 else 00134 { 00135 dimNames.push_back( "num_elem" ); 00136 dimSizes.push_back( m_meshOutput->faces.size() ); 00137 } 00138 00139 this->InitializeTargetDimensions( dimNames, dimSizes ); 00140 } 00141 } 00142 00143 /////////////////////////////////////////////////////////////////////////////// 00144 00145 moab::TempestOnlineMap::~TempestOnlineMap() 00146 { 00147 m_interface = NULL; 00148 #ifdef MOAB_HAVE_MPI 00149 m_pcomm = NULL; 00150 #endif 00151 m_meshInput = NULL; 00152 m_meshOutput = NULL; 00153 m_meshOverlap = NULL; 00154 } 00155 00156 /////////////////////////////////////////////////////////////////////////////// 00157 00158 moab::ErrorCode moab::TempestOnlineMap::SetDOFmapTags( const std::string srcDofTagName, 00159 const std::string tgtDofTagName ) 00160 { 00161 moab::ErrorCode rval; 00162 00163 int tagSize = 0; 00164 tagSize = ( m_eInputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Src * m_nDofsPEl_Src ); 00165 rval = 00166 m_interface->tag_get_handle( srcDofTagName.c_str(), tagSize, MB_TYPE_INTEGER, this->m_dofTagSrc, MB_TAG_ANY ); 00167 00168 if( rval == moab::MB_TAG_NOT_FOUND && m_eInputType != DiscretizationType_FV ) 00169 { 00170 int ntot_elements = 0, nelements = m_remapper->m_source_entities.size(); 00171 #ifdef MOAB_HAVE_MPI 00172 int ierr = MPI_Allreduce( &nelements, &ntot_elements, 1, MPI_INT, MPI_SUM, m_pcomm->comm() ); 00173 if( ierr != 0 ) MB_CHK_SET_ERR( MB_FAILURE, "MPI_Allreduce failed to get total source elements" ); 00174 #else 00175 ntot_elements = nelements; 00176 #endif 00177 00178 rval = m_remapper->GenerateCSMeshMetadata( ntot_elements, m_remapper->m_covering_source_entities, 00179 &m_remapper->m_source_entities, srcDofTagName, m_nDofsPEl_Src );MB_CHK_ERR( rval ); 00180 00181 rval = m_interface->tag_get_handle( srcDofTagName.c_str(), m_nDofsPEl_Src * m_nDofsPEl_Src, MB_TYPE_INTEGER, 00182 this->m_dofTagSrc, MB_TAG_ANY );MB_CHK_ERR( rval ); 00183 } 00184 else 00185 MB_CHK_ERR( rval ); 00186 00187 tagSize = ( m_eOutputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Dest * m_nDofsPEl_Dest ); 00188 rval = 00189 m_interface->tag_get_handle( tgtDofTagName.c_str(), tagSize, MB_TYPE_INTEGER, this->m_dofTagDest, MB_TAG_ANY ); 00190 if( rval == moab::MB_TAG_NOT_FOUND && m_eOutputType != DiscretizationType_FV ) 00191 { 00192 int ntot_elements = 0, nelements = m_remapper->m_target_entities.size(); 00193 #ifdef MOAB_HAVE_MPI 00194 int ierr = MPI_Allreduce( &nelements, &ntot_elements, 1, MPI_INT, MPI_SUM, m_pcomm->comm() ); 00195 if( ierr != 0 ) MB_CHK_SET_ERR( MB_FAILURE, "MPI_Allreduce failed to get total source elements" ); 00196 #else 00197 ntot_elements = nelements; 00198 #endif 00199 00200 rval = m_remapper->GenerateCSMeshMetadata( ntot_elements, m_remapper->m_target_entities, NULL, tgtDofTagName, 00201 m_nDofsPEl_Dest );MB_CHK_ERR( rval ); 00202 00203 rval = m_interface->tag_get_handle( tgtDofTagName.c_str(), m_nDofsPEl_Dest * m_nDofsPEl_Dest, MB_TYPE_INTEGER, 00204 this->m_dofTagDest, MB_TAG_ANY );MB_CHK_ERR( rval ); 00205 } 00206 else 00207 MB_CHK_ERR( rval ); 00208 00209 return moab::MB_SUCCESS; 00210 } 00211 00212 /////////////////////////////////////////////////////////////////////////////// 00213 00214 moab::ErrorCode moab::TempestOnlineMap::SetDOFmapAssociation( DiscretizationType srcType, 00215 bool isSrcContinuous, 00216 DataArray3D< int >* srcdataGLLNodes, 00217 DataArray3D< int >* srcdataGLLNodesSrc, 00218 DiscretizationType destType, 00219 bool isTgtContinuous, 00220 DataArray3D< int >* tgtdataGLLNodes ) 00221 { 00222 moab::ErrorCode rval; 00223 std::vector< bool > dgll_cgll_row_ldofmap, dgll_cgll_col_ldofmap, dgll_cgll_covcol_ldofmap; 00224 std::vector< int > src_soln_gdofs, locsrc_soln_gdofs, tgt_soln_gdofs; 00225 00226 // We are assuming that these are element based tags that are sized: np * np 00227 m_srcDiscType = srcType; 00228 m_destDiscType = destType; 00229 00230 bool vprint = is_root && false; 00231 00232 #ifdef VVERBOSE 00233 { 00234 src_soln_gdofs.resize( m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, -1 ); 00235 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_entities, &src_soln_gdofs[0] );MB_CHK_ERR( rval ); 00236 locsrc_soln_gdofs.resize( m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src ); 00237 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_entities, &locsrc_soln_gdofs[0] );MB_CHK_ERR( rval ); 00238 tgt_soln_gdofs.resize( m_remapper->m_target_entities.size() * m_nDofsPEl_Dest * m_nDofsPEl_Dest ); 00239 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_entities, &tgt_soln_gdofs[0] );MB_CHK_ERR( rval ); 00240 00241 if( is_root ) 00242 { 00243 { 00244 std::ofstream output_file( "sourcecov-gids-0.txt" ); 00245 output_file << "I, GDOF\n"; 00246 for( unsigned i = 0; i < src_soln_gdofs.size(); ++i ) 00247 output_file << i << ", " << src_soln_gdofs[i] << "\n"; 00248 00249 output_file << "ELEMID, IDOF, LDOF, GDOF, NDOF\n"; 00250 m_nTotDofs_SrcCov = 0; 00251 if( isSrcContinuous ) 00252 dgll_cgll_covcol_ldofmap.resize( 00253 m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, false ); 00254 for( unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ ) 00255 { 00256 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00257 { 00258 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00259 { 00260 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1; 00261 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q; 00262 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] ) 00263 { 00264 m_nTotDofs_SrcCov++; 00265 dgll_cgll_covcol_ldofmap[localDOF] = true; 00266 } 00267 output_file << m_remapper->lid_to_gid_covsrc[j] << ", " << offsetDOF << ", " << localDOF 00268 << ", " << src_soln_gdofs[offsetDOF] << ", " << m_nTotDofs_SrcCov << "\n"; 00269 } 00270 } 00271 } 00272 output_file.flush(); // required here 00273 output_file.close(); 00274 dgll_cgll_covcol_ldofmap.clear(); 00275 } 00276 00277 { 00278 std::ofstream output_file( "source-gids-0.txt" ); 00279 output_file << "I, GDOF\n"; 00280 for( unsigned i = 0; i < locsrc_soln_gdofs.size(); ++i ) 00281 output_file << i << ", " << locsrc_soln_gdofs[i] << "\n"; 00282 00283 output_file << "ELEMID, IDOF, LDOF, GDOF, NDOF\n"; 00284 m_nTotDofs_Src = 0; 00285 if( isSrcContinuous ) 00286 dgll_cgll_col_ldofmap.resize( 00287 m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, false ); 00288 for( unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ ) 00289 { 00290 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00291 { 00292 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00293 { 00294 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1; 00295 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q; 00296 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] ) 00297 { 00298 m_nTotDofs_Src++; 00299 dgll_cgll_col_ldofmap[localDOF] = true; 00300 } 00301 output_file << m_remapper->lid_to_gid_src[j] << ", " << offsetDOF << ", " << localDOF 00302 << ", " << locsrc_soln_gdofs[offsetDOF] << ", " << m_nTotDofs_Src << "\n"; 00303 } 00304 } 00305 } 00306 output_file.flush(); // required here 00307 output_file.close(); 00308 dgll_cgll_col_ldofmap.clear(); 00309 } 00310 00311 { 00312 std::ofstream output_file( "target-gids-0.txt" ); 00313 output_file << "I, GDOF\n"; 00314 for( unsigned i = 0; i < tgt_soln_gdofs.size(); ++i ) 00315 output_file << i << ", " << tgt_soln_gdofs[i] << "\n"; 00316 00317 output_file << "ELEMID, IDOF, GDOF, NDOF\n"; 00318 m_nTotDofs_Dest = 0; 00319 00320 for( unsigned i = 0; i < tgt_soln_gdofs.size(); ++i ) 00321 { 00322 output_file << m_remapper->lid_to_gid_tgt[i] << ", " << i << ", " << tgt_soln_gdofs[i] << ", " 00323 << m_nTotDofs_Dest << "\n"; 00324 m_nTotDofs_Dest++; 00325 } 00326 00327 output_file.flush(); // required here 00328 output_file.close(); 00329 } 00330 } 00331 else 00332 { 00333 { 00334 std::ofstream output_file( "sourcecov-gids-1.txt" ); 00335 output_file << "I, GDOF\n"; 00336 for( unsigned i = 0; i < src_soln_gdofs.size(); ++i ) 00337 output_file << i << ", " << src_soln_gdofs[i] << "\n"; 00338 00339 output_file << "ELEMID, IDOF, LDOF, GDOF, NDOF\n"; 00340 m_nTotDofs_SrcCov = 0; 00341 if( isSrcContinuous ) 00342 dgll_cgll_covcol_ldofmap.resize( 00343 m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, false ); 00344 for( unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ ) 00345 { 00346 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00347 { 00348 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00349 { 00350 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1; 00351 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q; 00352 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] ) 00353 { 00354 m_nTotDofs_SrcCov++; 00355 dgll_cgll_covcol_ldofmap[localDOF] = true; 00356 } 00357 output_file << m_remapper->lid_to_gid_covsrc[j] << ", " << offsetDOF << ", " << localDOF 00358 << ", " << src_soln_gdofs[offsetDOF] << ", " << m_nTotDofs_SrcCov << "\n"; 00359 } 00360 } 00361 } 00362 output_file.flush(); // required here 00363 output_file.close(); 00364 dgll_cgll_covcol_ldofmap.clear(); 00365 } 00366 00367 { 00368 std::ofstream output_file( "source-gids-1.txt" ); 00369 output_file << "I, GDOF\n"; 00370 for( unsigned i = 0; i < locsrc_soln_gdofs.size(); ++i ) 00371 output_file << i << ", " << locsrc_soln_gdofs[i] << "\n"; 00372 00373 output_file << "ELEMID, IDOF, LDOF, GDOF, NDOF\n"; 00374 m_nTotDofs_Src = 0; 00375 if( isSrcContinuous ) 00376 dgll_cgll_col_ldofmap.resize( 00377 m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, false ); 00378 for( unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ ) 00379 { 00380 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00381 { 00382 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00383 { 00384 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1; 00385 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q; 00386 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] ) 00387 { 00388 m_nTotDofs_Src++; 00389 dgll_cgll_col_ldofmap[localDOF] = true; 00390 } 00391 output_file << m_remapper->lid_to_gid_src[j] << ", " << offsetDOF << ", " << localDOF 00392 << ", " << locsrc_soln_gdofs[offsetDOF] << ", " << m_nTotDofs_Src << "\n"; 00393 } 00394 } 00395 } 00396 output_file.flush(); // required here 00397 output_file.close(); 00398 dgll_cgll_col_ldofmap.clear(); 00399 } 00400 00401 { 00402 std::ofstream output_file( "target-gids-1.txt" ); 00403 output_file << "I, GDOF\n"; 00404 for( unsigned i = 0; i < tgt_soln_gdofs.size(); ++i ) 00405 output_file << i << ", " << tgt_soln_gdofs[i] << "\n"; 00406 00407 output_file << "ELEMID, IDOF, GDOF, NDOF\n"; 00408 m_nTotDofs_Dest = 0; 00409 00410 for( unsigned i = 0; i < tgt_soln_gdofs.size(); ++i ) 00411 { 00412 output_file << m_remapper->lid_to_gid_tgt[i] << ", " << i << ", " << tgt_soln_gdofs[i] << ", " 00413 << m_nTotDofs_Dest << "\n"; 00414 m_nTotDofs_Dest++; 00415 } 00416 00417 output_file.flush(); // required here 00418 output_file.close(); 00419 } 00420 } 00421 } 00422 #endif 00423 00424 // Now compute the mapping and store it for the covering mesh 00425 int srcTagSize = ( m_eInputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Src * m_nDofsPEl_Src ); 00426 if( m_remapper->point_cloud_source ) 00427 { 00428 assert( m_nDofsPEl_Src == 1 ); 00429 col_gdofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX ); 00430 col_dtoc_dofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX ); 00431 src_soln_gdofs.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX ); 00432 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_vertices, &src_soln_gdofs[0] );MB_CHK_ERR( rval ); 00433 srcTagSize = 1; 00434 } 00435 else 00436 { 00437 col_gdofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX ); 00438 col_dtoc_dofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX ); 00439 src_soln_gdofs.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX ); 00440 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_entities, &src_soln_gdofs[0] );MB_CHK_ERR( rval ); 00441 } 00442 00443 // std::cout << "TOnlineMap: Process: " << rank << " and covering entities = [" << 00444 // col_dofmap.size() << ", " << src_soln_gdofs.size() << "]\n"; MPI_Barrier(MPI_COMM_WORLD); 00445 00446 #ifdef ALTERNATE_NUMBERING_IMPLEMENTATION 00447 unsigned maxSrcIndx = 0; 00448 00449 // for ( unsigned j = 0; j < m_covering_source_entities.size(); j++ ) 00450 std::vector< int > locdofs( srcTagSize ); 00451 std::map< Node, moab::EntityHandle > mapLocalMBNodes; 00452 double elcoords[3]; 00453 for( unsigned iel = 0; iel < m_remapper->m_covering_source_entities.size(); ++iel ) 00454 { 00455 EntityHandle eh = m_remapper->m_covering_source_entities[iel]; 00456 rval = m_interface->get_coords( &eh, 1, elcoords );MB_CHK_ERR( rval ); 00457 Node elCentroid( elcoords[0], elcoords[1], elcoords[2] ); 00458 mapLocalMBNodes.insert( std::pair< Node, moab::EntityHandle >( elCentroid, eh ) ); 00459 } 00460 00461 const NodeVector& nodes = m_remapper->m_covering_source->nodes; 00462 for( unsigned j = 0; j < m_remapper->m_covering_source->faces.size(); j++ ) 00463 { 00464 const Face& face = m_remapper->m_covering_source->faces[j]; 00465 00466 Node centroid; 00467 centroid.x = centroid.y = centroid.z = 0.0; 00468 for( unsigned l = 0; l < face.edges.size(); ++l ) 00469 { 00470 centroid.x += nodes[face[l]].x; 00471 centroid.y += nodes[face[l]].y; 00472 centroid.z += nodes[face[l]].z; 00473 } 00474 const double factor = 1.0 / face.edges.size(); 00475 centroid.x *= factor; 00476 centroid.y *= factor; 00477 centroid.z *= factor; 00478 00479 EntityHandle current_eh; 00480 if( mapLocalMBNodes.find( centroid ) != mapLocalMBNodes.end() ) 00481 { 00482 current_eh = mapLocalMBNodes[centroid]; 00483 } 00484 00485 rval = m_interface->tag_get_data( m_dofTagSrc, ¤t_eh, 1, &locdofs[0] );MB_CHK_ERR( rval ); 00486 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00487 { 00488 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00489 { 00490 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1; 00491 const int offsetDOF = p * m_nDofsPEl_Src + q; 00492 maxSrcIndx = ( localDOF > maxSrcIndx ? localDOF : maxSrcIndx ); 00493 std::cout << "Col: " << current_eh << ", " << m_remapper->lid_to_gid_covsrc[j] << ", " << offsetDOF 00494 << ", " << localDOF << ", " << locdofs[offsetDOF] - 1 << ", " << maxSrcIndx << "\n"; 00495 } 00496 } 00497 } 00498 #endif 00499 00500 m_nTotDofs_SrcCov = 0; 00501 if( srcdataGLLNodes == NULL ) 00502 { /* we only have a mapping for elements as DoFs */ 00503 for( unsigned i = 0; i < col_gdofmap.size(); ++i ) 00504 { 00505 assert( src_soln_gdofs[i] > 0 ); 00506 col_gdofmap[i] = src_soln_gdofs[i] - 1; 00507 col_dtoc_dofmap[i] = i; 00508 if( vprint ) std::cout << "Col: " << i << ", " << col_gdofmap[i] << "\n"; 00509 m_nTotDofs_SrcCov++; 00510 } 00511 } 00512 else 00513 { 00514 if( isSrcContinuous ) 00515 dgll_cgll_covcol_ldofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, false ); 00516 // Put these remap coefficients into the SparseMatrix map 00517 for( unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ ) 00518 { 00519 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00520 { 00521 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00522 { 00523 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1; 00524 const int offsetDOF = j * srcTagSize + p * m_nDofsPEl_Src + q; 00525 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] ) 00526 { 00527 m_nTotDofs_SrcCov++; 00528 dgll_cgll_covcol_ldofmap[localDOF] = true; 00529 } 00530 if( !isSrcContinuous ) m_nTotDofs_SrcCov++; 00531 assert( src_soln_gdofs[offsetDOF] > 0 ); 00532 col_gdofmap[localDOF] = src_soln_gdofs[offsetDOF] - 1; 00533 col_dtoc_dofmap[offsetDOF] = localDOF; 00534 if( vprint ) 00535 std::cout << "Col: " << m_remapper->lid_to_gid_covsrc[j] << ", " << offsetDOF << ", " 00536 << localDOF << ", " << col_gdofmap[offsetDOF] << ", " << m_nTotDofs_SrcCov << "\n"; 00537 } 00538 } 00539 } 00540 } 00541 00542 if( m_remapper->point_cloud_source ) 00543 { 00544 assert( m_nDofsPEl_Src == 1 ); 00545 srccol_gdofmap.resize( m_remapper->m_source_vertices.size(), UINT_MAX ); 00546 srccol_dtoc_dofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX ); 00547 locsrc_soln_gdofs.resize( m_remapper->m_source_vertices.size(), UINT_MAX ); 00548 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_vertices, &locsrc_soln_gdofs[0] );MB_CHK_ERR( rval ); 00549 } 00550 else 00551 { 00552 srccol_gdofmap.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX ); 00553 srccol_dtoc_dofmap.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX ); 00554 locsrc_soln_gdofs.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX ); 00555 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_entities, &locsrc_soln_gdofs[0] );MB_CHK_ERR( rval ); 00556 } 00557 00558 // Now compute the mapping and store it for the original source mesh 00559 m_nTotDofs_Src = 0; 00560 if( srcdataGLLNodesSrc == NULL ) 00561 { /* we only have a mapping for elements as DoFs */ 00562 for( unsigned i = 0; i < srccol_gdofmap.size(); ++i ) 00563 { 00564 assert( locsrc_soln_gdofs[i] > 0 ); 00565 srccol_gdofmap[i] = locsrc_soln_gdofs[i] - 1; 00566 srccol_dtoc_dofmap[i] = i; 00567 m_nTotDofs_Src++; 00568 } 00569 } 00570 else 00571 { 00572 if( isSrcContinuous ) dgll_cgll_col_ldofmap.resize( m_remapper->m_source_entities.size() * srcTagSize, false ); 00573 // Put these remap coefficients into the SparseMatrix map 00574 for( unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ ) 00575 { 00576 for( int p = 0; p < m_nDofsPEl_Src; p++ ) 00577 { 00578 for( int q = 0; q < m_nDofsPEl_Src; q++ ) 00579 { 00580 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1; 00581 const int offsetDOF = j * srcTagSize + p * m_nDofsPEl_Src + q; 00582 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] ) 00583 { 00584 m_nTotDofs_Src++; 00585 dgll_cgll_col_ldofmap[localDOF] = true; 00586 } 00587 if( !isSrcContinuous ) m_nTotDofs_Src++; 00588 assert( locsrc_soln_gdofs[offsetDOF] > 0 ); 00589 srccol_gdofmap[localDOF] = locsrc_soln_gdofs[offsetDOF] - 1; 00590 srccol_dtoc_dofmap[offsetDOF] = localDOF; 00591 } 00592 } 00593 } 00594 } 00595 00596 int tgtTagSize = ( m_eOutputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Dest * m_nDofsPEl_Dest ); 00597 if( m_remapper->point_cloud_target ) 00598 { 00599 assert( m_nDofsPEl_Dest == 1 ); 00600 row_gdofmap.resize( m_remapper->m_target_vertices.size(), UINT_MAX ); 00601 row_dtoc_dofmap.resize( m_remapper->m_target_vertices.size(), UINT_MAX ); 00602 tgt_soln_gdofs.resize( m_remapper->m_target_vertices.size(), UINT_MAX ); 00603 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_vertices, &tgt_soln_gdofs[0] );MB_CHK_ERR( rval ); 00604 tgtTagSize = 1; 00605 } 00606 else 00607 { 00608 row_gdofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX ); 00609 row_dtoc_dofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX ); 00610 tgt_soln_gdofs.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX ); 00611 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_entities, &tgt_soln_gdofs[0] );MB_CHK_ERR( rval ); 00612 } 00613 00614 // Now compute the mapping and store it for the target mesh 00615 // To access the GID for each row: row_gdofmap [ row_ldofmap [ 0 : local_ndofs ] ] = GDOF 00616 m_nTotDofs_Dest = 0; 00617 if( tgtdataGLLNodes == NULL ) 00618 { /* we only have a mapping for elements as DoFs */ 00619 for( unsigned i = 0; i < row_gdofmap.size(); ++i ) 00620 { 00621 assert( tgt_soln_gdofs[i] > 0 ); 00622 row_gdofmap[i] = tgt_soln_gdofs[i] - 1; 00623 row_dtoc_dofmap[i] = i; 00624 if( vprint ) std::cout << "Row: " << i << ", " << row_gdofmap[i] << "\n"; 00625 m_nTotDofs_Dest++; 00626 } 00627 } 00628 else 00629 { 00630 if( isTgtContinuous ) dgll_cgll_row_ldofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize, false ); 00631 // Put these remap coefficients into the SparseMatrix map 00632 for( unsigned j = 0; j < m_remapper->m_target_entities.size(); j++ ) 00633 { 00634 for( int p = 0; p < m_nDofsPEl_Dest; p++ ) 00635 { 00636 for( int q = 0; q < m_nDofsPEl_Dest; q++ ) 00637 { 00638 const int localDOF = ( *tgtdataGLLNodes )[p][q][j] - 1; 00639 const int offsetDOF = j * tgtTagSize + p * m_nDofsPEl_Dest + q; 00640 if( isTgtContinuous && !dgll_cgll_row_ldofmap[localDOF] ) 00641 { 00642 m_nTotDofs_Dest++; 00643 dgll_cgll_row_ldofmap[localDOF] = true; 00644 } 00645 if( !isTgtContinuous ) m_nTotDofs_Dest++; 00646 assert( tgt_soln_gdofs[offsetDOF] > 0 ); 00647 row_gdofmap[localDOF] = tgt_soln_gdofs[offsetDOF] - 1; 00648 row_dtoc_dofmap[offsetDOF] = localDOF; 00649 if( vprint ) 00650 std::cout << "Row: " << m_remapper->lid_to_gid_tgt[j] << ", " << offsetDOF << ", " << localDOF 00651 << ", " << row_gdofmap[offsetDOF] << ", " << m_nTotDofs_Dest << "\n"; 00652 } 00653 } 00654 } 00655 } 00656 00657 // Let us also allocate the local representation of the sparse matrix 00658 #if defined( MOAB_HAVE_EIGEN3 ) && defined( VERBOSE ) 00659 if( vprint ) 00660 { 00661 std::cout << "[" << rank << "]" 00662 << "DoFs: row = " << m_nTotDofs_Dest << ", " << row_gdofmap.size() << ", col = " << m_nTotDofs_Src 00663 << ", " << m_nTotDofs_SrcCov << ", " << col_gdofmap.size() << "\n"; 00664 // std::cout << "Max col_dofmap: " << maxcol << ", Min col_dofmap" << mincol << "\n"; 00665 } 00666 #endif 00667 00668 // check monotonicity of row_gdofmap and col_gdofmap 00669 #ifdef CHECK_INCREASING_DOF 00670 for( size_t i = 0; i < row_gdofmap.size() - 1; i++ ) 00671 { 00672 if( row_gdofmap[i] > row_gdofmap[i + 1] ) 00673 std::cout << " on rank " << rank << " in row_gdofmap[" << i << "]=" << row_gdofmap[i] << " > row_gdofmap[" 00674 << i + 1 << "]=" << row_gdofmap[i + 1] << " \n"; 00675 } 00676 for( size_t i = 0; i < col_gdofmap.size() - 1; i++ ) 00677 { 00678 if( col_gdofmap[i] > col_gdofmap[i + 1] ) 00679 std::cout << " on rank " << rank << " in col_gdofmap[" << i << "]=" << col_gdofmap[i] << " > col_gdofmap[" 00680 << i + 1 << "]=" << col_gdofmap[i + 1] << " \n"; 00681 } 00682 #endif 00683 00684 return moab::MB_SUCCESS; 00685 } 00686 00687 moab::ErrorCode moab::TempestOnlineMap::set_col_dc_dofs( std::vector< int >& values_entities ) 00688 { 00689 // col_gdofmap has global dofs , that should be in the list of values, such that 00690 // row_dtoc_dofmap[offsetDOF] = localDOF; 00691 // // we need to find col_dtoc_dofmap such that: col_gdofmap[ col_dtoc_dofmap[i] ] == values_entities [i]; 00692 // we know that col_gdofmap[0..(nbcols-1)] = global_col_dofs -> in values_entities 00693 // form first inverse 00694 00695 col_dtoc_dofmap.resize( values_entities.size() ); 00696 for( int j = 0; j < (int)values_entities.size(); j++ ) 00697 { 00698 if( colMap.find( values_entities[j] - 1 ) != colMap.end() ) 00699 col_dtoc_dofmap[j] = colMap[values_entities[j] - 1]; 00700 else 00701 { 00702 col_dtoc_dofmap[j] = -1; // signal that this value should not be used in 00703 // std::cout <<"values_entities[j] - 1: " << values_entities[j] - 1 <<" at index j = " << j << " not 00704 // found in colMap \n"; 00705 } 00706 } 00707 return moab::MB_SUCCESS; 00708 } 00709 00710 moab::ErrorCode moab::TempestOnlineMap::set_row_dc_dofs( std::vector< int >& values_entities ) 00711 { 00712 // row_dtoc_dofmap = values_entities; // needs to point to local 00713 // we need to find row_dtoc_dofmap such that: row_gdofmap[ row_dtoc_dofmap[i] ] == values_entities [i]; 00714 00715 row_dtoc_dofmap.resize( values_entities.size() ); 00716 for( int j = 0; j < (int)values_entities.size(); j++ ) 00717 { 00718 if( rowMap.find( values_entities[j] - 1 ) != rowMap.end() ) 00719 row_dtoc_dofmap[j] = rowMap[values_entities[j] - 1]; // values are 1 based, but rowMap, colMap are not 00720 else 00721 { 00722 row_dtoc_dofmap[j] = -1; // not all values are used 00723 // std::cout <<"values_entities[j] - 1: " << values_entities[j] - 1 <<" at index j = " << j << " not 00724 // found in rowMap \n"; 00725 } 00726 } 00727 return moab::MB_SUCCESS; 00728 } 00729 /////////////////////////////////////////////////////////////////////////////// 00730 00731 moab::ErrorCode moab::TempestOnlineMap::GenerateRemappingWeights( std::string strInputType, 00732 std::string strOutputType, 00733 const GenerateOfflineMapAlgorithmOptions& mapOptions, 00734 const std::string& srcDofTagName, 00735 const std::string& tgtDofTagName ) 00736 { 00737 NcError error( NcError::silent_nonfatal ); 00738 00739 moab::DebugOutput dbgprint( std::cout, rank, 0 ); 00740 dbgprint.set_prefix( "[TempestOnlineMap]: " ); 00741 moab::ErrorCode rval; 00742 00743 const bool m_bPointCloudSource = ( m_remapper->point_cloud_source ); 00744 const bool m_bPointCloudTarget = ( m_remapper->point_cloud_target ); 00745 const bool m_bPointCloud = m_bPointCloudSource || m_bPointCloudTarget; 00746 00747 try 00748 { 00749 // Check command line parameters (data type arguments) 00750 STLStringHelper::ToLower( strInputType ); 00751 STLStringHelper::ToLower( strOutputType ); 00752 00753 DiscretizationType eInputType; 00754 DiscretizationType eOutputType; 00755 00756 if( strInputType == "fv" ) 00757 { 00758 eInputType = DiscretizationType_FV; 00759 } 00760 else if( strInputType == "cgll" ) 00761 { 00762 eInputType = DiscretizationType_CGLL; 00763 } 00764 else if( strInputType == "dgll" ) 00765 { 00766 eInputType = DiscretizationType_DGLL; 00767 } 00768 else if( strInputType == "pcloud" ) 00769 { 00770 eInputType = DiscretizationType_PCLOUD; 00771 } 00772 else 00773 { 00774 _EXCEPTION1( "Invalid \"in_type\" value (%s), expected [fv|cgll|dgll]", strInputType.c_str() ); 00775 } 00776 00777 if( strOutputType == "fv" ) 00778 { 00779 eOutputType = DiscretizationType_FV; 00780 } 00781 else if( strOutputType == "cgll" ) 00782 { 00783 eOutputType = DiscretizationType_CGLL; 00784 } 00785 else if( strOutputType == "dgll" ) 00786 { 00787 eOutputType = DiscretizationType_DGLL; 00788 } 00789 else if( strOutputType == "pcloud" ) 00790 { 00791 eOutputType = DiscretizationType_PCLOUD; 00792 } 00793 else 00794 { 00795 _EXCEPTION1( "Invalid \"out_type\" value (%s), expected [fv|cgll|dgll]", strOutputType.c_str() ); 00796 } 00797 00798 // set all required input params 00799 m_bConserved = !mapOptions.fNoConservation; 00800 m_eInputType = eInputType; 00801 m_eOutputType = eOutputType; 00802 00803 // Method flags 00804 std::string strMapAlgorithm( "" ); 00805 int nMonotoneType = ( mapOptions.fMonotone ) ? ( 1 ) : ( 0 ); 00806 00807 // Make an index of method arguments 00808 std::set< std::string > setMethodStrings; 00809 { 00810 int iLast = 0; 00811 for( size_t i = 0; i <= mapOptions.strMethod.length(); i++ ) 00812 { 00813 if( ( i == mapOptions.strMethod.length() ) || ( mapOptions.strMethod[i] == ';' ) ) 00814 { 00815 std::string strMethodString = mapOptions.strMethod.substr( iLast, i - iLast ); 00816 STLStringHelper::RemoveWhitespaceInPlace( strMethodString ); 00817 if( strMethodString.length() > 0 ) 00818 { 00819 setMethodStrings.insert( strMethodString ); 00820 } 00821 iLast = i + 1; 00822 } 00823 } 00824 } 00825 00826 for( auto it : setMethodStrings ) 00827 { 00828 // Piecewise constant monotonicity 00829 if( it == "mono2" ) 00830 { 00831 if( nMonotoneType != 0 ) 00832 { 00833 _EXCEPTIONT( "Multiple monotonicity specifications found (--mono) or (--method \"mono#\")" ); 00834 } 00835 if( ( m_eInputType == DiscretizationType_FV ) && ( m_eOutputType == DiscretizationType_FV ) ) 00836 { 00837 _EXCEPTIONT( "--method \"mono2\" is only used when remapping to/from CGLL or DGLL grids" ); 00838 } 00839 nMonotoneType = 2; 00840 00841 // Piecewise linear monotonicity 00842 } 00843 else if( it == "mono3" ) 00844 { 00845 if( nMonotoneType != 0 ) 00846 { 00847 _EXCEPTIONT( "Multiple monotonicity specifications found (--mono) or (--method \"mono#\")" ); 00848 } 00849 if( ( m_eInputType == DiscretizationType_FV ) && ( m_eOutputType == DiscretizationType_FV ) ) 00850 { 00851 _EXCEPTIONT( "--method \"mono3\" is only used when remapping to/from CGLL or DGLL grids" ); 00852 } 00853 nMonotoneType = 3; 00854 00855 // Volumetric remapping from FV to GLL 00856 } 00857 else if( it == "volumetric" ) 00858 { 00859 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType == DiscretizationType_FV ) ) 00860 { 00861 _EXCEPTIONT( "--method \"volumetric\" may only be used for FV->CGLL or FV->DGLL remapping" ); 00862 } 00863 strMapAlgorithm = "volumetric"; 00864 00865 // Inverse distance mapping 00866 } 00867 else if( it == "invdist" ) 00868 { 00869 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) ) 00870 { 00871 _EXCEPTIONT( "--method \"invdist\" may only be used for FV->FV remapping" ); 00872 } 00873 strMapAlgorithm = "invdist"; 00874 00875 // Delaunay triangulation mapping 00876 } 00877 else if( it == "delaunay" ) 00878 { 00879 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) ) 00880 { 00881 _EXCEPTIONT( "--method \"delaunay\" may only be used for FV->FV remapping" ); 00882 } 00883 strMapAlgorithm = "delaunay"; 00884 00885 // Bilinear 00886 } 00887 else if( it == "bilin" ) 00888 { 00889 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) ) 00890 { 00891 _EXCEPTIONT( "--method \"bilin\" may only be used for FV->FV remapping" ); 00892 } 00893 strMapAlgorithm = "fvbilin"; 00894 00895 // Integrated bilinear (same as mono3 when source grid is CGLL/DGLL) 00896 } 00897 else if( it == "intbilin" ) 00898 { 00899 if( m_eOutputType != DiscretizationType_FV ) 00900 { 00901 _EXCEPTIONT( "--method \"intbilin\" may only be used when mapping to FV." ); 00902 } 00903 if( m_eInputType == DiscretizationType_FV ) 00904 { 00905 strMapAlgorithm = "fvintbilin"; 00906 } 00907 else 00908 { 00909 strMapAlgorithm = "mono3"; 00910 } 00911 00912 // Integrated bilinear with generalized Barycentric coordinates 00913 } 00914 else if( it == "intbilingb" ) 00915 { 00916 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) ) 00917 { 00918 _EXCEPTIONT( "--method \"intbilingb\" may only be used for FV->FV remapping" ); 00919 } 00920 strMapAlgorithm = "fvintbilingb"; 00921 } 00922 else 00923 { 00924 _EXCEPTION1( "Invalid --method argument \"%s\"", it.c_str() ); 00925 } 00926 } 00927 00928 m_nDofsPEl_Src = 00929 ( m_eInputType == DiscretizationType_FV || m_eInputType == DiscretizationType_PCLOUD ? 1 00930 : mapOptions.nPin ); 00931 m_nDofsPEl_Dest = 00932 ( m_eOutputType == DiscretizationType_FV || m_eOutputType == DiscretizationType_PCLOUD ? 1 00933 : mapOptions.nPout ); 00934 00935 rval = SetDOFmapTags( srcDofTagName, tgtDofTagName );MB_CHK_ERR( rval ); 00936 00937 /// the tag should be created already in the e3sm workflow; if not, create it here 00938 Tag areaTag; 00939 rval = m_interface->tag_get_handle( "aream", 1, MB_TYPE_DOUBLE, areaTag, 00940 MB_TAG_DENSE | MB_TAG_EXCL | MB_TAG_CREAT ); 00941 if ( MB_ALREADY_ALLOCATED == rval ) 00942 { 00943 if( is_root ) dbgprint.printf( 0, "aream tag already defined \n" ); 00944 } 00945 00946 double dTotalAreaInput = 0.0, dTotalAreaOutput = 0.0; 00947 if( !m_bPointCloudSource ) 00948 { 00949 // Calculate Input Mesh Face areas 00950 if( is_root ) dbgprint.printf( 0, "Calculating input mesh Face areas\n" ); 00951 double dTotalAreaInput_loc = m_meshInput->CalculateFaceAreas( mapOptions.fSourceConcave ); 00952 rval = m_interface->tag_set_data( areaTag, m_remapper->m_source_entities, m_meshInput->vecFaceArea );MB_CHK_ERR( rval ); 00953 dTotalAreaInput = dTotalAreaInput_loc; 00954 #ifdef MOAB_HAVE_MPI 00955 if( m_pcomm ) 00956 MPI_Reduce( &dTotalAreaInput_loc, &dTotalAreaInput, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 00957 #endif 00958 if( is_root ) dbgprint.printf( 0, "Input Mesh Geometric Area: %1.15e\n", dTotalAreaInput ); 00959 00960 // Input mesh areas 00961 m_meshInputCov->CalculateFaceAreas( mapOptions.fSourceConcave ); 00962 // we do not need to set the area on coverage mesh, only on source and target meshes 00963 // rval = m_interface->tag_set_data( areaTag, m_remapper->m_covering_source_entities, m_meshInputCov->vecFaceArea );MB_CHK_ERR( rval ); 00964 } 00965 00966 if( !m_bPointCloudTarget ) 00967 { 00968 // Calculate Output Mesh Face areas 00969 if( is_root ) dbgprint.printf( 0, "Calculating output mesh Face areas\n" ); 00970 double dTotalAreaOutput_loc = m_meshOutput->CalculateFaceAreas( mapOptions.fTargetConcave ); 00971 dTotalAreaOutput = dTotalAreaOutput_loc; 00972 #ifdef MOAB_HAVE_MPI 00973 if( m_pcomm ) 00974 MPI_Reduce( &dTotalAreaOutput_loc, &dTotalAreaOutput, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 00975 #endif 00976 if( is_root ) dbgprint.printf( 0, "Output Mesh Geometric Area: %1.15e\n", dTotalAreaOutput ); 00977 rval = m_interface->tag_set_data( areaTag, m_remapper->m_target_entities, m_meshOutput->vecFaceArea );MB_CHK_ERR( rval ); 00978 } 00979 00980 if( !m_bPointCloud ) 00981 { 00982 // Calculate Face areas 00983 if( is_root ) dbgprint.printf( 0, "Calculating overlap mesh Face areas\n" ); 00984 double dTotalAreaOverlap_loc = m_meshOverlap->CalculateFaceAreas( false ); 00985 double dTotalAreaOverlap = dTotalAreaOverlap_loc; 00986 #ifdef MOAB_HAVE_MPI 00987 if( m_pcomm ) 00988 MPI_Reduce( &dTotalAreaOverlap_loc, &dTotalAreaOverlap, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 00989 #endif 00990 if( is_root ) dbgprint.printf( 0, "Overlap Mesh Area: %1.15e\n", dTotalAreaOverlap ); 00991 00992 // Correct areas to match the areas calculated in the overlap mesh 00993 // if (fCorrectAreas) // In MOAB-TempestRemap, we will always keep this to be true 00994 { 00995 if( is_root ) dbgprint.printf( 0, "Correcting source/target areas to overlap mesh areas\n" ); 00996 DataArray1D< double > dSourceArea( m_meshInputCov->faces.size() ); 00997 DataArray1D< double > dTargetArea( m_meshOutput->faces.size() ); 00998 00999 assert( m_meshOverlap->vecSourceFaceIx.size() == m_meshOverlap->faces.size() ); 01000 assert( m_meshOverlap->vecTargetFaceIx.size() == m_meshOverlap->faces.size() ); 01001 assert( m_meshOverlap->vecFaceArea.GetRows() == m_meshOverlap->faces.size() ); 01002 01003 assert( m_meshInputCov->vecFaceArea.GetRows() == m_meshInputCov->faces.size() ); 01004 assert( m_meshOutput->vecFaceArea.GetRows() == m_meshOutput->faces.size() ); 01005 01006 for( size_t i = 0; i < m_meshOverlap->faces.size(); i++ ) 01007 { 01008 if( m_meshOverlap->vecSourceFaceIx[i] < 0 || m_meshOverlap->vecTargetFaceIx[i] < 0 ) 01009 continue; // skip this cell since it is ghosted 01010 01011 // let us recompute the source/target areas based on overlap mesh areas 01012 assert( static_cast< size_t >( m_meshOverlap->vecSourceFaceIx[i] ) < m_meshInputCov->faces.size() ); 01013 dSourceArea[m_meshOverlap->vecSourceFaceIx[i]] += m_meshOverlap->vecFaceArea[i]; 01014 assert( static_cast< size_t >( m_meshOverlap->vecTargetFaceIx[i] ) < m_meshOutput->faces.size() ); 01015 dTargetArea[m_meshOverlap->vecTargetFaceIx[i]] += m_meshOverlap->vecFaceArea[i]; 01016 } 01017 01018 for( size_t i = 0; i < m_meshInputCov->faces.size(); i++ ) 01019 { 01020 if( fabs( dSourceArea[i] - m_meshInputCov->vecFaceArea[i] ) < 1.0e-10 ) 01021 { 01022 m_meshInputCov->vecFaceArea[i] = dSourceArea[i]; 01023 } 01024 } 01025 for( size_t i = 0; i < m_meshOutput->faces.size(); i++ ) 01026 { 01027 if( fabs( dTargetArea[i] - m_meshOutput->vecFaceArea[i] ) < 1.0e-10 ) 01028 { 01029 m_meshOutput->vecFaceArea[i] = dTargetArea[i]; 01030 } 01031 } 01032 } 01033 01034 // Set source mesh areas in map 01035 if( !m_bPointCloudSource && eInputType == DiscretizationType_FV ) 01036 { 01037 this->SetSourceAreas( m_meshInputCov->vecFaceArea ); 01038 if( m_meshInputCov->vecMask.size() ) 01039 { 01040 this->SetSourceMask( m_meshInputCov->vecMask ); 01041 } 01042 } 01043 01044 // Set target mesh areas in map 01045 if( !m_bPointCloudTarget && eOutputType == DiscretizationType_FV ) 01046 { 01047 this->SetTargetAreas( m_meshOutput->vecFaceArea ); 01048 if( m_meshOutput->vecMask.size() ) 01049 { 01050 this->SetTargetMask( m_meshOutput->vecMask ); 01051 } 01052 } 01053 01054 /* 01055 // Recalculate input mesh area from overlap mesh 01056 if (fabs(dTotalAreaOverlap - dTotalAreaInput) > 1.0e-10) { 01057 dbgprint.printf(0, "Overlap mesh only covers a sub-area of the sphere\n"); 01058 dbgprint.printf(0, "Recalculating source mesh areas\n"); 01059 dTotalAreaInput = m_meshInput->CalculateFaceAreasFromOverlap(m_meshOverlap); 01060 dbgprint.printf(0, "New Input Mesh Geometric Area: %1.15e\n", dTotalAreaInput); 01061 } 01062 */ 01063 } 01064 01065 // Finite volume input / Finite volume output 01066 if( ( eInputType == DiscretizationType_FV ) && ( eOutputType == DiscretizationType_FV ) ) 01067 { 01068 // Generate reverse node array and edge map 01069 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray(); 01070 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap( false ); 01071 01072 // Initialize coordinates for map 01073 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov ); 01074 this->InitializeTargetCoordinatesFromMeshFV( *m_meshOutput ); 01075 01076 // Finite volume input / Finite element output 01077 rval = this->SetDOFmapAssociation( eInputType, false, NULL, NULL, eOutputType, false, NULL );MB_CHK_ERR( rval ); 01078 01079 // Construct remap for FV-FV 01080 if( is_root ) dbgprint.printf( 0, "Calculating remap weights\n" ); 01081 01082 // Construct OfflineMap 01083 if( strMapAlgorithm == "invdist" ) 01084 { 01085 if( is_root ) AnnounceStartBlock( "Calculating map (invdist)" ); 01086 LinearRemapFVtoFVInvDist( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *this ); 01087 } 01088 else if( strMapAlgorithm == "delaunay" ) 01089 { 01090 if( is_root ) AnnounceStartBlock( "Calculating map (delaunay)" ); 01091 LinearRemapTriangulation( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *this ); 01092 } 01093 else if( strMapAlgorithm == "fvintbilin" ) 01094 { 01095 if( is_root ) AnnounceStartBlock( "Calculating map (intbilin)" ); 01096 LinearRemapIntegratedBilinear( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *this ); 01097 } 01098 else if( strMapAlgorithm == "fvintbilingb" ) 01099 { 01100 if( is_root ) AnnounceStartBlock( "Calculating map (intbilingb)" ); 01101 LinearRemapIntegratedGeneralizedBarycentric( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *this ); 01102 } 01103 else if( strMapAlgorithm == "fvbilin" ) 01104 { 01105 if( is_root ) AnnounceStartBlock( "Calculating map (bilin)" ); 01106 LinearRemapBilinear( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *this ); 01107 } 01108 else 01109 { 01110 if( is_root ) AnnounceStartBlock( "Calculating map (default)" ); 01111 // LinearRemapFVtoFV( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, 01112 // ( mapOptions.fMonotone ) ? ( 1 ) : ( mapOptions.nPin ), *this ); 01113 LinearRemapFVtoFV_Tempest_MOAB( ( mapOptions.fMonotone ? 1 : mapOptions.nPin ) ); 01114 } 01115 } 01116 else if( eInputType == DiscretizationType_FV ) 01117 { 01118 DataArray3D< double > dataGLLJacobian; 01119 01120 if( is_root ) dbgprint.printf( 0, "Generating output mesh meta data\n" ); 01121 double dNumericalArea_loc = GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble, 01122 dataGLLNodesDest, dataGLLJacobian ); 01123 01124 double dNumericalArea = dNumericalArea_loc; 01125 #ifdef MOAB_HAVE_MPI 01126 if( m_pcomm ) 01127 MPI_Reduce( &dNumericalArea_loc, &dNumericalArea, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 01128 #endif 01129 if( is_root ) dbgprint.printf( 0, "Output Mesh Numerical Area: %1.15e\n", dNumericalArea ); 01130 01131 // Initialize coordinates for map 01132 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov ); 01133 this->InitializeTargetCoordinatesFromMeshFE( *m_meshOutput, mapOptions.nPout, dataGLLNodesDest ); 01134 01135 // Generate the continuous Jacobian 01136 bool fContinuous = ( eOutputType == DiscretizationType_CGLL ); 01137 01138 if( eOutputType == DiscretizationType_CGLL ) 01139 { 01140 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobian, this->GetTargetAreas() ); 01141 } 01142 else 01143 { 01144 GenerateDiscontinuousJacobian( dataGLLJacobian, this->GetTargetAreas() ); 01145 } 01146 01147 // Generate reverse node array and edge map 01148 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray(); 01149 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap( false ); 01150 01151 // Finite volume input / Finite element output 01152 rval = this->SetDOFmapAssociation( eInputType, false, NULL, NULL, eOutputType, 01153 ( eOutputType == DiscretizationType_CGLL ), &dataGLLNodesDest );MB_CHK_ERR( rval ); 01154 01155 // Generate remap weights 01156 if( strMapAlgorithm == "volumetric" ) 01157 { 01158 if( is_root ) dbgprint.printf( 0, "Calculating remapping weights for FV->GLL (volumetric)\n" ); 01159 LinearRemapFVtoGLL_Volumetric( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesDest, 01160 dataGLLJacobian, this->GetTargetAreas(), mapOptions.nPin, *this, 01161 nMonotoneType, fContinuous, mapOptions.fNoConservation ); 01162 } 01163 else 01164 { 01165 if( is_root ) dbgprint.printf( 0, "Calculating remapping weights for FV->GLL\n" ); 01166 LinearRemapFVtoGLL( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesDest, dataGLLJacobian, 01167 this->GetTargetAreas(), mapOptions.nPin, *this, nMonotoneType, fContinuous, 01168 mapOptions.fNoConservation ); 01169 } 01170 } 01171 else if( ( eInputType == DiscretizationType_PCLOUD ) || ( eOutputType == DiscretizationType_PCLOUD ) ) 01172 { 01173 DataArray3D< double > dataGLLJacobian; 01174 if( !m_bPointCloudSource ) 01175 { 01176 // Generate reverse node array and edge map 01177 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray(); 01178 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap( false ); 01179 01180 // Initialize coordinates for map 01181 if( eInputType == DiscretizationType_FV ) 01182 { 01183 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov ); 01184 } 01185 else 01186 { 01187 if( is_root ) dbgprint.printf( 0, "Generating input mesh meta data\n" ); 01188 DataArray3D< double > dataGLLJacobianSrc; 01189 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov, 01190 dataGLLJacobian ); 01191 GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrc, 01192 dataGLLJacobianSrc ); 01193 } 01194 } 01195 // else { /* Source is a point cloud dataset */ } 01196 01197 if( !m_bPointCloudTarget ) 01198 { 01199 // Generate reverse node array and edge map 01200 if( m_meshOutput->revnodearray.size() == 0 ) m_meshOutput->ConstructReverseNodeArray(); 01201 if( m_meshOutput->edgemap.size() == 0 ) m_meshOutput->ConstructEdgeMap( false ); 01202 01203 // Initialize coordinates for map 01204 if( eOutputType == DiscretizationType_FV ) 01205 { 01206 this->InitializeSourceCoordinatesFromMeshFV( *m_meshOutput ); 01207 } 01208 else 01209 { 01210 if( is_root ) dbgprint.printf( 0, "Generating output mesh meta data\n" ); 01211 GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble, dataGLLNodesDest, 01212 dataGLLJacobian ); 01213 } 01214 } 01215 // else { /* Target is a point cloud dataset */ } 01216 01217 // Finite volume input / Finite element output 01218 rval = this->SetDOFmapAssociation( 01219 eInputType, ( eInputType == DiscretizationType_CGLL ), 01220 ( m_bPointCloudSource || eInputType == DiscretizationType_FV ? NULL : &dataGLLNodesSrcCov ), 01221 ( m_bPointCloudSource || eInputType == DiscretizationType_FV ? NULL : &dataGLLNodesSrc ), eOutputType, 01222 ( eOutputType == DiscretizationType_CGLL ), ( m_bPointCloudTarget ? NULL : &dataGLLNodesDest ) );MB_CHK_ERR( rval ); 01223 01224 // Construct remap 01225 if( is_root ) dbgprint.printf( 0, "Calculating remap weights with Nearest-Neighbor method\n" ); 01226 rval = LinearRemapNN_MOAB( true /*use_GID_matching*/, false /*strict_check*/ );MB_CHK_ERR( rval ); 01227 } 01228 else if( ( eInputType != DiscretizationType_FV ) && ( eOutputType == DiscretizationType_FV ) ) 01229 { 01230 DataArray3D< double > dataGLLJacobianSrc, dataGLLJacobian; 01231 01232 if( is_root ) dbgprint.printf( 0, "Generating input mesh meta data\n" ); 01233 // double dNumericalAreaCov_loc = 01234 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov, 01235 dataGLLJacobian ); 01236 01237 double dNumericalArea_loc = GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble, 01238 dataGLLNodesSrc, dataGLLJacobianSrc ); 01239 01240 // if ( is_root ) dbgprint.printf ( 0, "Input Mesh: Coverage Area: %1.15e, Output Area: 01241 // %1.15e\n", dNumericalAreaCov_loc, dTotalAreaOutput_loc ); 01242 // assert(dNumericalAreaCov_loc >= dTotalAreaOutput_loc); 01243 01244 double dNumericalArea = dNumericalArea_loc; 01245 #ifdef MOAB_HAVE_MPI 01246 if( m_pcomm ) 01247 MPI_Reduce( &dNumericalArea_loc, &dNumericalArea, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 01248 #endif 01249 if( is_root ) 01250 { 01251 dbgprint.printf( 0, "Input Mesh Numerical Area: %1.15e\n", dNumericalArea ); 01252 01253 if( fabs( dNumericalArea - dTotalAreaInput ) > 1.0e-12 ) 01254 { 01255 dbgprint.printf( 0, "WARNING: Significant mismatch between input mesh " 01256 "numerical area and geometric area\n" ); 01257 } 01258 } 01259 01260 if( dataGLLNodesSrcCov.GetSubColumns() != m_meshInputCov->faces.size() ) 01261 { 01262 _EXCEPTIONT( "Number of element does not match between metadata and " 01263 "input mesh" ); 01264 } 01265 01266 // Initialize coordinates for map 01267 this->InitializeSourceCoordinatesFromMeshFE( *m_meshInputCov, mapOptions.nPin, dataGLLNodesSrcCov ); 01268 this->InitializeTargetCoordinatesFromMeshFV( *m_meshOutput ); 01269 01270 // Generate the continuous Jacobian for input mesh 01271 bool fContinuousIn = ( eInputType == DiscretizationType_CGLL ); 01272 01273 if( eInputType == DiscretizationType_CGLL ) 01274 { 01275 GenerateUniqueJacobian( dataGLLNodesSrcCov, dataGLLJacobian, this->GetSourceAreas() ); 01276 } 01277 else 01278 { 01279 GenerateDiscontinuousJacobian( dataGLLJacobian, this->GetSourceAreas() ); 01280 } 01281 01282 // Finite element input / Finite volume output 01283 rval = this->SetDOFmapAssociation( eInputType, ( eInputType == DiscretizationType_CGLL ), 01284 &dataGLLNodesSrcCov, &dataGLLNodesSrc, eOutputType, false, NULL );MB_CHK_ERR( rval ); 01285 01286 // Generate remap 01287 if( is_root ) dbgprint.printf( 0, "Calculating remap weights\n" ); 01288 01289 if( strMapAlgorithm == "volumetric" ) 01290 { 01291 _EXCEPTIONT( "Unimplemented: Volumetric currently unavailable for" 01292 "GLL input mesh" ); 01293 } 01294 01295 LinearRemapSE4_Tempest_MOAB( dataGLLNodesSrcCov, dataGLLJacobian, nMonotoneType, fContinuousIn, 01296 mapOptions.fNoConservation ); 01297 } 01298 else if( ( eInputType != DiscretizationType_FV ) && ( eOutputType != DiscretizationType_FV ) ) 01299 { 01300 DataArray3D< double > dataGLLJacobianIn, dataGLLJacobianSrc; 01301 DataArray3D< double > dataGLLJacobianOut; 01302 01303 // Input metadata 01304 if( is_root ) dbgprint.printf( 0, "Generating input mesh meta data\n" ); 01305 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov, 01306 dataGLLJacobianIn ); 01307 01308 double dNumericalAreaSrc_loc = GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble, 01309 dataGLLNodesSrc, dataGLLJacobianSrc ); 01310 double dNumericalAreaIn = dNumericalAreaSrc_loc; 01311 #ifdef MOAB_HAVE_MPI 01312 if( m_pcomm ) 01313 MPI_Reduce( &dNumericalAreaSrc_loc, &dNumericalAreaIn, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 01314 #endif 01315 if( is_root ) 01316 { 01317 dbgprint.printf( 0, "Input Mesh Numerical Area: %1.15e\n", dNumericalAreaIn ); 01318 01319 if( fabs( dNumericalAreaIn - dTotalAreaInput ) > 1.0e-12 ) 01320 { 01321 dbgprint.printf( 0, "WARNING: Significant mismatch between input mesh " 01322 "numerical area and geometric area\n" ); 01323 } 01324 } 01325 01326 // Output metadata 01327 if( is_root ) dbgprint.printf( 0, "Generating output mesh meta data\n" ); 01328 double dNumericalAreaOut_loc = GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble, 01329 dataGLLNodesDest, dataGLLJacobianOut ); 01330 double dNumericalAreaOut = dNumericalAreaOut_loc; 01331 #ifdef MOAB_HAVE_MPI 01332 if( m_pcomm ) 01333 MPI_Reduce( &dNumericalAreaOut_loc, &dNumericalAreaOut, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 01334 #endif 01335 if( is_root ) 01336 { 01337 dbgprint.printf( 0, "Output Mesh Numerical Area: %1.15e\n", dNumericalAreaOut ); 01338 01339 if( fabs( dNumericalAreaOut - dTotalAreaOutput ) > 1.0e-12 ) 01340 { 01341 if( is_root ) 01342 dbgprint.printf( 0, "WARNING: Significant mismatch between output mesh " 01343 "numerical area and geometric area\n" ); 01344 } 01345 } 01346 01347 // Initialize coordinates for map 01348 this->InitializeSourceCoordinatesFromMeshFE( *m_meshInputCov, mapOptions.nPin, dataGLLNodesSrcCov ); 01349 this->InitializeTargetCoordinatesFromMeshFE( *m_meshOutput, mapOptions.nPout, dataGLLNodesDest ); 01350 01351 // Generate the continuous Jacobian for input mesh 01352 bool fContinuousIn = ( eInputType == DiscretizationType_CGLL ); 01353 01354 if( eInputType == DiscretizationType_CGLL ) 01355 { 01356 GenerateUniqueJacobian( dataGLLNodesSrcCov, dataGLLJacobianIn, this->GetSourceAreas() ); 01357 } 01358 else 01359 { 01360 GenerateDiscontinuousJacobian( dataGLLJacobianIn, this->GetSourceAreas() ); 01361 } 01362 01363 // Generate the continuous Jacobian for output mesh 01364 bool fContinuousOut = ( eOutputType == DiscretizationType_CGLL ); 01365 01366 if( eOutputType == DiscretizationType_CGLL ) 01367 { 01368 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobianOut, this->GetTargetAreas() ); 01369 } 01370 else 01371 { 01372 GenerateDiscontinuousJacobian( dataGLLJacobianOut, this->GetTargetAreas() ); 01373 } 01374 01375 // Input Finite Element to Output Finite Element 01376 rval = this->SetDOFmapAssociation( eInputType, ( eInputType == DiscretizationType_CGLL ), 01377 &dataGLLNodesSrcCov, &dataGLLNodesSrc, eOutputType, 01378 ( eOutputType == DiscretizationType_CGLL ), &dataGLLNodesDest );MB_CHK_ERR( rval ); 01379 01380 // Generate remap 01381 if( is_root ) dbgprint.printf( 0, "Calculating remap weights\n" ); 01382 01383 LinearRemapGLLtoGLL2_MOAB( dataGLLNodesSrcCov, dataGLLJacobianIn, dataGLLNodesDest, dataGLLJacobianOut, 01384 this->GetTargetAreas(), mapOptions.nPin, mapOptions.nPout, nMonotoneType, 01385 fContinuousIn, fContinuousOut, mapOptions.fNoConservation ); 01386 } 01387 else 01388 { 01389 _EXCEPTIONT( "Not implemented" ); 01390 } 01391 01392 #ifdef MOAB_HAVE_EIGEN3 01393 copy_tempest_sparsemat_to_eigen3(); 01394 #endif 01395 01396 #ifdef MOAB_HAVE_MPI 01397 { 01398 // Remove ghosted entities from overlap set 01399 moab::Range ghostedEnts; 01400 rval = m_remapper->GetOverlapAugmentedEntities( ghostedEnts );MB_CHK_ERR( rval ); 01401 moab::EntityHandle m_meshOverlapSet = m_remapper->GetMeshSet( moab::Remapper::OverlapMesh ); 01402 rval = m_interface->remove_entities( m_meshOverlapSet, ghostedEnts );MB_CHK_SET_ERR( rval, "Deleting ghosted entities failed" ); 01403 } 01404 #endif 01405 // Verify consistency, conservation and monotonicity, globally 01406 if( !mapOptions.fNoCheck ) 01407 { 01408 if( is_root ) dbgprint.printf( 0, "Verifying map" ); 01409 this->IsConsistent( 1.0e-8 ); 01410 if( !mapOptions.fNoConservation ) this->IsConservative( 1.0e-8 ); 01411 01412 if( nMonotoneType != 0 ) 01413 { 01414 this->IsMonotone( 1.0e-12 ); 01415 } 01416 } 01417 } 01418 catch( Exception& e ) 01419 { 01420 dbgprint.printf( 0, "%s", e.ToString().c_str() ); 01421 return ( moab::MB_FAILURE ); 01422 } 01423 catch( ... ) 01424 { 01425 return ( moab::MB_FAILURE ); 01426 } 01427 return moab::MB_SUCCESS; 01428 } 01429 01430 /////////////////////////////////////////////////////////////////////////////// 01431 01432 int moab::TempestOnlineMap::IsConsistent( double dTolerance ) 01433 { 01434 #ifndef MOAB_HAVE_MPI 01435 01436 return OfflineMap::IsConsistent( dTolerance ); 01437 01438 #else 01439 01440 // Get map entries 01441 DataArray1D< int > dataRows; 01442 DataArray1D< int > dataCols; 01443 DataArray1D< double > dataEntries; 01444 01445 // Calculate row sums 01446 DataArray1D< double > dRowSums; 01447 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries ); 01448 dRowSums.Allocate( m_mapRemap.GetRows() ); 01449 01450 for( unsigned i = 0; i < dataRows.GetRows(); i++ ) 01451 { 01452 dRowSums[dataRows[i]] += dataEntries[i]; 01453 } 01454 01455 // Verify all row sums are equal to 1 01456 int fConsistent = 0; 01457 for( unsigned i = 0; i < dRowSums.GetRows(); i++ ) 01458 { 01459 if( fabs( dRowSums[i] - 1.0 ) > dTolerance ) 01460 { 01461 fConsistent++; 01462 int rowGID = row_gdofmap[i]; 01463 Announce( "TempestOnlineMap is not consistent in row %i (%1.15e)", rowGID, dRowSums[i] ); 01464 } 01465 } 01466 01467 int ierr; 01468 int fConsistentGlobal = 0; 01469 ierr = MPI_Allreduce( &fConsistent, &fConsistentGlobal, 1, MPI_INT, MPI_SUM, m_pcomm->comm() ); 01470 if( ierr != MPI_SUCCESS ) return -1; 01471 01472 return fConsistentGlobal; 01473 #endif 01474 } 01475 01476 /////////////////////////////////////////////////////////////////////////////// 01477 01478 int moab::TempestOnlineMap::IsConservative( double dTolerance ) 01479 { 01480 #ifndef MOAB_HAVE_MPI 01481 01482 return OfflineMap::IsConservative( dTolerance ); 01483 01484 #else 01485 // return OfflineMap::IsConservative(dTolerance); 01486 01487 int ierr; 01488 // Get map entries 01489 DataArray1D< int > dataRows; 01490 DataArray1D< int > dataCols; 01491 DataArray1D< double > dataEntries; 01492 const DataArray1D< double >& dTargetAreas = this->GetTargetAreas(); 01493 const DataArray1D< double >& dSourceAreas = this->GetSourceAreas(); 01494 01495 // Calculate column sums 01496 std::vector< int > dColumnsUnique; 01497 std::vector< double > dColumnSums; 01498 01499 int nColumns = m_mapRemap.GetColumns(); 01500 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries ); 01501 dColumnSums.resize( m_nTotDofs_SrcCov, 0.0 ); 01502 dColumnsUnique.resize( m_nTotDofs_SrcCov, -1 ); 01503 01504 for( unsigned i = 0; i < dataEntries.GetRows(); i++ ) 01505 { 01506 dColumnSums[dataCols[i]] += dataEntries[i] * dTargetAreas[dataRows[i]] / dSourceAreas[dataCols[i]]; 01507 01508 assert( dataCols[i] < m_nTotDofs_SrcCov ); 01509 01510 // GID for column DoFs: col_gdofmap[ col_ldofmap [ dataCols[i] ] ] 01511 int colGID = this->GetColGlobalDoF( dataCols[i] ); // col_gdofmap[ col_ldofmap [ dataCols[i] ] ]; 01512 // int colGID = col_gdofmap[ col_ldofmap [ dataCols[i] ] ]; 01513 dColumnsUnique[dataCols[i]] = colGID; 01514 01515 // std::cout << "Column dataCols[i]=" << dataCols[i] << " with GID = " << colGID << 01516 // std::endl; 01517 } 01518 01519 int rootProc = 0; 01520 std::vector< int > nElementsInProc; 01521 const int nDATA = 3; 01522 if( !rank ) nElementsInProc.resize( size * nDATA ); 01523 int senddata[nDATA] = {nColumns, m_nTotDofs_SrcCov, m_nTotDofs_Src}; 01524 ierr = MPI_Gather( senddata, nDATA, MPI_INT, nElementsInProc.data(), nDATA, MPI_INT, rootProc, m_pcomm->comm() ); 01525 if( ierr != MPI_SUCCESS ) return -1; 01526 01527 int nTotVals = 0, nTotColumns = 0, nTotColumnsUnq = 0; 01528 std::vector< int > dColumnIndices; 01529 std::vector< double > dColumnSourceAreas; 01530 std::vector< double > dColumnSumsTotal; 01531 std::vector< int > displs, rcount; 01532 if( rank == rootProc ) 01533 { 01534 displs.resize( size + 1, 0 ); 01535 rcount.resize( size, 0 ); 01536 int gsum = 0; 01537 for( int ir = 0; ir < size; ++ir ) 01538 { 01539 nTotVals += nElementsInProc[ir * nDATA]; 01540 nTotColumns += nElementsInProc[ir * nDATA + 1]; 01541 nTotColumnsUnq += nElementsInProc[ir * nDATA + 2]; 01542 01543 displs[ir] = gsum; 01544 rcount[ir] = nElementsInProc[ir * nDATA + 1]; 01545 gsum += rcount[ir]; 01546 01547 // printf("%d: nTotColumns: %d, Displs: %d, rcount: %d, gsum = %d\n", ir, nTotColumns, 01548 // displs[ir], rcount[ir], gsum); 01549 } 01550 01551 dColumnIndices.resize( nTotColumns, -1 ); 01552 dColumnSumsTotal.resize( nTotColumns, 0.0 ); 01553 // dColumnSourceAreas.resize ( nTotColumns, 0.0 ); 01554 } 01555 01556 // Gather all ColumnSums to root process and accumulate 01557 // We expect that the sums of all columns equate to 1.0 within user specified tolerance 01558 // Need to do a gatherv here since different processes have different number of elements 01559 // MPI_Reduce(&dColumnSums[0], &dColumnSumsTotal[0], m_mapRemap.GetColumns(), MPI_DOUBLE, 01560 // MPI_SUM, 0, m_pcomm->comm()); 01561 ierr = MPI_Gatherv( &dColumnsUnique[0], m_nTotDofs_SrcCov, MPI_INT, &dColumnIndices[0], rcount.data(), 01562 displs.data(), MPI_INT, rootProc, m_pcomm->comm() ); 01563 if( ierr != MPI_SUCCESS ) return -1; 01564 ierr = MPI_Gatherv( &dColumnSums[0], m_nTotDofs_SrcCov, MPI_DOUBLE, &dColumnSumsTotal[0], rcount.data(), 01565 displs.data(), MPI_DOUBLE, rootProc, m_pcomm->comm() ); 01566 if( ierr != MPI_SUCCESS ) return -1; 01567 // ierr = MPI_Gatherv ( &dSourceAreas[0], m_nTotDofs_SrcCov, MPI_DOUBLE, &dColumnSourceAreas[0], 01568 // rcount.data(), displs.data(), MPI_DOUBLE, rootProc, m_pcomm->comm() ); if ( ierr != 01569 // MPI_SUCCESS ) return -1; 01570 01571 // Clean out unwanted arrays now 01572 dColumnSums.clear(); 01573 dColumnsUnique.clear(); 01574 01575 // Verify all column sums equal the input Jacobian 01576 int fConservative = 0; 01577 if( rank == rootProc ) 01578 { 01579 displs[size] = ( nTotColumns ); 01580 // std::vector<double> dColumnSumsOnRoot(nTotColumnsUnq, 0.0); 01581 std::map< int, double > dColumnSumsOnRoot; 01582 // std::map<int, double> dColumnSourceAreasOnRoot; 01583 for( int ir = 0; ir < size; ir++ ) 01584 { 01585 for( int ips = displs[ir]; ips < displs[ir + 1]; ips++ ) 01586 { 01587 if( dColumnIndices[ips] < 0 ) continue; 01588 // printf("%d, %d: dColumnIndices[ips]: %d\n", ir, ips, dColumnIndices[ips]); 01589 assert( dColumnIndices[ips] < nTotColumnsUnq ); 01590 dColumnSumsOnRoot[dColumnIndices[ips]] += dColumnSumsTotal[ips]; // / dColumnSourceAreas[ips]; 01591 // dColumnSourceAreasOnRoot[ dColumnIndices[ips] ] = dColumnSourceAreas[ips]; 01592 // dColumnSourceAreas[ dColumnIndices[ips] ] 01593 } 01594 } 01595 01596 for( std::map< int, double >::iterator it = dColumnSumsOnRoot.begin(); it != dColumnSumsOnRoot.end(); ++it ) 01597 { 01598 // if ( fabs ( it->second - dColumnSourceAreasOnRoot[it->first] ) > dTolerance ) 01599 if( fabs( it->second - 1.0 ) > dTolerance ) 01600 { 01601 fConservative++; 01602 Announce( "TempestOnlineMap is not conservative in column " 01603 // "%i (%1.15e)", it->first, it->second ); 01604 "%i (%1.15e)", 01605 it->first, it->second /* / dColumnSourceAreasOnRoot[it->first] */ ); 01606 } 01607 } 01608 } 01609 01610 // TODO: Just do a broadcast from root instead of a reduction 01611 ierr = MPI_Bcast( &fConservative, 1, MPI_INT, rootProc, m_pcomm->comm() ); 01612 if( ierr != MPI_SUCCESS ) return -1; 01613 01614 return fConservative; 01615 #endif 01616 } 01617 01618 /////////////////////////////////////////////////////////////////////////////// 01619 01620 int moab::TempestOnlineMap::IsMonotone( double dTolerance ) 01621 { 01622 #ifndef MOAB_HAVE_MPI 01623 01624 return OfflineMap::IsMonotone( dTolerance ); 01625 01626 #else 01627 01628 // Get map entries 01629 DataArray1D< int > dataRows; 01630 DataArray1D< int > dataCols; 01631 DataArray1D< double > dataEntries; 01632 01633 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries ); 01634 01635 // Verify all entries are in the range [0,1] 01636 int fMonotone = 0; 01637 for( unsigned i = 0; i < dataRows.GetRows(); i++ ) 01638 { 01639 if( ( dataEntries[i] < -dTolerance ) || ( dataEntries[i] > 1.0 + dTolerance ) ) 01640 { 01641 fMonotone++; 01642 01643 Announce( "TempestOnlineMap is not monotone in entry (%i): %1.15e", i, dataEntries[i] ); 01644 } 01645 } 01646 01647 int ierr; 01648 int fMonotoneGlobal = 0; 01649 ierr = MPI_Allreduce( &fMonotone, &fMonotoneGlobal, 1, MPI_INT, MPI_SUM, m_pcomm->comm() ); 01650 if( ierr != MPI_SUCCESS ) return -1; 01651 01652 return fMonotoneGlobal; 01653 #endif 01654 } 01655 01656 /////////////////////////////////////////////////////////////////////////////// 01657 01658 moab::ErrorCode moab::TempestOnlineMap::ApplyWeights( moab::Tag srcSolutionTag, 01659 moab::Tag tgtSolutionTag, 01660 bool transpose ) 01661 { 01662 moab::ErrorCode rval; 01663 01664 std::vector< double > solSTagVals; 01665 std::vector< double > solTTagVals; 01666 01667 moab::Range sents, tents; 01668 if( m_remapper->point_cloud_source || m_remapper->point_cloud_target ) 01669 { 01670 if( m_remapper->point_cloud_source ) 01671 { 01672 moab::Range& covSrcEnts = m_remapper->GetMeshVertices( moab::Remapper::CoveringMesh ); 01673 solSTagVals.resize( covSrcEnts.size(), -1.0 ); 01674 sents = covSrcEnts; 01675 } 01676 else 01677 { 01678 moab::Range& covSrcEnts = m_remapper->GetMeshEntities( moab::Remapper::CoveringMesh ); 01679 solSTagVals.resize( covSrcEnts.size() * this->GetSourceNDofsPerElement() * this->GetSourceNDofsPerElement(), 01680 -1.0 ); 01681 sents = covSrcEnts; 01682 } 01683 if( m_remapper->point_cloud_target ) 01684 { 01685 moab::Range& tgtEnts = m_remapper->GetMeshVertices( moab::Remapper::TargetMesh ); 01686 solTTagVals.resize( tgtEnts.size(), -1.0 ); 01687 tents = tgtEnts; 01688 } 01689 else 01690 { 01691 moab::Range& tgtEnts = m_remapper->GetMeshEntities( moab::Remapper::TargetMesh ); 01692 solTTagVals.resize( 01693 tgtEnts.size() * this->GetDestinationNDofsPerElement() * this->GetDestinationNDofsPerElement(), -1.0 ); 01694 tents = tgtEnts; 01695 } 01696 } 01697 else 01698 { 01699 moab::Range& covSrcEnts = m_remapper->GetMeshEntities( moab::Remapper::CoveringMesh ); 01700 moab::Range& tgtEnts = m_remapper->GetMeshEntities( moab::Remapper::TargetMesh ); 01701 solSTagVals.resize( covSrcEnts.size() * this->GetSourceNDofsPerElement() * this->GetSourceNDofsPerElement(), 01702 -1.0 ); 01703 solTTagVals.resize( 01704 tgtEnts.size() * this->GetDestinationNDofsPerElement() * this->GetDestinationNDofsPerElement(), -1.0 ); 01705 01706 sents = covSrcEnts; 01707 tents = tgtEnts; 01708 } 01709 01710 // The tag data is np*np*n_el_src 01711 rval = m_interface->tag_get_data( srcSolutionTag, sents, &solSTagVals[0] );MB_CHK_SET_ERR( rval, "Getting local tag data failed" ); 01712 01713 // Compute the application of weights on the suorce solution data and store it in the 01714 // destination solution vector data Optionally, can also perform the transpose application of 01715 // the weight matrix. Set the 3rd argument to true if this is needed 01716 rval = this->ApplyWeights( solSTagVals, solTTagVals, transpose );MB_CHK_SET_ERR( rval, "Applying remap operator onto source vector data failed" ); 01717 01718 // The tag data is np*np*n_el_dest 01719 rval = m_interface->tag_set_data( tgtSolutionTag, tents, &solTTagVals[0] );MB_CHK_SET_ERR( rval, "Setting local tag data failed" ); 01720 01721 return moab::MB_SUCCESS; 01722 } 01723 01724 moab::ErrorCode moab::TempestOnlineMap::DefineAnalyticalSolution( moab::Tag& solnTag, 01725 const std::string& solnName, 01726 moab::Remapper::IntersectionContext ctx, 01727 sample_function testFunction, 01728 moab::Tag* clonedSolnTag, 01729 std::string cloneSolnName ) 01730 { 01731 moab::ErrorCode rval; 01732 const bool outputEnabled = ( is_root ); 01733 int discOrder; 01734 DiscretizationType discMethod; 01735 moab::EntityHandle meshset; 01736 moab::Range entities; 01737 Mesh* trmesh; 01738 switch( ctx ) 01739 { 01740 case Remapper::SourceMesh: 01741 meshset = m_remapper->m_covering_source_set; 01742 trmesh = m_remapper->m_covering_source; 01743 entities = ( m_remapper->point_cloud_source ? m_remapper->m_covering_source_vertices 01744 : m_remapper->m_covering_source_entities ); 01745 discOrder = m_nDofsPEl_Src; 01746 discMethod = m_eInputType; 01747 break; 01748 01749 case Remapper::TargetMesh: 01750 meshset = m_remapper->m_target_set; 01751 trmesh = m_remapper->m_target; 01752 entities = 01753 ( m_remapper->point_cloud_target ? m_remapper->m_target_vertices : m_remapper->m_target_entities ); 01754 discOrder = m_nDofsPEl_Dest; 01755 discMethod = m_eOutputType; 01756 break; 01757 01758 default: 01759 if( outputEnabled ) 01760 std::cout << "Invalid context specified for defining an analytical solution tag" << std::endl; 01761 return moab::MB_FAILURE; 01762 } 01763 01764 // Let us create teh solution tag with appropriate information for name, discretization order 01765 // (DoF space) 01766 rval = m_interface->tag_get_handle( solnName.c_str(), discOrder * discOrder, MB_TYPE_DOUBLE, solnTag, 01767 MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval ); 01768 if( clonedSolnTag != NULL ) 01769 { 01770 if( cloneSolnName.size() == 0 ) 01771 { 01772 cloneSolnName = solnName + std::string( "Cloned" ); 01773 } 01774 rval = m_interface->tag_get_handle( cloneSolnName.c_str(), discOrder * discOrder, MB_TYPE_DOUBLE, 01775 *clonedSolnTag, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval ); 01776 } 01777 01778 // Triangular quadrature rule 01779 const int TriQuadratureOrder = 10; 01780 01781 if( outputEnabled ) std::cout << "Using triangular quadrature of order " << TriQuadratureOrder << std::endl; 01782 01783 TriangularQuadratureRule triquadrule( TriQuadratureOrder ); 01784 01785 const int TriQuadraturePoints = triquadrule.GetPoints(); 01786 01787 const DataArray2D< double >& TriQuadratureG = triquadrule.GetG(); 01788 const DataArray1D< double >& TriQuadratureW = triquadrule.GetW(); 01789 01790 // Output data 01791 DataArray1D< double > dVar; 01792 DataArray1D< double > dVarMB; // re-arranged local MOAB vector 01793 01794 // Nodal geometric area 01795 DataArray1D< double > dNodeArea; 01796 01797 // Calculate element areas 01798 // trmesh->CalculateFaceAreas(fContainsConcaveFaces); 01799 01800 if( discMethod == DiscretizationType_CGLL || discMethod == DiscretizationType_DGLL ) 01801 { 01802 /* Get the spectral points and sample the functionals accordingly */ 01803 const bool fGLL = true; 01804 const bool fGLLIntegrate = false; 01805 01806 // Generate grid metadata 01807 DataArray3D< int > dataGLLNodes; 01808 DataArray3D< double > dataGLLJacobian; 01809 01810 GenerateMetaData( *trmesh, discOrder, false, dataGLLNodes, dataGLLJacobian ); 01811 01812 // Number of elements 01813 int nElements = trmesh->faces.size(); 01814 01815 // Verify all elements are quadrilaterals 01816 for( int k = 0; k < nElements; k++ ) 01817 { 01818 const Face& face = trmesh->faces[k]; 01819 01820 if( face.edges.size() != 4 ) 01821 { 01822 _EXCEPTIONT( "Non-quadrilateral face detected; " 01823 "incompatible with --gll" ); 01824 } 01825 } 01826 01827 // Number of unique nodes 01828 int iMaxNode = 0; 01829 for( int i = 0; i < discOrder; i++ ) 01830 { 01831 for( int j = 0; j < discOrder; j++ ) 01832 { 01833 for( int k = 0; k < nElements; k++ ) 01834 { 01835 if( dataGLLNodes[i][j][k] > iMaxNode ) 01836 { 01837 iMaxNode = dataGLLNodes[i][j][k]; 01838 } 01839 } 01840 } 01841 } 01842 01843 // Get Gauss-Lobatto quadrature nodes 01844 DataArray1D< double > dG; 01845 DataArray1D< double > dW; 01846 01847 GaussLobattoQuadrature::GetPoints( discOrder, 0.0, 1.0, dG, dW ); 01848 01849 // Get Gauss quadrature nodes 01850 const int nGaussP = 10; 01851 01852 DataArray1D< double > dGaussG; 01853 DataArray1D< double > dGaussW; 01854 01855 GaussQuadrature::GetPoints( nGaussP, 0.0, 1.0, dGaussG, dGaussW ); 01856 01857 // Allocate data 01858 dVar.Allocate( iMaxNode ); 01859 dVarMB.Allocate( discOrder * discOrder * nElements ); 01860 dNodeArea.Allocate( iMaxNode ); 01861 01862 // Sample data 01863 for( int k = 0; k < nElements; k++ ) 01864 { 01865 const Face& face = trmesh->faces[k]; 01866 01867 // Sample data at GLL nodes 01868 if( fGLL ) 01869 { 01870 for( int i = 0; i < discOrder; i++ ) 01871 { 01872 for( int j = 0; j < discOrder; j++ ) 01873 { 01874 01875 // Apply local map 01876 Node node; 01877 Node dDx1G; 01878 Node dDx2G; 01879 01880 ApplyLocalMap( face, trmesh->nodes, dG[i], dG[j], node, dDx1G, dDx2G ); 01881 01882 // Sample data at this point 01883 double dNodeLon = atan2( node.y, node.x ); 01884 if( dNodeLon < 0.0 ) 01885 { 01886 dNodeLon += 2.0 * M_PI; 01887 } 01888 double dNodeLat = asin( node.z ); 01889 01890 double dSample = ( *testFunction )( dNodeLon, dNodeLat ); 01891 01892 dVar[dataGLLNodes[j][i][k] - 1] = dSample; 01893 } 01894 } 01895 // High-order Gaussian integration over basis function 01896 } 01897 else 01898 { 01899 DataArray2D< double > dCoeff( discOrder, discOrder ); 01900 01901 for( int p = 0; p < nGaussP; p++ ) 01902 { 01903 for( int q = 0; q < nGaussP; q++ ) 01904 { 01905 01906 // Apply local map 01907 Node node; 01908 Node dDx1G; 01909 Node dDx2G; 01910 01911 ApplyLocalMap( face, trmesh->nodes, dGaussG[p], dGaussG[q], node, dDx1G, dDx2G ); 01912 01913 // Cross product gives local Jacobian 01914 Node nodeCross = CrossProduct( dDx1G, dDx2G ); 01915 01916 double dJacobian = 01917 sqrt( nodeCross.x * nodeCross.x + nodeCross.y * nodeCross.y + nodeCross.z * nodeCross.z ); 01918 01919 // Find components of quadrature point in basis 01920 // of the first Face 01921 SampleGLLFiniteElement( 0, discOrder, dGaussG[p], dGaussG[q], dCoeff ); 01922 01923 // Sample data at this point 01924 double dNodeLon = atan2( node.y, node.x ); 01925 if( dNodeLon < 0.0 ) 01926 { 01927 dNodeLon += 2.0 * M_PI; 01928 } 01929 double dNodeLat = asin( node.z ); 01930 01931 double dSample = ( *testFunction )( dNodeLon, dNodeLat ); 01932 01933 // Integrate 01934 for( int i = 0; i < discOrder; i++ ) 01935 { 01936 for( int j = 0; j < discOrder; j++ ) 01937 { 01938 01939 double dNodalArea = dCoeff[i][j] * dGaussW[p] * dGaussW[q] * dJacobian; 01940 01941 dVar[dataGLLNodes[i][j][k] - 1] += dSample * dNodalArea; 01942 01943 dNodeArea[dataGLLNodes[i][j][k] - 1] += dNodalArea; 01944 } 01945 } 01946 } 01947 } 01948 } 01949 } 01950 01951 // Divide by area 01952 if( fGLLIntegrate ) 01953 { 01954 for( size_t i = 0; i < dVar.GetRows(); i++ ) 01955 { 01956 dVar[i] /= dNodeArea[i]; 01957 } 01958 } 01959 01960 // Let us rearrange the data based on DoF ID specification 01961 if( ctx == Remapper::SourceMesh ) 01962 { 01963 for( unsigned j = 0; j < entities.size(); j++ ) 01964 for( int p = 0; p < discOrder; p++ ) 01965 for( int q = 0; q < discOrder; q++ ) 01966 { 01967 const int offsetDOF = j * discOrder * discOrder + p * discOrder + q; 01968 dVarMB[offsetDOF] = dVar[col_dtoc_dofmap[offsetDOF]]; 01969 } 01970 } 01971 else 01972 { 01973 for( unsigned j = 0; j < entities.size(); j++ ) 01974 for( int p = 0; p < discOrder; p++ ) 01975 for( int q = 0; q < discOrder; q++ ) 01976 { 01977 const int offsetDOF = j * discOrder * discOrder + p * discOrder + q; 01978 dVarMB[offsetDOF] = dVar[row_dtoc_dofmap[offsetDOF]]; 01979 } 01980 } 01981 01982 // Set the tag data 01983 rval = m_interface->tag_set_data( solnTag, entities, &dVarMB[0] );MB_CHK_ERR( rval ); 01984 } 01985 else 01986 { 01987 // assert( discOrder == 1 ); 01988 if( discMethod == DiscretizationType_FV ) 01989 { 01990 /* Compute an element-wise integral to store the sampled solution based on Quadrature 01991 * rules */ 01992 // Resize the array 01993 dVar.Allocate( trmesh->faces.size() ); 01994 01995 std::vector< Node >& nodes = trmesh->nodes; 01996 01997 // Loop through all Faces 01998 for( size_t i = 0; i < trmesh->faces.size(); i++ ) 01999 { 02000 const Face& face = trmesh->faces[i]; 02001 02002 // Loop through all sub-triangles 02003 for( size_t j = 0; j < face.edges.size() - 2; j++ ) 02004 { 02005 02006 const Node& node0 = nodes[face[0]]; 02007 const Node& node1 = nodes[face[j + 1]]; 02008 const Node& node2 = nodes[face[j + 2]]; 02009 02010 // Triangle area 02011 Face faceTri( 3 ); 02012 faceTri.SetNode( 0, face[0] ); 02013 faceTri.SetNode( 1, face[j + 1] ); 02014 faceTri.SetNode( 2, face[j + 2] ); 02015 02016 double dTriangleArea = CalculateFaceArea( faceTri, nodes ); 02017 02018 // Calculate the element average 02019 double dTotalSample = 0.0; 02020 02021 // Loop through all quadrature points 02022 for( int k = 0; k < TriQuadraturePoints; k++ ) 02023 { 02024 Node node( TriQuadratureG[k][0] * node0.x + TriQuadratureG[k][1] * node1.x + 02025 TriQuadratureG[k][2] * node2.x, 02026 TriQuadratureG[k][0] * node0.y + TriQuadratureG[k][1] * node1.y + 02027 TriQuadratureG[k][2] * node2.y, 02028 TriQuadratureG[k][0] * node0.z + TriQuadratureG[k][1] * node1.z + 02029 TriQuadratureG[k][2] * node2.z ); 02030 02031 double dMagnitude = node.Magnitude(); 02032 node.x /= dMagnitude; 02033 node.y /= dMagnitude; 02034 node.z /= dMagnitude; 02035 02036 double dLon = atan2( node.y, node.x ); 02037 if( dLon < 0.0 ) 02038 { 02039 dLon += 2.0 * M_PI; 02040 } 02041 double dLat = asin( node.z ); 02042 02043 double dSample = ( *testFunction )( dLon, dLat ); 02044 02045 dTotalSample += dSample * TriQuadratureW[k] * dTriangleArea; 02046 } 02047 02048 dVar[i] += dTotalSample / trmesh->vecFaceArea[i]; 02049 } 02050 } 02051 rval = m_interface->tag_set_data( solnTag, entities, &dVar[0] );MB_CHK_ERR( rval ); 02052 } 02053 else /* discMethod == DiscretizationType_PCLOUD */ 02054 { 02055 /* Get the coordinates of the vertices and sample the functionals accordingly */ 02056 std::vector< Node >& nodes = trmesh->nodes; 02057 02058 // Resize the array 02059 dVar.Allocate( nodes.size() ); 02060 02061 for( size_t j = 0; j < nodes.size(); j++ ) 02062 { 02063 Node& node = nodes[j]; 02064 double dMagnitude = node.Magnitude(); 02065 node.x /= dMagnitude; 02066 node.y /= dMagnitude; 02067 node.z /= dMagnitude; 02068 double dLon = atan2( node.y, node.x ); 02069 if( dLon < 0.0 ) 02070 { 02071 dLon += 2.0 * M_PI; 02072 } 02073 double dLat = asin( node.z ); 02074 02075 double dSample = ( *testFunction )( dLon, dLat ); 02076 dVar[j] = dSample; 02077 } 02078 02079 rval = m_interface->tag_set_data( solnTag, entities, &dVar[0] );MB_CHK_ERR( rval ); 02080 } 02081 } 02082 02083 return moab::MB_SUCCESS; 02084 } 02085 02086 moab::ErrorCode moab::TempestOnlineMap::ComputeMetrics( moab::Remapper::IntersectionContext ctx, 02087 moab::Tag& exactTag, 02088 moab::Tag& approxTag, 02089 std::map< std::string, double >& metrics, 02090 bool verbose ) 02091 { 02092 moab::ErrorCode rval; 02093 const bool outputEnabled = ( is_root ); 02094 int discOrder; 02095 DiscretizationType discMethod; 02096 moab::EntityHandle meshset; 02097 moab::Range entities; 02098 Mesh* trmesh; 02099 switch( ctx ) 02100 { 02101 case Remapper::SourceMesh: 02102 meshset = m_remapper->m_covering_source_set; 02103 trmesh = m_remapper->m_covering_source; 02104 entities = ( m_remapper->point_cloud_source ? m_remapper->m_covering_source_vertices 02105 : m_remapper->m_covering_source_entities ); 02106 discOrder = m_nDofsPEl_Src; 02107 discMethod = m_eInputType; 02108 break; 02109 02110 case Remapper::TargetMesh: 02111 meshset = m_remapper->m_target_set; 02112 trmesh = m_remapper->m_target; 02113 entities = 02114 ( m_remapper->point_cloud_target ? m_remapper->m_target_vertices : m_remapper->m_target_entities ); 02115 discOrder = m_nDofsPEl_Dest; 02116 discMethod = m_eOutputType; 02117 break; 02118 02119 default: 02120 if( outputEnabled ) 02121 std::cout << "Invalid context specified for defining an analytical solution tag" << std::endl; 02122 return moab::MB_FAILURE; 02123 } 02124 02125 // Let us create teh solution tag with appropriate information for name, discretization order 02126 // (DoF space) 02127 std::string exactTagName, projTagName; 02128 const int ntotsize = entities.size() * discOrder * discOrder; 02129 int ntotsize_glob = 0; 02130 std::vector< double > exactSolution( ntotsize, 0.0 ), projSolution( ntotsize, 0.0 ); 02131 rval = m_interface->tag_get_name( exactTag, exactTagName );MB_CHK_ERR( rval ); 02132 rval = m_interface->tag_get_data( exactTag, entities, &exactSolution[0] );MB_CHK_ERR( rval ); 02133 rval = m_interface->tag_get_name( approxTag, projTagName );MB_CHK_ERR( rval ); 02134 rval = m_interface->tag_get_data( approxTag, entities, &projSolution[0] );MB_CHK_ERR( rval ); 02135 02136 std::vector< double > errnorms( 3, 0.0 ), globerrnorms( 3, 0.0 ); // L1Err, L2Err, LinfErr 02137 for( int i = 0; i < ntotsize; ++i ) 02138 { 02139 const double error = fabs( exactSolution[i] - projSolution[i] ); 02140 errnorms[0] += error; 02141 errnorms[1] += error * error; 02142 errnorms[2] = ( error > errnorms[2] ? error : errnorms[2] ); 02143 } 02144 #ifdef MOAB_HAVE_MPI 02145 if( m_pcomm ) 02146 { 02147 MPI_Reduce( &ntotsize, &ntotsize_glob, 1, MPI_INT, MPI_SUM, 0, m_pcomm->comm() ); 02148 MPI_Reduce( &errnorms[0], &globerrnorms[0], 2, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() ); 02149 MPI_Reduce( &errnorms[2], &globerrnorms[2], 1, MPI_DOUBLE, MPI_MAX, 0, m_pcomm->comm() ); 02150 } 02151 #else 02152 ntotsize_glob = ntotsize; 02153 globerrnorms = errnorms; 02154 #endif 02155 globerrnorms[0] = ( globerrnorms[0] / ntotsize_glob ); 02156 globerrnorms[1] = std::sqrt( globerrnorms[1] / ntotsize_glob ); 02157 02158 metrics.clear(); 02159 metrics["L1Error"] = globerrnorms[0]; 02160 metrics["L2Error"] = globerrnorms[1]; 02161 metrics["LinfError"] = globerrnorms[2]; 02162 02163 if( verbose && is_root ) 02164 { 02165 std::cout << "Error metrics when comparing " << projTagName << " against " << exactTagName << std::endl; 02166 std::cout << "\t L_1 error = " << globerrnorms[0] << std::endl; 02167 std::cout << "\t L_2 error = " << globerrnorms[1] << std::endl; 02168 std::cout << "\t L_inf error = " << globerrnorms[2] << std::endl; 02169 } 02170 02171 return moab::MB_SUCCESS; 02172 }