![]() |
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), mahadevan@anl.gov
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
00030 #include
00031 #include
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 dColumnSumsOnRoot(nTotColumnsUnq, 0.0);
01581 std::map< int, double > dColumnSumsOnRoot;
01582 // std::map 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 }