16 #include "DataArray3D.h"
17 #include "FiniteVolumeTools.h"
18 #include "FiniteElementTools.h"
19 #include "TriangularQuadrature.h"
20 #include "GaussQuadrature.h"
21 #include "GaussLobattoQuadrature.h"
22 #include "SparseMatrix.h"
23 #include "STLStringHelper.h"
24 #include "LinearRemapFV.h"
26 #include "LinearRemapSE0.h"
27 #include "LinearRemapFV.h"
40 #ifdef MOAB_HAVE_NETCDFPAR
43 #include "netcdfcpp.h"
56 #define MPI_CHK_ERR( err ) \
59 std::cout << "MPI Failure. ErrorCode (" << ( err ) << ") "; \
60 std::cout << "\nMPI Aborting... \n"; \
61 return moab::MB_FAILURE; \
69 m_pcomm =
m_remapper->get_parallel_communicator();
94 std::vector< std::string > dimNames;
95 std::vector< int > dimSizes;
96 dimNames.push_back(
"num_elem" );
97 dimSizes.push_back( m_meshInputCov->faces.size() );
99 this->InitializeSourceDimensions( dimNames, dimSizes );
104 std::vector< std::string > dimNames;
105 std::vector< int > dimSizes;
106 dimNames.push_back(
"num_elem" );
107 dimSizes.push_back( m_meshOutput->faces.size() );
109 this->InitializeTargetDimensions( dimNames, dimSizes );
117 m_interface =
nullptr;
121 m_meshInput =
nullptr;
122 m_meshOutput =
nullptr;
123 m_meshOverlap =
nullptr;
129 const std::string tgtDofTagName )
134 tagSize = ( m_eInputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Src * m_nDofsPEl_Src );
140 MB_CHK_SET_ERR( MB_FAILURE,
"DoF tag is not set correctly for source mesh." );
145 tagSize = ( m_eOutputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Dest * m_nDofsPEl_Dest );
150 MB_CHK_SET_ERR( MB_FAILURE,
"DoF tag is not set correctly for target mesh." );
162 bool isSrcContinuous,
163 DataArray3D< int >* srcdataGLLNodes,
164 DataArray3D< int >* srcdataGLLNodesSrc,
167 bool isTgtContinuous,
168 DataArray3D< int >* tgtdataGLLNodes )
171 std::vector< bool > dgll_cgll_row_ldofmap, dgll_cgll_col_ldofmap, dgll_cgll_covcol_ldofmap;
172 std::vector< int > src_soln_gdofs, locsrc_soln_gdofs, tgt_soln_gdofs;
175 m_srcDiscType = srcType;
176 m_destDiscType = destType;
177 m_input_order = srcOrder;
178 m_output_order = destOrder;
180 bool vprint = is_root &&
false;
186 src_soln_gdofs.resize( m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src, -1 );
187 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_entities, &src_soln_gdofs[0] );
MB_CHK_ERR( rval );
188 locsrc_soln_gdofs.resize( m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src );
189 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_entities, &locsrc_soln_gdofs[0] );
MB_CHK_ERR( rval );
190 tgt_soln_gdofs.resize( m_remapper->m_target_entities.size() * m_nDofsPEl_Dest * m_nDofsPEl_Dest );
191 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_entities, &tgt_soln_gdofs[0] );
MB_CHK_ERR( rval );
196 std::ofstream output_file(
"sourcecov-gids-0.txt" );
197 output_file <<
"I, GDOF\n";
198 for(
unsigned i = 0; i < src_soln_gdofs.size(); ++i )
199 output_file << i <<
", " << src_soln_gdofs[i] <<
"\n";
201 output_file <<
"ELEMID, IDOF, LDOF, GDOF, NDOF\n";
202 m_nTotDofs_SrcCov = 0;
203 if( isSrcContinuous )
204 dgll_cgll_covcol_ldofmap.resize(
205 m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src,
false );
206 for(
unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ )
208 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
210 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
212 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1;
213 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q;
214 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] )
217 dgll_cgll_covcol_ldofmap[localDOF] =
true;
219 output_file << m_remapper->lid_to_gid_covsrc[j] <<
", " << offsetDOF <<
", " << localDOF
220 <<
", " << src_soln_gdofs[offsetDOF] <<
", " << m_nTotDofs_SrcCov <<
"\n";
226 dgll_cgll_covcol_ldofmap.clear();
230 std::ofstream output_file(
"source-gids-0.txt" );
231 output_file <<
"I, GDOF\n";
232 for(
unsigned i = 0; i < locsrc_soln_gdofs.size(); ++i )
233 output_file << i <<
", " << locsrc_soln_gdofs[i] <<
"\n";
235 output_file <<
"ELEMID, IDOF, LDOF, GDOF, NDOF\n";
237 if( isSrcContinuous )
238 dgll_cgll_col_ldofmap.resize(
239 m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src,
false );
240 for(
unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ )
242 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
244 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
246 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1;
247 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q;
248 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] )
251 dgll_cgll_col_ldofmap[localDOF] =
true;
253 output_file << m_remapper->lid_to_gid_src[j] <<
", " << offsetDOF <<
", " << localDOF
254 <<
", " << locsrc_soln_gdofs[offsetDOF] <<
", " << m_nTotDofs_Src <<
"\n";
260 dgll_cgll_col_ldofmap.clear();
264 std::ofstream output_file(
"target-gids-0.txt" );
265 output_file <<
"I, GDOF\n";
266 for(
unsigned i = 0; i < tgt_soln_gdofs.size(); ++i )
267 output_file << i <<
", " << tgt_soln_gdofs[i] <<
"\n";
269 output_file <<
"ELEMID, IDOF, GDOF, NDOF\n";
272 for(
unsigned i = 0; i < tgt_soln_gdofs.size(); ++i )
274 output_file << m_remapper->lid_to_gid_tgt[i] <<
", " << i <<
", " << tgt_soln_gdofs[i] <<
", "
275 << m_nTotDofs_Dest <<
"\n";
286 std::ofstream output_file(
"sourcecov-gids-1.txt" );
287 output_file <<
"I, GDOF\n";
288 for(
unsigned i = 0; i < src_soln_gdofs.size(); ++i )
289 output_file << i <<
", " << src_soln_gdofs[i] <<
"\n";
291 output_file <<
"ELEMID, IDOF, LDOF, GDOF, NDOF\n";
292 m_nTotDofs_SrcCov = 0;
293 if( isSrcContinuous )
294 dgll_cgll_covcol_ldofmap.resize(
295 m_remapper->m_covering_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src,
false );
296 for(
unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ )
298 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
300 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
302 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1;
303 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q;
304 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] )
307 dgll_cgll_covcol_ldofmap[localDOF] =
true;
309 output_file << m_remapper->lid_to_gid_covsrc[j] <<
", " << offsetDOF <<
", " << localDOF
310 <<
", " << src_soln_gdofs[offsetDOF] <<
", " << m_nTotDofs_SrcCov <<
"\n";
316 dgll_cgll_covcol_ldofmap.clear();
320 std::ofstream output_file(
"source-gids-1.txt" );
321 output_file <<
"I, GDOF\n";
322 for(
unsigned i = 0; i < locsrc_soln_gdofs.size(); ++i )
323 output_file << i <<
", " << locsrc_soln_gdofs[i] <<
"\n";
325 output_file <<
"ELEMID, IDOF, LDOF, GDOF, NDOF\n";
327 if( isSrcContinuous )
328 dgll_cgll_col_ldofmap.resize(
329 m_remapper->m_source_entities.size() * m_nDofsPEl_Src * m_nDofsPEl_Src,
false );
330 for(
unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ )
332 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
334 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
336 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1;
337 const int offsetDOF = j * m_nDofsPEl_Src * m_nDofsPEl_Src + p * m_nDofsPEl_Src + q;
338 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] )
341 dgll_cgll_col_ldofmap[localDOF] =
true;
343 output_file << m_remapper->lid_to_gid_src[j] <<
", " << offsetDOF <<
", " << localDOF
344 <<
", " << locsrc_soln_gdofs[offsetDOF] <<
", " << m_nTotDofs_Src <<
"\n";
350 dgll_cgll_col_ldofmap.clear();
354 std::ofstream output_file(
"target-gids-1.txt" );
355 output_file <<
"I, GDOF\n";
356 for(
unsigned i = 0; i < tgt_soln_gdofs.size(); ++i )
357 output_file << i <<
", " << tgt_soln_gdofs[i] <<
"\n";
359 output_file <<
"ELEMID, IDOF, GDOF, NDOF\n";
362 for(
unsigned i = 0; i < tgt_soln_gdofs.size(); ++i )
364 output_file << m_remapper->lid_to_gid_tgt[i] <<
", " << i <<
", " << tgt_soln_gdofs[i] <<
", "
365 << m_nTotDofs_Dest <<
"\n";
377 int srcTagSize = ( m_eInputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Src * m_nDofsPEl_Src );
378 if( m_remapper->point_cloud_source )
380 assert( m_nDofsPEl_Src == 1 );
381 col_gdofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX );
382 col_dtoc_dofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX );
383 src_soln_gdofs.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX );
384 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_vertices, &src_soln_gdofs[0] );
MB_CHK_ERR( rval );
389 col_gdofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX );
390 col_dtoc_dofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX );
391 src_soln_gdofs.resize( m_remapper->m_covering_source_entities.size() * srcTagSize, UINT_MAX );
392 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_covering_source_entities, &src_soln_gdofs[0] );
MB_CHK_ERR( rval );
398 #ifdef ALTERNATE_NUMBERING_IMPLEMENTATION
399 unsigned maxSrcIndx = 0;
402 std::vector< int > locdofs( srcTagSize );
403 std::map< Node, moab::EntityHandle > mapLocalMBNodes;
405 for(
unsigned iel = 0; iel < m_remapper->m_covering_source_entities.size(); ++iel )
407 EntityHandle eh = m_remapper->m_covering_source_entities[iel];
408 rval = m_interface->get_coords( &eh, 1, elcoords );
MB_CHK_ERR( rval );
409 Node elCentroid( elcoords[0], elcoords[1], elcoords[2] );
410 mapLocalMBNodes.insert( std::pair< Node, moab::EntityHandle >( elCentroid, eh ) );
413 const NodeVector& nodes = m_remapper->m_covering_source->nodes;
414 for(
unsigned j = 0; j < m_remapper->m_covering_source->faces.size(); j++ )
416 const Face&
face = m_remapper->m_covering_source->faces[j];
419 centroid.x = centroid.y = centroid.z = 0.0;
420 for(
unsigned l = 0; l <
face.edges.size(); ++l )
422 centroid.x += nodes[
face[l]].x;
423 centroid.y += nodes[
face[l]].y;
424 centroid.z += nodes[
face[l]].z;
426 const double factor = 1.0 /
face.edges.size();
427 centroid.x *= factor;
428 centroid.y *= factor;
429 centroid.z *= factor;
432 if( mapLocalMBNodes.find( centroid ) != mapLocalMBNodes.end() )
434 current_eh = mapLocalMBNodes[centroid];
437 rval = m_interface->tag_get_data( m_dofTagSrc, ¤t_eh, 1, &locdofs[0] );
MB_CHK_ERR( rval );
438 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
440 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
442 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1;
443 const int offsetDOF = p * m_nDofsPEl_Src + q;
444 maxSrcIndx = ( localDOF > maxSrcIndx ? localDOF : maxSrcIndx );
445 std::cout <<
"Col: " << current_eh <<
", " << m_remapper->lid_to_gid_covsrc[j] <<
", " << offsetDOF
446 <<
", " << localDOF <<
", " << locdofs[offsetDOF] - 1 <<
", " << maxSrcIndx <<
"\n";
452 m_nTotDofs_SrcCov = 0;
453 if( srcdataGLLNodes ==
nullptr )
455 for(
unsigned i = 0; i < col_gdofmap.size(); ++i )
457 assert( src_soln_gdofs[i] > 0 );
458 col_gdofmap[i] = src_soln_gdofs[i] - 1;
459 col_dtoc_dofmap[i] = i;
460 if( vprint ) std::cout <<
"Col: " << i <<
", " << col_gdofmap[i] <<
"\n";
466 if( isSrcContinuous )
467 dgll_cgll_covcol_ldofmap.resize( m_remapper->m_covering_source_entities.size() * srcTagSize,
false );
469 for(
unsigned j = 0; j < m_remapper->m_covering_source_entities.size(); j++ )
471 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
473 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
475 const int localDOF = ( *srcdataGLLNodes )[p][q][j] - 1;
476 const int offsetDOF = j * srcTagSize + p * m_nDofsPEl_Src + q;
477 if( isSrcContinuous && !dgll_cgll_covcol_ldofmap[localDOF] )
480 dgll_cgll_covcol_ldofmap[localDOF] =
true;
482 if( !isSrcContinuous ) m_nTotDofs_SrcCov++;
483 assert( src_soln_gdofs[offsetDOF] > 0 );
484 col_gdofmap[localDOF] = src_soln_gdofs[offsetDOF] - 1;
485 col_dtoc_dofmap[offsetDOF] = localDOF;
487 std::cout <<
"Col: " << m_remapper->lid_to_gid_covsrc[j] <<
", " << offsetDOF <<
", "
488 << localDOF <<
", " << col_gdofmap[offsetDOF] <<
", " << m_nTotDofs_SrcCov <<
"\n";
494 if( m_remapper->point_cloud_source )
496 assert( m_nDofsPEl_Src == 1 );
497 srccol_gdofmap.resize( m_remapper->m_source_vertices.size(), UINT_MAX );
498 srccol_dtoc_dofmap.resize( m_remapper->m_covering_source_vertices.size(), UINT_MAX );
499 locsrc_soln_gdofs.resize( m_remapper->m_source_vertices.size(), UINT_MAX );
500 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_vertices, &locsrc_soln_gdofs[0] );
MB_CHK_ERR( rval );
504 srccol_gdofmap.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX );
505 srccol_dtoc_dofmap.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX );
506 locsrc_soln_gdofs.resize( m_remapper->m_source_entities.size() * srcTagSize, UINT_MAX );
507 rval = m_interface->tag_get_data( m_dofTagSrc, m_remapper->m_source_entities, &locsrc_soln_gdofs[0] );
MB_CHK_ERR( rval );
512 if( srcdataGLLNodesSrc ==
nullptr )
514 for(
unsigned i = 0; i < srccol_gdofmap.size(); ++i )
516 assert( locsrc_soln_gdofs[i] > 0 );
517 srccol_gdofmap[i] = locsrc_soln_gdofs[i] - 1;
518 srccol_dtoc_dofmap[i] = i;
524 if( isSrcContinuous ) dgll_cgll_col_ldofmap.resize( m_remapper->m_source_entities.size() * srcTagSize,
false );
526 for(
unsigned j = 0; j < m_remapper->m_source_entities.size(); j++ )
528 for(
int p = 0; p < m_nDofsPEl_Src; p++ )
530 for(
int q = 0; q < m_nDofsPEl_Src; q++ )
532 const int localDOF = ( *srcdataGLLNodesSrc )[p][q][j] - 1;
533 const int offsetDOF = j * srcTagSize + p * m_nDofsPEl_Src + q;
534 if( isSrcContinuous && !dgll_cgll_col_ldofmap[localDOF] )
537 dgll_cgll_col_ldofmap[localDOF] =
true;
539 if( !isSrcContinuous ) m_nTotDofs_Src++;
540 assert( locsrc_soln_gdofs[offsetDOF] > 0 );
541 srccol_gdofmap[localDOF] = locsrc_soln_gdofs[offsetDOF] - 1;
542 srccol_dtoc_dofmap[offsetDOF] = localDOF;
548 int tgtTagSize = ( m_eOutputType == DiscretizationType_FV ? 1 : m_nDofsPEl_Dest * m_nDofsPEl_Dest );
549 if( m_remapper->point_cloud_target )
551 assert( m_nDofsPEl_Dest == 1 );
552 row_gdofmap.resize( m_remapper->m_target_vertices.size(), UINT_MAX );
553 row_dtoc_dofmap.resize( m_remapper->m_target_vertices.size(), UINT_MAX );
554 tgt_soln_gdofs.resize( m_remapper->m_target_vertices.size(), UINT_MAX );
555 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_vertices, &tgt_soln_gdofs[0] );
MB_CHK_ERR( rval );
560 row_gdofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX );
561 row_dtoc_dofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX );
562 tgt_soln_gdofs.resize( m_remapper->m_target_entities.size() * tgtTagSize, UINT_MAX );
563 rval = m_interface->tag_get_data( m_dofTagDest, m_remapper->m_target_entities, &tgt_soln_gdofs[0] );
MB_CHK_ERR( rval );
569 if( tgtdataGLLNodes ==
nullptr )
571 for(
unsigned i = 0; i < row_gdofmap.size(); ++i )
573 assert( tgt_soln_gdofs[i] > 0 );
574 row_gdofmap[i] = tgt_soln_gdofs[i] - 1;
575 row_dtoc_dofmap[i] = i;
576 if( vprint ) std::cout <<
"Row: " << i <<
", " << row_gdofmap[i] <<
"\n";
582 if( isTgtContinuous ) dgll_cgll_row_ldofmap.resize( m_remapper->m_target_entities.size() * tgtTagSize,
false );
584 for(
unsigned j = 0; j < m_remapper->m_target_entities.size(); j++ )
586 for(
int p = 0; p < m_nDofsPEl_Dest; p++ )
588 for(
int q = 0; q < m_nDofsPEl_Dest; q++ )
590 const int localDOF = ( *tgtdataGLLNodes )[p][q][j] - 1;
591 const int offsetDOF = j * tgtTagSize + p * m_nDofsPEl_Dest + q;
592 if( isTgtContinuous && !dgll_cgll_row_ldofmap[localDOF] )
595 dgll_cgll_row_ldofmap[localDOF] =
true;
597 if( !isTgtContinuous ) m_nTotDofs_Dest++;
598 assert( tgt_soln_gdofs[offsetDOF] > 0 );
599 row_gdofmap[localDOF] = tgt_soln_gdofs[offsetDOF] - 1;
600 row_dtoc_dofmap[offsetDOF] = localDOF;
602 std::cout <<
"Row: " << m_remapper->lid_to_gid_tgt[j] <<
", " << offsetDOF <<
", " << localDOF
603 <<
", " << row_gdofmap[offsetDOF] <<
", " << m_nTotDofs_Dest <<
"\n";
610 #if defined( MOAB_HAVE_EIGEN3 ) && defined( VERBOSE )
613 std::cout <<
"[" << rank <<
"]"
614 <<
"DoFs: row = " << m_nTotDofs_Dest <<
", " << row_gdofmap.size() <<
", col = " << m_nTotDofs_Src
615 <<
", " << m_nTotDofs_SrcCov <<
", " << col_gdofmap.size() <<
"\n";
621 #ifdef CHECK_INCREASING_DOF
622 for(
size_t i = 0; i < row_gdofmap.size() - 1; i++ )
624 if( row_gdofmap[i] > row_gdofmap[i + 1] )
625 std::cout <<
" on rank " << rank <<
" in row_gdofmap[" << i <<
"]=" << row_gdofmap[i] <<
" > row_gdofmap["
626 << i + 1 <<
"]=" << row_gdofmap[i + 1] <<
" \n";
628 for(
size_t i = 0; i < col_gdofmap.size() - 1; i++ )
630 if( col_gdofmap[i] > col_gdofmap[i + 1] )
631 std::cout <<
" on rank " << rank <<
" in col_gdofmap[" << i <<
"]=" << col_gdofmap[i] <<
" > col_gdofmap["
632 << i + 1 <<
"]=" << col_gdofmap[i + 1] <<
" \n";
647 col_dtoc_dofmap.resize( values_entities.size() );
648 for(
int j = 0; j < (int)values_entities.size(); j++ )
650 if( colMap.find( values_entities[j] - 1 ) != colMap.end() )
651 col_dtoc_dofmap[j] = colMap[values_entities[j] - 1];
654 col_dtoc_dofmap[j] = -1;
667 row_dtoc_dofmap.resize( values_entities.size() );
668 for(
int j = 0; j < (int)values_entities.size(); j++ )
670 if( rowMap.find( values_entities[j] - 1 ) != rowMap.end() )
671 row_dtoc_dofmap[j] = rowMap[values_entities[j] - 1];
674 row_dtoc_dofmap[j] = -1;
684 std::string strOutputType,
685 const GenerateOfflineMapAlgorithmOptions& mapOptions,
686 const std::string& srcDofTagName,
687 const std::string& tgtDofTagName )
689 NcError
error( NcError::silent_nonfatal );
692 dbgprint.set_prefix(
"[TempestOnlineMap]: " );
695 const bool m_bPointCloudSource = ( m_remapper->point_cloud_source );
696 const bool m_bPointCloudTarget = ( m_remapper->point_cloud_target );
697 const bool m_bPointCloud = m_bPointCloudSource || m_bPointCloudTarget;
706 STLStringHelper::ToLower( strInputType );
707 STLStringHelper::ToLower( strOutputType );
712 if( strInputType ==
"fv" )
714 eInputType = DiscretizationType_FV;
716 else if( strInputType ==
"cgll" )
718 eInputType = DiscretizationType_CGLL;
720 else if( strInputType ==
"dgll" )
722 eInputType = DiscretizationType_DGLL;
724 else if( strInputType ==
"pcloud" )
726 eInputType = DiscretizationType_PCLOUD;
730 _EXCEPTION1(
"Invalid \"in_type\" value (%s), expected [fv|cgll|dgll]", strInputType.c_str() );
733 if( strOutputType ==
"fv" )
735 eOutputType = DiscretizationType_FV;
737 else if( strOutputType ==
"cgll" )
739 eOutputType = DiscretizationType_CGLL;
741 else if( strOutputType ==
"dgll" )
743 eOutputType = DiscretizationType_DGLL;
745 else if( strOutputType ==
"pcloud" )
747 eOutputType = DiscretizationType_PCLOUD;
751 _EXCEPTION1(
"Invalid \"out_type\" value (%s), expected [fv|cgll|dgll]", strOutputType.c_str() );
755 m_bConserved = !mapOptions.fNoConservation;
756 m_eInputType = eInputType;
757 m_eOutputType = eOutputType;
760 std::string strMapAlgorithm(
"" );
761 int nMonotoneType = ( mapOptions.fMonotone ) ? ( 1 ) : ( 0 );
764 std::set< std::string > setMethodStrings;
767 for(
size_t i = 0; i <= mapOptions.strMethod.length(); i++ )
769 if( ( i == mapOptions.strMethod.length() ) || ( mapOptions.strMethod[i] ==
';' ) )
771 std::string strMethodString = mapOptions.strMethod.substr( iLast, i - iLast );
772 STLStringHelper::RemoveWhitespaceInPlace( strMethodString );
773 if( strMethodString.length() > 0 )
775 setMethodStrings.insert( strMethodString );
782 for(
auto it : setMethodStrings )
787 if( nMonotoneType != 0 )
789 _EXCEPTIONT(
"Multiple monotonicity specifications found (--mono) or (--method \"mono#\")" );
791 if( ( m_eInputType == DiscretizationType_FV ) && ( m_eOutputType == DiscretizationType_FV ) )
793 _EXCEPTIONT(
"--method \"mono2\" is only used when remapping to/from CGLL or DGLL grids" );
799 else if( it ==
"mono3" )
801 if( nMonotoneType != 0 )
803 _EXCEPTIONT(
"Multiple monotonicity specifications found (--mono) or (--method \"mono#\")" );
805 if( ( m_eInputType == DiscretizationType_FV ) && ( m_eOutputType == DiscretizationType_FV ) )
807 _EXCEPTIONT(
"--method \"mono3\" is only used when remapping to/from CGLL or DGLL grids" );
813 else if( it ==
"volumetric" )
815 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType == DiscretizationType_FV ) )
817 _EXCEPTIONT(
"--method \"volumetric\" may only be used for FV->CGLL or FV->DGLL remapping" );
819 strMapAlgorithm =
"volumetric";
823 else if( it ==
"invdist" )
825 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) )
827 _EXCEPTIONT(
"--method \"invdist\" may only be used for FV->FV remapping" );
829 strMapAlgorithm =
"invdist";
833 else if( it ==
"delaunay" )
835 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) )
837 _EXCEPTIONT(
"--method \"delaunay\" may only be used for FV->FV remapping" );
839 strMapAlgorithm =
"delaunay";
843 else if( it ==
"bilin" )
845 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) )
847 _EXCEPTIONT(
"--method \"bilin\" may only be used for FV->FV remapping" );
849 strMapAlgorithm =
"fvbilin";
853 else if( it ==
"intbilin" )
855 if( m_eOutputType != DiscretizationType_FV )
857 _EXCEPTIONT(
"--method \"intbilin\" may only be used when mapping to FV." );
859 if( m_eInputType == DiscretizationType_FV )
861 strMapAlgorithm =
"fvintbilin";
865 strMapAlgorithm =
"mono3";
870 else if( it ==
"intbilingb" )
872 if( ( m_eInputType != DiscretizationType_FV ) || ( m_eOutputType != DiscretizationType_FV ) )
874 _EXCEPTIONT(
"--method \"intbilingb\" may only be used for FV->FV remapping" );
876 strMapAlgorithm =
"fvintbilingb";
880 _EXCEPTION1(
"Invalid --method argument \"%s\"", it.c_str() );
885 ( m_eInputType == DiscretizationType_FV || m_eInputType == DiscretizationType_PCLOUD ? 1
888 ( m_eOutputType == DiscretizationType_FV || m_eOutputType == DiscretizationType_PCLOUD ? 1
889 : mapOptions.nPout );
891 rval = SetDOFmapTags( srcDofTagName, tgtDofTagName );
MB_CHK_ERR( rval );
895 rval = m_interface->tag_get_handle(
"aream", 1,
MB_TYPE_DOUBLE, areaTag,
899 if( is_root )
dbgprint.printf( 0,
"aream tag already defined \n" );
902 double dTotalAreaInput = 0.0, dTotalAreaOutput = 0.0;
903 if( !m_bPointCloudSource )
906 if( is_root )
dbgprint.printf( 0,
"Calculating input mesh Face areas\n" );
907 double dTotalAreaInput_loc = m_meshInput->CalculateFaceAreas( mapOptions.fSourceConcave );
908 rval = m_interface->tag_set_data( areaTag, m_remapper->m_source_entities, m_meshInput->vecFaceArea );
MB_CHK_ERR( rval );
909 dTotalAreaInput = dTotalAreaInput_loc;
912 MPI_Reduce( &dTotalAreaInput_loc, &dTotalAreaInput, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
914 if( is_root )
dbgprint.printf( 0,
"Input Mesh Geometric Area: %1.15e\n", dTotalAreaInput );
917 m_meshInputCov->CalculateFaceAreas( mapOptions.fSourceConcave );
922 if( !m_bPointCloudTarget )
925 if( is_root )
dbgprint.printf( 0,
"Calculating output mesh Face areas\n" );
926 double dTotalAreaOutput_loc = m_meshOutput->CalculateFaceAreas( mapOptions.fTargetConcave );
927 dTotalAreaOutput = dTotalAreaOutput_loc;
930 MPI_Reduce( &dTotalAreaOutput_loc, &dTotalAreaOutput, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
932 if( is_root )
dbgprint.printf( 0,
"Output Mesh Geometric Area: %1.15e\n", dTotalAreaOutput );
933 rval = m_interface->tag_set_data( areaTag, m_remapper->m_target_entities, m_meshOutput->vecFaceArea );
MB_CHK_ERR( rval );
941 int ixSourceFaceMax = ( -1 );
942 int ixTargetFaceMax = ( -1 );
944 if( m_meshOverlap->vecSourceFaceIx.size() != m_meshOverlap->vecTargetFaceIx.size() )
946 _EXCEPTIONT(
"Invalid overlap mesh:\n"
947 " Possible mesh file corruption?" );
950 for(
unsigned i = 0; i < m_meshOverlap->faces.size(); i++ )
952 if( m_meshOverlap->vecSourceFaceIx[i] + 1 > ixSourceFaceMax )
953 ixSourceFaceMax = m_meshOverlap->vecSourceFaceIx[i] + 1;
955 if( m_meshOverlap->vecTargetFaceIx[i] + 1 > ixTargetFaceMax )
956 ixTargetFaceMax = m_meshOverlap->vecTargetFaceIx[i] + 1;
960 if( m_meshInputCov->faces.size() - ixSourceFaceMax == 0 )
962 if( is_root )
dbgprint.printf( 0,
"Overlap mesh forward correspondence found\n" );
964 else if( m_meshOutput->faces.size() - ixTargetFaceMax == 0 )
966 if( is_root )
dbgprint.printf( 0,
"Overlap mesh reverse correspondence found (reversing)\n" );
969 m_meshOverlap->ExchangeFirstAndSecondMesh();
973 _EXCEPTION4(
"Invalid overlap mesh:\n No correspondence found with input and output meshes "
974 "(%i,%i) vs (%i,%i)",
975 m_meshInputCov->faces.size(), m_meshOutput->faces.size(), ixSourceFaceMax,
981 if( is_root )
dbgprint.printf( 0,
"Calculating overlap mesh Face areas\n" );
982 double dTotalAreaOverlap_loc = m_meshOverlap->CalculateFaceAreas(
false );
983 double dTotalAreaOverlap = dTotalAreaOverlap_loc;
986 MPI_Reduce( &dTotalAreaOverlap_loc, &dTotalAreaOverlap, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
988 if( is_root )
dbgprint.printf( 0,
"Overlap Mesh Area: %1.15e\n", dTotalAreaOverlap );
993 if( is_root )
dbgprint.printf( 0,
"Correcting source/target areas to overlap mesh areas\n" );
994 DataArray1D< double > dSourceArea( m_meshInputCov->faces.size() );
995 DataArray1D< double > dTargetArea( m_meshOutput->faces.size() );
997 assert( m_meshOverlap->vecSourceFaceIx.size() == m_meshOverlap->faces.size() );
998 assert( m_meshOverlap->vecTargetFaceIx.size() == m_meshOverlap->faces.size() );
999 assert( m_meshOverlap->vecFaceArea.GetRows() == m_meshOverlap->faces.size() );
1001 assert( m_meshInputCov->vecFaceArea.GetRows() == m_meshInputCov->faces.size() );
1002 assert( m_meshOutput->vecFaceArea.GetRows() == m_meshOutput->faces.size() );
1004 for(
size_t i = 0; i < m_meshOverlap->faces.size(); i++ )
1006 if( m_meshOverlap->vecSourceFaceIx[i] < 0 || m_meshOverlap->vecTargetFaceIx[i] < 0 )
1010 assert(
static_cast< size_t >( m_meshOverlap->vecSourceFaceIx[i] ) < m_meshInputCov->faces.size() );
1011 dSourceArea[m_meshOverlap->vecSourceFaceIx[i]] += m_meshOverlap->vecFaceArea[i];
1012 assert(
static_cast< size_t >( m_meshOverlap->vecTargetFaceIx[i] ) < m_meshOutput->faces.size() );
1013 dTargetArea[m_meshOverlap->vecTargetFaceIx[i]] += m_meshOverlap->vecFaceArea[i];
1016 for(
size_t i = 0; i < m_meshInputCov->faces.size(); i++ )
1018 if( fabs( dSourceArea[i] - m_meshInputCov->vecFaceArea[i] ) < 1.0e-10 )
1020 m_meshInputCov->vecFaceArea[i] = dSourceArea[i];
1023 for(
size_t i = 0; i < m_meshOutput->faces.size(); i++ )
1025 if( fabs( dTargetArea[i] - m_meshOutput->vecFaceArea[i] ) < 1.0e-10 )
1027 m_meshOutput->vecFaceArea[i] = dTargetArea[i];
1033 if( !m_bPointCloudSource && eInputType == DiscretizationType_FV )
1035 this->SetSourceAreas( m_meshInputCov->vecFaceArea );
1036 if( m_meshInputCov->vecMask.size() )
1038 this->SetSourceMask( m_meshInputCov->vecMask );
1043 if( !m_bPointCloudTarget && eOutputType == DiscretizationType_FV )
1045 this->SetTargetAreas( m_meshOutput->vecFaceArea );
1046 if( m_meshOutput->vecMask.size() )
1048 this->SetTargetMask( m_meshOutput->vecMask );
1063 this->m_pmeshSource = m_meshInputCov;
1064 this->m_pmeshOverlap = m_meshOverlap;
1067 if( ( eInputType == DiscretizationType_FV ) && ( eOutputType == DiscretizationType_FV ) )
1070 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray();
1071 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap(
false );
1074 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov );
1075 this->InitializeTargetCoordinatesFromMeshFV( *m_meshOutput );
1077 this->m_pdataGLLNodesIn =
nullptr;
1078 this->m_pdataGLLNodesOut =
nullptr;
1081 rval = this->SetDOFmapAssociation( eInputType, mapOptions.nPin,
false,
nullptr,
nullptr, eOutputType,
1082 mapOptions.nPout,
false,
nullptr );
MB_CHK_ERR( rval );
1085 if( is_root )
dbgprint.printf( 0,
"Calculating remap weights\n" );
1088 if( strMapAlgorithm ==
"invdist" )
1090 if( is_root )
dbgprint.printf( 0,
"Calculating map (invdist)\n" );
1091 if( m_meshInputCov->faces.size() )
1092 LinearRemapFVtoFVInvDist( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *
this );
1094 else if( strMapAlgorithm ==
"delaunay" )
1096 if( is_root )
dbgprint.printf( 0,
"Calculating map (delaunay)\n" );
1097 if( m_meshInputCov->faces.size() )
1098 LinearRemapTriangulation( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *
this );
1100 else if( strMapAlgorithm ==
"fvintbilin" )
1102 if( is_root )
dbgprint.printf( 0,
"Calculating map (intbilin)\n" );
1103 if( m_meshInputCov->faces.size() )
1104 LinearRemapIntegratedBilinear( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *
this );
1106 else if( strMapAlgorithm ==
"fvintbilingb" )
1108 if( is_root )
dbgprint.printf( 0,
"Calculating map (intbilingb)\n" );
1109 if( m_meshInputCov->faces.size() )
1110 LinearRemapIntegratedGeneralizedBarycentric( *m_meshInputCov, *m_meshOutput, *m_meshOverlap,
1113 else if( strMapAlgorithm ==
"fvbilin" )
1118 m_meshInputCov->Write(
"SourceMeshMBTR.g" );
1119 m_meshOutput->Write(
"TargetMeshMBTR.g" );
1123 m_meshInputCov->Write(
"SourceMeshMBTR" + std::to_string( rank ) +
".g" );
1124 m_meshOutput->Write(
"TargetMeshMBTR" + std::to_string( rank ) +
".g" );
1127 if( is_root )
dbgprint.printf( 0,
"Calculating map (bilin)\n" );
1128 if( m_meshInputCov->faces.size() )
1129 LinearRemapBilinear( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, *
this );
1133 if( is_root )
dbgprint.printf( 0,
"Calculating conservative FV-FV map\n" );
1134 if( m_meshInputCov->faces.size() )
1136 #ifdef USE_NATIVE_TEMPESTREMAP_ROUTINES
1137 LinearRemapFVtoFV( *m_meshInputCov, *m_meshOutput, *m_meshOverlap,
1138 ( mapOptions.fMonotone ) ? ( 1 ) : ( mapOptions.nPin ), *
this );
1140 LinearRemapFVtoFV_Tempest_MOAB( ( mapOptions.fMonotone ? 1 : mapOptions.nPin ) );
1145 else if( eInputType == DiscretizationType_FV )
1147 DataArray3D< double > dataGLLJacobian;
1149 if( is_root )
dbgprint.printf( 0,
"Generating output mesh meta data\n" );
1150 double dNumericalArea_loc = GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble,
1151 dataGLLNodesDest, dataGLLJacobian );
1153 double dNumericalArea = dNumericalArea_loc;
1154 #ifdef MOAB_HAVE_MPI
1156 MPI_Reduce( &dNumericalArea_loc, &dNumericalArea, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
1158 if( is_root )
dbgprint.printf( 0,
"Output Mesh Numerical Area: %1.15e\n", dNumericalArea );
1161 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov );
1162 this->InitializeTargetCoordinatesFromMeshFE( *m_meshOutput, mapOptions.nPout, dataGLLNodesDest );
1164 this->m_pdataGLLNodesIn =
nullptr;
1165 this->m_pdataGLLNodesOut = &dataGLLNodesDest;
1168 bool fContinuous = ( eOutputType == DiscretizationType_CGLL );
1170 if( eOutputType == DiscretizationType_CGLL )
1172 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobian, this->GetTargetAreas() );
1176 GenerateDiscontinuousJacobian( dataGLLJacobian, this->GetTargetAreas() );
1180 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray();
1181 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap(
false );
1184 rval = this->SetDOFmapAssociation( eInputType, mapOptions.nPin,
false,
nullptr,
nullptr, eOutputType,
1185 mapOptions.nPout, ( eOutputType == DiscretizationType_CGLL ),
1189 if( strMapAlgorithm ==
"volumetric" )
1191 if( is_root )
dbgprint.printf( 0,
"Calculating remapping weights for FV->GLL (volumetric)\n" );
1192 LinearRemapFVtoGLL_Volumetric( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesDest,
1193 dataGLLJacobian, this->GetTargetAreas(), mapOptions.nPin, *
this,
1194 nMonotoneType, fContinuous, mapOptions.fNoConservation );
1198 if( is_root )
dbgprint.printf( 0,
"Calculating remapping weights for FV->GLL\n" );
1199 LinearRemapFVtoGLL( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesDest, dataGLLJacobian,
1200 this->GetTargetAreas(), mapOptions.nPin, *
this, nMonotoneType, fContinuous,
1201 mapOptions.fNoConservation );
1204 else if( ( eInputType == DiscretizationType_PCLOUD ) || ( eOutputType == DiscretizationType_PCLOUD ) )
1206 DataArray3D< double > dataGLLJacobian;
1207 if( !m_bPointCloudSource )
1210 if( m_meshInputCov->revnodearray.size() == 0 ) m_meshInputCov->ConstructReverseNodeArray();
1211 if( m_meshInputCov->edgemap.size() == 0 ) m_meshInputCov->ConstructEdgeMap(
false );
1214 if( eInputType == DiscretizationType_FV )
1216 this->InitializeSourceCoordinatesFromMeshFV( *m_meshInputCov );
1220 if( is_root )
dbgprint.printf( 0,
"Generating input mesh meta data\n" );
1221 DataArray3D< double > dataGLLJacobianSrc;
1222 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov,
1224 GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrc,
1225 dataGLLJacobianSrc );
1230 if( !m_bPointCloudTarget )
1233 if( m_meshOutput->revnodearray.size() == 0 ) m_meshOutput->ConstructReverseNodeArray();
1234 if( m_meshOutput->edgemap.size() == 0 ) m_meshOutput->ConstructEdgeMap(
false );
1237 if( eOutputType == DiscretizationType_FV )
1239 this->InitializeSourceCoordinatesFromMeshFV( *m_meshOutput );
1243 if( is_root )
dbgprint.printf( 0,
"Generating output mesh meta data\n" );
1244 GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble, dataGLLNodesDest,
1251 rval = this->SetDOFmapAssociation(
1252 eInputType, mapOptions.nPin, ( eInputType == DiscretizationType_CGLL ),
1253 ( m_bPointCloudSource || eInputType == DiscretizationType_FV ?
nullptr : &dataGLLNodesSrcCov ),
1254 ( m_bPointCloudSource || eInputType == DiscretizationType_FV ?
nullptr : &dataGLLNodesSrc ),
1255 eOutputType, mapOptions.nPout, ( eOutputType == DiscretizationType_CGLL ),
1256 ( m_bPointCloudTarget ?
nullptr : &dataGLLNodesDest ) );
MB_CHK_ERR( rval );
1259 if( is_root )
dbgprint.printf( 0,
"Calculating remap weights with Nearest-Neighbor method\n" );
1260 rval = LinearRemapNN_MOAB(
true ,
false );
MB_CHK_ERR( rval );
1262 else if( ( eInputType != DiscretizationType_FV ) && ( eOutputType == DiscretizationType_FV ) )
1264 DataArray3D< double > dataGLLJacobianSrc, dataGLLJacobian;
1266 if( is_root )
dbgprint.printf( 0,
"Generating input mesh meta data\n" );
1268 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov,
1271 double dNumericalArea_loc = GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble,
1272 dataGLLNodesSrc, dataGLLJacobianSrc );
1278 double dNumericalArea = dNumericalArea_loc;
1279 #ifdef MOAB_HAVE_MPI
1281 MPI_Reduce( &dNumericalArea_loc, &dNumericalArea, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
1285 dbgprint.printf( 0,
"Input Mesh Numerical Area: %1.15e\n", dNumericalArea );
1287 if( fabs( dNumericalArea - dTotalAreaInput ) > 1.0e-12 )
1289 dbgprint.printf( 0,
"WARNING: Significant mismatch between input mesh "
1290 "numerical area and geometric area\n" );
1294 if( dataGLLNodesSrcCov.GetSubColumns() != m_meshInputCov->faces.size() )
1296 _EXCEPTIONT(
"Number of element does not match between metadata and "
1301 this->InitializeSourceCoordinatesFromMeshFE( *m_meshInputCov, mapOptions.nPin, dataGLLNodesSrcCov );
1302 this->InitializeTargetCoordinatesFromMeshFV( *m_meshOutput );
1305 bool fContinuousIn = ( eInputType == DiscretizationType_CGLL );
1307 if( eInputType == DiscretizationType_CGLL )
1309 GenerateUniqueJacobian( dataGLLNodesSrcCov, dataGLLJacobian, this->GetSourceAreas() );
1313 GenerateDiscontinuousJacobian( dataGLLJacobian, this->GetSourceAreas() );
1317 rval = this->SetDOFmapAssociation( eInputType, mapOptions.nPin, ( eInputType == DiscretizationType_CGLL ),
1318 &dataGLLNodesSrcCov, &dataGLLNodesSrc, eOutputType, mapOptions.nPout,
1322 if( is_root )
dbgprint.printf( 0,
"Calculating remap weights\n" );
1324 if( strMapAlgorithm ==
"volumetric" )
1326 _EXCEPTIONT(
"Unimplemented: Volumetric currently unavailable for"
1330 this->m_pdataGLLNodesIn = &dataGLLNodesSrcCov;
1331 this->m_pdataGLLNodesOut =
nullptr;
1333 #ifdef USE_NATIVE_TEMPESTREMAP_ROUTINES
1334 LinearRemapSE4( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesSrcCov, dataGLLJacobian,
1335 nMonotoneType, fContinuousIn, mapOptions.fNoConservation, mapOptions.fSparseConstraints,
1338 LinearRemapSE4_Tempest_MOAB( dataGLLNodesSrcCov, dataGLLJacobian, nMonotoneType, fContinuousIn,
1339 mapOptions.fNoConservation );
1342 else if( ( eInputType != DiscretizationType_FV ) && ( eOutputType != DiscretizationType_FV ) )
1344 DataArray3D< double > dataGLLJacobianIn, dataGLLJacobianSrc;
1345 DataArray3D< double > dataGLLJacobianOut;
1348 if( is_root )
dbgprint.printf( 0,
"Generating input mesh meta data\n" );
1349 GenerateMetaData( *m_meshInputCov, mapOptions.nPin, mapOptions.fNoBubble, dataGLLNodesSrcCov,
1350 dataGLLJacobianIn );
1352 double dNumericalAreaSrc_loc = GenerateMetaData( *m_meshInput, mapOptions.nPin, mapOptions.fNoBubble,
1353 dataGLLNodesSrc, dataGLLJacobianSrc );
1354 double dNumericalAreaIn = dNumericalAreaSrc_loc;
1355 #ifdef MOAB_HAVE_MPI
1357 MPI_Reduce( &dNumericalAreaSrc_loc, &dNumericalAreaIn, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
1361 dbgprint.printf( 0,
"Input Mesh Numerical Area: %1.15e\n", dNumericalAreaIn );
1363 if( fabs( dNumericalAreaIn - dTotalAreaInput ) > 1.0e-12 )
1365 dbgprint.printf( 0,
"WARNING: Significant mismatch between input mesh "
1366 "numerical area and geometric area\n" );
1371 if( is_root )
dbgprint.printf( 0,
"Generating output mesh meta data\n" );
1372 double dNumericalAreaOut_loc = GenerateMetaData( *m_meshOutput, mapOptions.nPout, mapOptions.fNoBubble,
1373 dataGLLNodesDest, dataGLLJacobianOut );
1374 double dNumericalAreaOut = dNumericalAreaOut_loc;
1375 #ifdef MOAB_HAVE_MPI
1377 MPI_Reduce( &dNumericalAreaOut_loc, &dNumericalAreaOut, 1, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
1381 dbgprint.printf( 0,
"Output Mesh Numerical Area: %1.15e\n", dNumericalAreaOut );
1383 if( fabs( dNumericalAreaOut - dTotalAreaOutput ) > 1.0e-12 )
1386 dbgprint.printf( 0,
"WARNING: Significant mismatch between output mesh "
1387 "numerical area and geometric area\n" );
1392 this->InitializeSourceCoordinatesFromMeshFE( *m_meshInputCov, mapOptions.nPin, dataGLLNodesSrcCov );
1393 this->InitializeTargetCoordinatesFromMeshFE( *m_meshOutput, mapOptions.nPout, dataGLLNodesDest );
1396 bool fContinuousIn = ( eInputType == DiscretizationType_CGLL );
1398 if( eInputType == DiscretizationType_CGLL )
1400 GenerateUniqueJacobian( dataGLLNodesSrcCov, dataGLLJacobianIn, this->GetSourceAreas() );
1404 GenerateDiscontinuousJacobian( dataGLLJacobianIn, this->GetSourceAreas() );
1408 bool fContinuousOut = ( eOutputType == DiscretizationType_CGLL );
1410 if( eOutputType == DiscretizationType_CGLL )
1412 GenerateUniqueJacobian( dataGLLNodesDest, dataGLLJacobianOut, this->GetTargetAreas() );
1416 GenerateDiscontinuousJacobian( dataGLLJacobianOut, this->GetTargetAreas() );
1420 rval = this->SetDOFmapAssociation( eInputType, mapOptions.nPin, ( eInputType == DiscretizationType_CGLL ),
1421 &dataGLLNodesSrcCov, &dataGLLNodesSrc, eOutputType, mapOptions.nPout,
1422 ( eOutputType == DiscretizationType_CGLL ), &dataGLLNodesDest );
MB_CHK_ERR( rval );
1424 this->m_pdataGLLNodesIn = &dataGLLNodesSrcCov;
1425 this->m_pdataGLLNodesOut = &dataGLLNodesDest;
1428 if( is_root )
dbgprint.printf( 0,
"Calculating remap weights\n" );
1430 #ifdef USE_NATIVE_TEMPESTREMAP_ROUTINES
1431 LinearRemapGLLtoGLL_Integrated( *m_meshInputCov, *m_meshOutput, *m_meshOverlap, dataGLLNodesSrcCov,
1432 dataGLLJacobianIn, dataGLLNodesDest, dataGLLJacobianOut,
1433 this->GetTargetAreas(), mapOptions.nPin, mapOptions.nPout, nMonotoneType,
1434 fContinuousIn, fContinuousOut, mapOptions.fSparseConstraints, *
this );
1436 LinearRemapGLLtoGLL2_MOAB( dataGLLNodesSrcCov, dataGLLJacobianIn, dataGLLNodesDest, dataGLLJacobianOut,
1437 this->GetTargetAreas(), mapOptions.nPin, mapOptions.nPout, nMonotoneType,
1438 fContinuousIn, fContinuousOut, mapOptions.fNoConservation );
1443 _EXCEPTIONT(
"Not implemented" );
1446 #ifdef MOAB_HAVE_EIGEN3
1447 copy_tempest_sparsemat_to_eigen3();
1450 #ifdef MOAB_HAVE_MPI
1454 rval = m_remapper->GetOverlapAugmentedEntities( ghostedEnts );
MB_CHK_ERR( rval );
1456 rval = m_interface->remove_entities( m_meshOverlapSet, ghostedEnts );
MB_CHK_SET_ERR( rval,
"Deleting ghosted entities failed" );
1460 if( !mapOptions.fNoCheck )
1462 if( is_root )
dbgprint.printf( 0,
"Verifying map" );
1463 this->IsConsistent( 1.0e-8 );
1464 if( !mapOptions.fNoConservation ) this->IsConservative( 1.0e-8 );
1466 if( nMonotoneType != 0 )
1468 this->IsMonotone( 1.0e-12 );
1472 catch( Exception& e )
1474 dbgprint.printf( 0,
"%s", e.ToString().c_str() );
1475 return ( moab::MB_FAILURE );
1479 return ( moab::MB_FAILURE );
1488 #ifndef MOAB_HAVE_MPI
1490 return OfflineMap::IsConsistent( dTolerance );
1495 DataArray1D< int > dataRows;
1496 DataArray1D< int > dataCols;
1497 DataArray1D< double > dataEntries;
1500 DataArray1D< double > dRowSums;
1501 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries );
1502 dRowSums.Allocate( m_mapRemap.GetRows() );
1504 for(
unsigned i = 0; i < dataRows.GetRows(); i++ )
1506 dRowSums[dataRows[i]] += dataEntries[i];
1510 int fConsistent = 0;
1511 for(
unsigned i = 0; i < dRowSums.GetRows(); i++ )
1513 if( fabs( dRowSums[i] - 1.0 ) > dTolerance )
1516 int rowGID = row_gdofmap[i];
1517 Announce(
"TempestOnlineMap is not consistent in row %i (%1.15e)", rowGID, dRowSums[i] );
1522 int fConsistentGlobal = 0;
1523 ierr = MPI_Allreduce( &fConsistent, &fConsistentGlobal, 1, MPI_INT, MPI_SUM, m_pcomm->comm() );
1524 if( ierr != MPI_SUCCESS )
return -1;
1526 return fConsistentGlobal;
1534 #ifndef MOAB_HAVE_MPI
1536 return OfflineMap::IsConservative( dTolerance );
1543 DataArray1D< int > dataRows;
1544 DataArray1D< int > dataCols;
1545 DataArray1D< double > dataEntries;
1546 const DataArray1D< double >& dTargetAreas = this->GetTargetAreas();
1547 const DataArray1D< double >& dSourceAreas = this->GetSourceAreas();
1550 std::vector< int > dColumnsUnique;
1551 std::vector< double > dColumnSums;
1553 int nColumns = m_mapRemap.GetColumns();
1554 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries );
1555 dColumnSums.resize( m_nTotDofs_SrcCov, 0.0 );
1556 dColumnsUnique.resize( m_nTotDofs_SrcCov, -1 );
1558 for(
unsigned i = 0; i < dataEntries.GetRows(); i++ )
1560 dColumnSums[dataCols[i]] += dataEntries[i] * dTargetAreas[dataRows[i]] / dSourceAreas[dataCols[i]];
1562 assert( dataCols[i] < m_nTotDofs_SrcCov );
1565 int colGID = this->GetColGlobalDoF( dataCols[i] );
1567 dColumnsUnique[dataCols[i]] = colGID;
1574 std::vector< int > nElementsInProc;
1575 const int nDATA = 3;
1576 nElementsInProc.resize(
size * nDATA );
1577 int senddata[nDATA] = { nColumns, m_nTotDofs_SrcCov, m_nTotDofs_Src };
1578 ierr = MPI_Gather( senddata, nDATA, MPI_INT, nElementsInProc.data(), nDATA, MPI_INT, rootProc, m_pcomm->comm() );
1579 if( ierr != MPI_SUCCESS )
return -1;
1581 int nTotVals = 0, nTotColumns = 0, nTotColumnsUnq = 0;
1582 std::vector< int > dColumnIndices;
1583 std::vector< double > dColumnSourceAreas;
1584 std::vector< double > dColumnSumsTotal;
1585 std::vector< int > displs, rcount;
1586 if( rank == rootProc )
1588 displs.resize(
size + 1, 0 );
1589 rcount.resize(
size, 0 );
1591 for(
int ir = 0; ir <
size; ++ir )
1593 nTotVals += nElementsInProc[ir * nDATA];
1594 nTotColumns += nElementsInProc[ir * nDATA + 1];
1595 nTotColumnsUnq += nElementsInProc[ir * nDATA + 2];
1598 rcount[ir] = nElementsInProc[ir * nDATA + 1];
1604 printf(
"Total nnz: %d, global source elements = %d\n", nTotVals, gsum );
1606 dColumnIndices.resize( nTotColumns, -1 );
1607 dColumnSumsTotal.resize( nTotColumns, 0.0 );
1616 ierr = MPI_Gatherv( &dColumnsUnique[0], m_nTotDofs_SrcCov, MPI_INT, &dColumnIndices[0], rcount.data(),
1617 displs.data(), MPI_INT, rootProc, m_pcomm->comm() );
1618 if( ierr != MPI_SUCCESS )
return -1;
1619 ierr = MPI_Gatherv( &dColumnSums[0], m_nTotDofs_SrcCov, MPI_DOUBLE, &dColumnSumsTotal[0], rcount.data(),
1620 displs.data(), MPI_DOUBLE, rootProc, m_pcomm->comm() );
1621 if( ierr != MPI_SUCCESS )
return -1;
1627 dColumnSums.clear();
1628 dColumnsUnique.clear();
1631 int fConservative = 0;
1632 if( rank == rootProc )
1634 displs[
size] = ( nTotColumns );
1636 std::map< int, double > dColumnSumsOnRoot;
1638 for(
int ir = 0; ir <
size; ir++ )
1640 for(
int ips = displs[ir]; ips < displs[ir + 1]; ips++ )
1642 if( dColumnIndices[ips] < 0 )
continue;
1644 assert( dColumnIndices[ips] < nTotColumnsUnq );
1645 dColumnSumsOnRoot[dColumnIndices[ips]] += dColumnSumsTotal[ips];
1651 for( std::map< int, double >::iterator it = dColumnSumsOnRoot.begin(); it != dColumnSumsOnRoot.end(); ++it )
1654 if( fabs( it->second - 1.0 ) > dTolerance )
1657 Announce(
"TempestOnlineMap is not conservative in column "
1660 it->first, it->second );
1666 ierr = MPI_Bcast( &fConservative, 1, MPI_INT, rootProc, m_pcomm->comm() );
1667 if( ierr != MPI_SUCCESS )
return -1;
1669 return fConservative;
1677 #ifndef MOAB_HAVE_MPI
1679 return OfflineMap::IsMonotone( dTolerance );
1684 DataArray1D< int > dataRows;
1685 DataArray1D< int > dataCols;
1686 DataArray1D< double > dataEntries;
1688 m_mapRemap.GetEntries( dataRows, dataCols, dataEntries );
1692 for(
unsigned i = 0; i < dataRows.GetRows(); i++ )
1694 if( ( dataEntries[i] < -dTolerance ) || ( dataEntries[i] > 1.0 + dTolerance ) )
1698 Announce(
"TempestOnlineMap is not monotone in entry (%i): %1.15e", i, dataEntries[i] );
1703 int fMonotoneGlobal = 0;
1704 ierr = MPI_Allreduce( &fMonotone, &fMonotoneGlobal, 1, MPI_INT, MPI_SUM, m_pcomm->comm() );
1705 if( ierr != MPI_SUCCESS )
return -1;
1707 return fMonotoneGlobal;
1716 bool useMOABAdjacencies,
1719 assert( nrings > 0 );
1720 assert( useMOABAdjacencies || trMesh !=
nullptr );
1722 const size_t nrows = vecAdjFaces.size();
1724 for(
size_t index = 0; index < nrows; index++ )
1726 vecAdjFaces[index].insert( index );
1729 if( useMOABAdjacencies )
1739 int adjIndex =
entities.index( *it );
1741 if( adjIndex >= 0 ) vecAdjFaces[index].insert( adjIndex );
1750 Face&
face = trMesh->faces[index];
1751 GetAdjacentFaceVectorByEdge( *trMesh, index, nrings *
face.edges.size(), adjFaces );
1754 for(
auto adjFace : adjFaces )
1755 if( adjFace.first >= 0 )
1756 vecAdjFaces[index].insert( adjFace.first );
1766 double default_projection )
1770 std::vector< double > solSTagVals;
1771 std::vector< double > solTTagVals;
1774 if( m_remapper->point_cloud_source || m_remapper->point_cloud_target )
1776 if( m_remapper->point_cloud_source )
1779 solSTagVals.resize( covSrcEnts.
size(), default_projection );
1785 solSTagVals.resize( covSrcEnts.
size() * this->GetSourceNDofsPerElement() * this->GetSourceNDofsPerElement(),
1786 default_projection );
1789 if( m_remapper->point_cloud_target )
1792 solTTagVals.resize( tgtEnts.
size(), default_projection );
1798 solTTagVals.resize( tgtEnts.
size() * this->GetDestinationNDofsPerElement() *
1799 this->GetDestinationNDofsPerElement(),
1800 default_projection );
1808 solSTagVals.resize( covSrcEnts.
size() * this->GetSourceNDofsPerElement() * this->GetSourceNDofsPerElement(),
1809 default_projection );
1810 solTTagVals.resize( tgtEnts.
size() * this->GetDestinationNDofsPerElement() *
1811 this->GetDestinationNDofsPerElement(),
1812 default_projection );
1819 rval = m_interface->tag_get_data( srcSolutionTag, sents, &solSTagVals[0] );
MB_CHK_SET_ERR( rval,
"Getting local tag data failed" );
1824 rval = this->ApplyWeights( solSTagVals, solTTagVals, transpose );
MB_CHK_SET_ERR( rval,
"Applying remap operator onto source vector data failed" );
1826 if( caasType != CAAS_NONE )
1828 std::string tgtSolutionTagName;
1829 rval = m_interface->tag_get_name( tgtSolutionTag, tgtSolutionTagName );
MB_CHK_SET_ERR( rval,
"Getting tag name failed" );
1832 constexpr
int nmax_caas_iterations = 10;
1833 double mismatch = 1.0;
1834 int caasIteration = 0;
1835 double initialMismatch = 0.0;
1836 while( ( fabs( mismatch / initialMismatch ) > 1e-15 && fabs( mismatch ) > 1e-15 ) &&
1837 caasIteration++ < nmax_caas_iterations )
1840 rval = m_interface->tag_set_data( tgtSolutionTag, tents, &solTTagVals[0] );
MB_CHK_SET_ERR( rval,
"Setting local tag data failed" );
1842 double dMassDiffPostGlobal;
1843 std::pair< double, double > mDefect =
1844 this->ApplyBoundsLimiting( solSTagVals, solTTagVals, caasType, caasIteration, mismatch );
1845 #ifdef MOAB_HAVE_MPI
1846 double dMassDiffPost = mDefect.second;
1847 MPI_Allreduce( &dMassDiffPost, &dMassDiffPostGlobal, 1, MPI_DOUBLE, MPI_SUM, m_pcomm->comm() );
1849 dMassDiffPostGlobal = mDefect.second;
1851 if( caasIteration == 1 ) initialMismatch = mDefect.first;
1852 if( m_remapper->verbose && is_root )
1854 printf(
"Field {%s} -> CAAS iteration: %d, mass defect: %3.4e, post-CAAS: %3.4e\n",
1855 tgtSolutionTagName.c_str(), caasIteration, mDefect.first, dMassDiffPostGlobal );
1857 mismatch = dMassDiffPostGlobal;
1862 rval = m_interface->tag_set_data( tgtSolutionTag, tents, &solTTagVals[0] );
MB_CHK_SET_ERR( rval,
"Setting local tag data failed" );
1868 const std::string& solnName,
1870 sample_function testFunction,
1872 std::string cloneSolnName )
1875 const bool outputEnabled = ( is_root );
1885 trmesh = m_remapper->m_covering_source;
1886 entities = ( m_remapper->point_cloud_source ? m_remapper->m_covering_source_vertices
1887 : m_remapper->m_covering_source_entities );
1888 discOrder = m_nDofsPEl_Src;
1889 discMethod = m_eInputType;
1894 trmesh = m_remapper->m_target;
1896 ( m_remapper->point_cloud_target ? m_remapper->m_target_vertices : m_remapper->m_target_entities );
1897 discOrder = m_nDofsPEl_Dest;
1898 discMethod = m_eOutputType;
1903 std::cout <<
"Invalid context specified for defining an analytical solution tag" << std::endl;
1904 return moab::MB_FAILURE;
1909 rval = m_interface->tag_get_handle( solnName.c_str(), discOrder * discOrder,
MB_TYPE_DOUBLE, solnTag,
1911 if( clonedSolnTag !=
nullptr )
1913 if( cloneSolnName.size() == 0 )
1915 cloneSolnName = solnName + std::string(
"Cloned" );
1917 rval = m_interface->tag_get_handle( cloneSolnName.c_str(), discOrder * discOrder,
MB_TYPE_DOUBLE,
1922 const int TriQuadratureOrder = 10;
1924 if( outputEnabled ) std::cout <<
"Using triangular quadrature of order " << TriQuadratureOrder << std::endl;
1926 TriangularQuadratureRule triquadrule( TriQuadratureOrder );
1928 const int TriQuadraturePoints = triquadrule.GetPoints();
1930 const DataArray2D< double >& TriQuadratureG = triquadrule.GetG();
1931 const DataArray1D< double >& TriQuadratureW = triquadrule.GetW();
1934 DataArray1D< double > dVar;
1935 DataArray1D< double > dVarMB;
1938 DataArray1D< double > dNodeArea;
1943 if( discMethod == DiscretizationType_CGLL || discMethod == DiscretizationType_DGLL )
1946 const bool fGLL =
true;
1947 const bool fGLLIntegrate =
false;
1950 DataArray3D< int > dataGLLNodes;
1951 DataArray3D< double > dataGLLJacobian;
1953 GenerateMetaData( *trmesh, discOrder,
false, dataGLLNodes, dataGLLJacobian );
1956 int nElements = trmesh->faces.size();
1959 for(
int k = 0; k < nElements; k++ )
1961 const Face&
face = trmesh->faces[k];
1963 if(
face.edges.size() != 4 )
1965 _EXCEPTIONT(
"Non-quadrilateral face detected; "
1966 "incompatible with --gll" );
1972 for(
int i = 0; i < discOrder; i++ )
1974 for(
int j = 0; j < discOrder; j++ )
1976 for(
int k = 0; k < nElements; k++ )
1978 if( dataGLLNodes[i][j][k] > iMaxNode )
1980 iMaxNode = dataGLLNodes[i][j][k];
1987 DataArray1D< double > dG;
1988 DataArray1D< double > dW;
1990 GaussLobattoQuadrature::GetPoints( discOrder, 0.0, 1.0, dG, dW );
1993 const int nGaussP = 10;
1995 DataArray1D< double > dGaussG;
1996 DataArray1D< double > dGaussW;
1998 GaussQuadrature::GetPoints( nGaussP, 0.0, 1.0, dGaussG, dGaussW );
2001 dVar.Allocate( iMaxNode );
2002 dVarMB.Allocate( discOrder * discOrder * nElements );
2003 dNodeArea.Allocate( iMaxNode );
2006 for(
int k = 0; k < nElements; k++ )
2008 const Face&
face = trmesh->faces[k];
2013 for(
int i = 0; i < discOrder; i++ )
2015 for(
int j = 0; j < discOrder; j++ )
2023 ApplyLocalMap(
face, trmesh->nodes, dG[i], dG[j], node, dDx1G, dDx2G );
2026 double dNodeLon = atan2( node.y, node.x );
2027 if( dNodeLon < 0.0 )
2029 dNodeLon += 2.0 * M_PI;
2031 double dNodeLat = asin( node.z );
2033 double dSample = ( *testFunction )( dNodeLon, dNodeLat );
2035 dVar[dataGLLNodes[j][i][k] - 1] = dSample;
2042 DataArray2D< double > dCoeff( discOrder, discOrder );
2044 for(
int p = 0; p < nGaussP; p++ )
2046 for(
int q = 0; q < nGaussP; q++ )
2054 ApplyLocalMap(
face, trmesh->nodes, dGaussG[p], dGaussG[q], node, dDx1G, dDx2G );
2057 Node nodeCross = CrossProduct( dDx1G, dDx2G );
2060 sqrt( nodeCross.x * nodeCross.x + nodeCross.y * nodeCross.y + nodeCross.z * nodeCross.z );
2064 SampleGLLFiniteElement( 0, discOrder, dGaussG[p], dGaussG[q], dCoeff );
2067 double dNodeLon = atan2( node.y, node.x );
2068 if( dNodeLon < 0.0 )
2070 dNodeLon += 2.0 * M_PI;
2072 double dNodeLat = asin( node.z );
2074 double dSample = ( *testFunction )( dNodeLon, dNodeLat );
2077 for(
int i = 0; i < discOrder; i++ )
2079 for(
int j = 0; j < discOrder; j++ )
2082 double dNodalArea = dCoeff[i][j] * dGaussW[p] * dGaussW[q] * dJacobian;
2084 dVar[dataGLLNodes[i][j][k] - 1] += dSample * dNodalArea;
2086 dNodeArea[dataGLLNodes[i][j][k] - 1] += dNodalArea;
2097 for(
size_t i = 0; i < dVar.GetRows(); i++ )
2099 dVar[i] /= dNodeArea[i];
2106 for(
unsigned j = 0; j <
entities.size(); j++ )
2107 for(
int p = 0; p < discOrder; p++ )
2108 for(
int q = 0; q < discOrder; q++ )
2110 const int offsetDOF = j * discOrder * discOrder + p * discOrder + q;
2111 dVarMB[offsetDOF] = dVar[col_dtoc_dofmap[offsetDOF]];
2116 for(
unsigned j = 0; j <
entities.size(); j++ )
2117 for(
int p = 0; p < discOrder; p++ )
2118 for(
int q = 0; q < discOrder; q++ )
2120 const int offsetDOF = j * discOrder * discOrder + p * discOrder + q;
2121 dVarMB[offsetDOF] = dVar[row_dtoc_dofmap[offsetDOF]];
2126 rval = m_interface->tag_set_data( solnTag,
entities, &dVarMB[0] );
MB_CHK_ERR( rval );
2131 if( discMethod == DiscretizationType_FV )
2136 dVar.Allocate( trmesh->faces.size() );
2138 std::vector< Node >& nodes = trmesh->nodes;
2141 for(
size_t i = 0; i < trmesh->faces.size(); i++ )
2143 const Face&
face = trmesh->faces[i];
2146 for(
size_t j = 0; j <
face.edges.size() - 2; j++ )
2149 const Node& node0 = nodes[
face[0]];
2150 const Node& node1 = nodes[
face[j + 1]];
2151 const Node& node2 = nodes[
face[j + 2]];
2155 faceTri.SetNode( 0,
face[0] );
2156 faceTri.SetNode( 1,
face[j + 1] );
2157 faceTri.SetNode( 2,
face[j + 2] );
2159 double dTriangleArea = CalculateFaceArea( faceTri, nodes );
2162 double dTotalSample = 0.0;
2165 for(
int k = 0; k < TriQuadraturePoints; k++ )
2167 Node node( TriQuadratureG[k][0] * node0.x + TriQuadratureG[k][1] * node1.x +
2168 TriQuadratureG[k][2] * node2.x,
2169 TriQuadratureG[k][0] * node0.y + TriQuadratureG[k][1] * node1.y +
2170 TriQuadratureG[k][2] * node2.y,
2171 TriQuadratureG[k][0] * node0.z + TriQuadratureG[k][1] * node1.z +
2172 TriQuadratureG[k][2] * node2.z );
2174 double dMagnitude = node.Magnitude();
2175 node.x /= dMagnitude;
2176 node.y /= dMagnitude;
2177 node.z /= dMagnitude;
2179 double dLon = atan2( node.y, node.x );
2184 double dLat = asin( node.z );
2186 double dSample = ( *testFunction )( dLon, dLat );
2188 dTotalSample += dSample * TriQuadratureW[k] * dTriangleArea;
2191 dVar[i] += dTotalSample / trmesh->vecFaceArea[i];
2199 std::vector< Node >& nodes = trmesh->nodes;
2202 dVar.Allocate( nodes.size() );
2204 for(
size_t j = 0; j < nodes.size(); j++ )
2206 Node& node = nodes[j];
2207 double dMagnitude = node.Magnitude();
2208 node.x /= dMagnitude;
2209 node.y /= dMagnitude;
2210 node.z /= dMagnitude;
2211 double dLon = atan2( node.y, node.x );
2216 double dLat = asin( node.z );
2218 double dSample = ( *testFunction )( dLon, dLat );
2232 std::map< std::string, double >& metrics,
2236 const bool outputEnabled = ( is_root );
2247 entities = ( m_remapper->point_cloud_source ? m_remapper->m_covering_source_vertices
2248 : m_remapper->m_covering_source_entities );
2249 discOrder = m_nDofsPEl_Src;
2257 ( m_remapper->point_cloud_target ? m_remapper->m_target_vertices : m_remapper->m_target_entities );
2258 discOrder = m_nDofsPEl_Dest;
2264 std::cout <<
"Invalid context specified for defining an analytical solution tag" << std::endl;
2265 return moab::MB_FAILURE;
2270 std::string exactTagName, projTagName;
2271 const int ntotsize =
entities.size() * discOrder * discOrder;
2272 std::vector< double > exactSolution( ntotsize, 0.0 ), projSolution( ntotsize, 0.0 );
2273 rval = m_interface->tag_get_name( exactTag, exactTagName );
MB_CHK_ERR( rval );
2274 rval = m_interface->tag_get_data( exactTag,
entities, &exactSolution[0] );
MB_CHK_ERR( rval );
2275 rval = m_interface->tag_get_name( approxTag, projTagName );
MB_CHK_ERR( rval );
2276 rval = m_interface->tag_get_data( approxTag,
entities, &projSolution[0] );
MB_CHK_ERR( rval );
2278 const auto& ovents = m_remapper->m_overlap_entities;
2280 std::vector< double > errnorms( 4, 0.0 ), globerrnorms( 4, 0.0 );
2281 double sumarea = 0.0;
2282 for(
size_t i = 0; i < ovents.size(); ++i )
2284 const int srcidx = m_remapper->m_overlap->vecSourceFaceIx[i];
2285 if( srcidx < 0 )
continue;
2286 const int tgtidx = m_remapper->m_overlap->vecTargetFaceIx[i];
2287 if( tgtidx < 0 )
continue;
2288 const double ovarea = m_remapper->m_overlap->vecFaceArea[i];
2289 const double error = fabs( exactSolution[tgtidx] - projSolution[tgtidx] );
2290 errnorms[0] += ovarea *
error;
2292 errnorms[3] = (
error > errnorms[3] ?
error : errnorms[3] );
2295 errnorms[2] = sumarea;
2296 #ifdef MOAB_HAVE_MPI
2299 MPI_Reduce( &errnorms[0], &globerrnorms[0], 3, MPI_DOUBLE, MPI_SUM, 0, m_pcomm->comm() );
2300 MPI_Reduce( &errnorms[3], &globerrnorms[3], 1, MPI_DOUBLE, MPI_MAX, 0, m_pcomm->comm() );
2303 for(
int i = 0; i < 4; ++i )
2304 globerrnorms[i] = errnorms[i];
2307 globerrnorms[0] = ( globerrnorms[0] / globerrnorms[2] );
2308 globerrnorms[1] = std::sqrt( globerrnorms[1] / globerrnorms[2] );
2311 metrics[
"L1Error"] = globerrnorms[0];
2312 metrics[
"L2Error"] = globerrnorms[1];
2313 metrics[
"LinfError"] = globerrnorms[3];
2317 std::cout <<
"Error metrics when comparing " << projTagName <<
" against " << exactTagName << std::endl;
2318 std::cout <<
"\t Total Intersection area = " << globerrnorms[2] << std::endl;
2319 std::cout <<
"\t L_1 error = " << globerrnorms[0] << std::endl;
2320 std::cout <<
"\t L_2 error = " << globerrnorms[1] << std::endl;
2321 std::cout <<
"\t L_inf error = " << globerrnorms[3] << std::endl;