9 #define _USE_MATH_DEFINES
12 #pragma GCC diagnostic push
13 #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
14 #pragma GCC diagnostic ignored "-Wsign-compare"
17 #include "DataArray3D.h"
18 #include "FiniteElementTools.h"
19 #include "FiniteVolumeTools.h"
20 #include "GaussLobattoQuadrature.h"
21 #include "TriangularQuadrature.h"
22 #include "MathHelper.h"
23 #include "SparseMatrix.h"
24 #include "OverlapMesh.h"
33 #pragma GCC diagnostic pop
41 #include <unordered_set>
44 #define USE_ComputeAdjacencyRelations
64 std::ofstream output_file(
"rowcolindices.txt", std::ios::out );
66 << row_ldofmap.size() <<
" " <<
col_gdofmap.size() <<
" " << col_ldofmap.size() <<
"\n";
67 output_file <<
"Rows \n";
68 for(
unsigned iv = 0; iv <
row_gdofmap.size(); iv++ )
69 output_file <<
row_gdofmap[iv] <<
" " << row_dofmap[iv] <<
"\n";
70 output_file <<
"Cols \n";
71 for(
unsigned iv = 0; iv <
col_gdofmap.size(); iv++ )
72 output_file <<
col_gdofmap[iv] <<
" " << col_dofmap[iv] <<
"\n";
78 if( use_GID_matching )
80 std::map< unsigned, unsigned > src_gl;
81 for(
unsigned it = 0; it <
col_gdofmap.size(); ++it )
84 std::map< unsigned, unsigned >::iterator iter;
85 for(
unsigned it = 0; it <
row_gdofmap.size(); ++it )
88 iter = src_gl.find( row );
89 if( strict_check && iter == src_gl.end() )
91 std::cout <<
"Searching for global target DOF " << row
92 <<
" but could not find correspondence in source mesh.\n";
95 else if( iter == src_gl.end() )
101 unsigned icol = src_gl[row];
105 m_mapRemap( irow, icol ) = 1.0;
115 return moab::MB_FAILURE;
124 const int TriQuadRuleOrder = 4;
127 if( m_meshInputCov->faces.size() > 0 && m_meshInputCov->revnodearray.size() == 0 )
129 _EXCEPTIONT(
"ReverseNodeArray has not been calculated for m_meshInputCov" );
133 TriangularQuadratureRule triquadrule( TriQuadRuleOrder );
136 #ifdef RECTANGULAR_TRUNCATION
137 int nCoefficients = nOrder * nOrder;
139 #ifdef TRIANGULAR_TRUNCATION
140 int nCoefficients = nOrder * ( nOrder + 1 ) / 2;
144 const int nRequiredFaceSetSize = nCoefficients;
147 const int nFitWeightsExponent = nOrder + 2;
151 dbgprint.set_prefix(
"[LinearRemapFVtoFV_Tempest_MOAB]: " );
154 dbgprint.printf( 0,
"Finite Volume to Finite Volume Projection\n" );
155 dbgprint.printf( 0,
"Triangular quadrature rule order %i\n", TriQuadRuleOrder );
156 dbgprint.printf( 0,
"Number of coefficients: %i\n", nCoefficients );
157 dbgprint.printf( 0,
"Required adjacency set size: %i\n", nRequiredFaceSetSize );
158 dbgprint.printf( 0,
"Fit weights exponent: %i\n", nFitWeightsExponent );
164 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
166 DataArray2D< double > dIntArray;
167 DataArray1D< double > dConstraint( nCoefficients );
170 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
174 if( ixFirst % outputFrequency == 0 && is_root )
176 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
180 int ixOverlapBegin = ixOverlap;
181 unsigned ixOverlapEnd = ixOverlapBegin;
183 for( ; ixOverlapEnd < m_meshOverlap->faces.size(); ixOverlapEnd++ )
185 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapEnd] != 0 )
break;
188 unsigned nOverlapFaces = ixOverlapEnd - ixOverlapBegin;
190 if( nOverlapFaces == 0 )
continue;
193 BuildIntegrationArray( *m_meshInputCov, *m_meshOverlap, triquadrule, ixFirst, ixOverlapBegin, ixOverlapEnd,
200 GetAdjacentFaceVectorByEdge( *m_meshInputCov, ixFirst, nRequiredFaceSetSize, vecAdjFaces );
203 int nAdjFaces = vecAdjFaces.size();
206 double dFirstArea = m_meshInputCov->vecFaceArea[ixFirst];
208 for(
int p = 0; p < nCoefficients; p++ )
210 for(
unsigned j = 0; j < nOverlapFaces; j++ )
212 dConstraint[p] += dIntArray[p][j];
214 dConstraint[p] /= dFirstArea;
218 DataArray2D< double > dFitArray;
219 DataArray1D< double > dFitWeights;
220 DataArray2D< double > dFitArrayPlus;
222 BuildFitArray( *m_meshInputCov, triquadrule, ixFirst, vecAdjFaces, nOrder, nFitWeightsExponent, dConstraint,
223 dFitArray, dFitWeights );
226 bool fSuccess = InvertFitArray_Corrected( dConstraint, dFitArray, dFitWeights, dFitArrayPlus );
229 DataArray2D< double > dComposedArray( nAdjFaces, nOverlapFaces );
233 for(
int i = 0; i < nAdjFaces; i++ )
235 for(
size_t j = 0; j < nOverlapFaces; j++ )
237 for(
int k = 0; k < nCoefficients; k++ )
239 dComposedArray( i, j ) += dIntArray( k, j ) * dFitArrayPlus( i, k );
249 dComposedArray.Zero();
250 for(
size_t j = 0; j < nOverlapFaces; j++ )
252 dComposedArray( 0, j ) += dIntArray( 0, j );
257 for(
unsigned i = 0; i < vecAdjFaces.size(); i++ )
259 for(
unsigned j = 0; j < nOverlapFaces; j++ )
261 int& ixFirstFaceLoc = vecAdjFaces[i].first;
262 int& ixSecondFaceLoc = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
268 if( ixSecondFaceLoc < 0 )
continue;
270 m_mapRemap( ixSecondFaceLoc, ixFirstFaceLoc ) +=
271 dComposedArray[i][j] / m_meshOutput->vecFaceArea[ixSecondFaceLoc];
276 ixOverlap += nOverlapFaces;
286 int nrows = m_weightMatrix.rows();
287 int ncols = m_weightMatrix.cols();
288 int NNZ = m_weightMatrix.nonZeros();
292 int arr3[6] = { NNZ, nrows, ncols, -NNZ, -nrows, -ncols };
294 MPI_Reduce( arr3, rarr3, 6, MPI_INT, MPI_MIN, 0, m_pcomm->comm() );
297 MPI_Reduce( arr3, total, 3, MPI_INT, MPI_SUM, 0, m_pcomm->comm() );
299 std::cout <<
"-> Rows (min/max/sum): (" << rarr3[1] <<
" / " << -rarr3[4] <<
" / " << total[1] <<
"), "
300 <<
" Cols (min/max/sum): (" << rarr3[2] <<
" / " << -rarr3[5] <<
" / " << total[2] <<
"), "
301 <<
" NNZ (min/max/sum): (" << rarr3[0] <<
" / " << -rarr3[3] <<
" / " << total[0] <<
")\n";
303 std::cout <<
"-> Rows: " << nrows <<
", Cols: " << ncols <<
", NNZ: " << NNZ <<
"\n";
307 #ifdef MOAB_HAVE_EIGEN3
308 void moab::TempestOnlineMap::copy_tempest_sparsemat_to_eigen3()
311 #define VERBOSE_ACTIVATED
316 m_weightMatrix.resize( m_nTotDofs_Dest, m_nTotDofs_SrcCov );
317 m_rowVector.resize( m_weightMatrix.rows() );
318 m_colVector.resize( m_weightMatrix.cols() );
321 int locrows = std::max( m_mapRemap.GetRows(), m_nTotDofs_Dest );
322 int loccols = std::max( m_mapRemap.GetColumns(), m_nTotDofs_SrcCov );
324 std::cout << m_weightMatrix.rows() <<
", " << locrows <<
", " << m_weightMatrix.cols() <<
", " << loccols <<
"\n";
328 DataArray1D< int > lrows;
329 DataArray1D< int > lcols;
330 DataArray1D< double > lvals;
331 m_mapRemap.GetEntries( lrows, lcols, lvals );
332 size_t locvals = lvals.GetRows();
335 typedef Eigen::Triplet< double > Triplet;
336 std::vector< Triplet > tripletList;
337 tripletList.reserve( locvals );
338 for(
size_t iv = 0; iv < locvals; iv++ )
340 tripletList.push_back( Triplet( lrows[iv], lcols[iv], lvals[iv] ) );
342 m_weightMatrix.setFromTriplets( tripletList.begin(), tripletList.end() );
343 m_weightMatrix.makeCompressed();
346 std::stringstream sstr;
347 sstr <<
"tempestmatrix.txt.0000" << rank;
348 std::ofstream output_file( sstr.str(), std::ios::out );
349 output_file <<
"0 " << locrows <<
" 0 " << loccols <<
"\n";
350 for(
unsigned iv = 0; iv < locvals; iv++ )
355 output_file << row_gdofmap[row_ldofmap[lrows[iv]]] <<
" " << col_gdofmap[col_ldofmap[lcols[iv]]] <<
" "
356 << lvals[iv] <<
"\n";
362 #ifdef VERBOSE_ACTIVATED
363 #undef VERBOSE_ACTIVATED
371 template <
typename T >
372 static std::vector< size_t > sort_indexes(
const std::vector< T >& v )
375 std::vector< size_t > idx( v.size() );
376 std::iota( idx.begin(), idx.end(), 0 );
382 std::stable_sort( idx.begin(), idx.end(), [&v](
size_t i1,
size_t i2 ) { return fabs( v[i1] ) > fabs( v[i2] ); } );
388 std::vector< double >& dataCorrectedField,
389 std::vector< double >& dataLowerBound,
390 std::vector< double >& dataUpperBound,
391 std::vector< double >& dMassDefect )
393 const size_t nrows = dataCorrectedField.size();
396 std::vector< double > dataCorrection( nrows );
397 double dMassDiffCum = 0.0;
398 double dLMinusU = fabs( dataUpperBound[0] - dataLowerBound[0] );
399 const DataArray1D< double >& dTargetAreas = this->m_remapper->m_target->vecFaceArea;
402 std::vector< std::unordered_set< int > > vecAdjTargetFaces( nrows );
403 constexpr
bool useMOABAdjacencies =
true;
404 #ifdef USE_ComputeAdjacencyRelations
405 if( useMOABAdjacencies )
406 ComputeAdjacencyRelations( vecAdjTargetFaces, caasIteration, m_remapper->m_target_entities,
407 useMOABAdjacencies );
409 ComputeAdjacencyRelations( vecAdjTargetFaces, caasIteration, m_remapper->m_target_entities, useMOABAdjacencies,
410 this->m_remapper->m_target );
416 for(
size_t i = 0; i < nrows; i++ )
420 dataCorrection[index] = fmax( dataLowerBound[index], fmin( dataUpperBound[index], 0.0 ) );
424 dMassL += dTargetAreas[index] * dataLowerBound[index];
425 dMassU += dTargetAreas[index] * dataUpperBound[index];
426 dLMinusU = fmax( dLMinusU, fabs( dataUpperBound[index] - dataLowerBound[index] ) );
427 dMassDiffCum += dMassDefect[index] - dTargetAreas[index] * dataCorrection[index];
429 #ifndef USE_ComputeAdjacencyRelations
430 vecAdjTargetFaces[index].insert( index );
433 if( useMOABAdjacencies )
437 ents.
insert( m_remapper->m_target_entities[index] );
443 int adjIndex = m_remapper->m_target_entities.index( *it );
445 if( adjIndex >= 0 ) vecAdjTargetFaces[index].insert( adjIndex );
451 GetAdjacentFaceVectorByEdge( *this->m_remapper->m_target, index,
452 ( m_output_order + 1 ) * ( m_output_order + 1 ) * ( m_output_order + 1 ),
458 for(
auto adjFace : vecAdjFaces )
459 if( adjFace.first >= 0 )
460 vecAdjTargetFaces[index].insert( adjFace.first );
467 std::vector< double > localDefects( 5, 0.0 ), globalDefects( 5, 0.0 );
468 localDefects[0] = dMassL;
469 localDefects[1] = dMassU;
470 localDefects[2] = dMassDiffCum;
471 localDefects[3] = dLMinusU;
474 MPI_Allreduce( localDefects.data(), globalDefects.data(), 4, MPI_DOUBLE, MPI_SUM, m_pcomm->comm() );
476 dMassL = globalDefects[0];
477 dMassU = globalDefects[1];
478 dMassDiffCum = globalDefects[2];
479 dLMinusU = globalDefects[3];
484 if( fabs( dMassDiffCum ) < 1e-15 || dLMinusU < 1e-15 )
486 for(
size_t i = 0; i < nrows; i++ )
487 dataCorrectedField[i] += dataCorrection[i];
492 if( dMassL > dMassDiffCum )
494 Announce(
"Lower bound mass exceeds target mass by %1.15e: CAAS will need another iteration",
495 dMassL - dMassDiffCum );
496 dMassDiffCum = dMassL;
499 else if( dMassU < dMassDiffCum )
501 Announce(
"Target mass exceeds upper bound mass by %1.15e: CAAS will need another iteration",
502 dMassDiffCum - dMassU );
503 dMassDiffCum = dMassU;
509 for(
size_t i = 0; i < nrows; i++ )
513 const std::unordered_set< int >& neighbors = vecAdjTargetFaces[index];
514 if( dMassDefect[index] > 0.0 )
516 double dMassCorrectU = 0.0;
517 for(
auto it : neighbors )
518 dMassCorrectU += dTargetAreas[it] * ( dataUpperBound[it] - dataCorrection[it] );
521 for(
auto it : neighbors )
522 dataCorrection[it] +=
523 dMassDefect[index] * ( dataUpperBound[it] - dataCorrection[it] ) / dMassCorrectU;
527 double dMassCorrectL = 0.0;
528 for(
auto it : neighbors )
529 dMassCorrectL += dTargetAreas[it] * ( dataCorrection[it] - dataLowerBound[it] );
532 for(
auto it : neighbors )
533 dataCorrection[it] +=
534 dMassDefect[index] * ( dataCorrection[it] - dataLowerBound[it] ) / dMassCorrectL;
538 for(
size_t i = 0; i < nrows; i++ )
539 dataCorrectedField[i] += dataCorrection[i];
546 std::vector< double >& dataLowerBound,
547 std::vector< double >& dataUpperBound,
550 const size_t nrows = dataCorrectedField.size();
553 std::vector< double > dataCorrection( nrows );
554 const DataArray1D< double >& dTargetAreas = this->m_remapper->m_target->vecFaceArea;
555 double dMassDiff = dMass;
556 double dLMinusU = fabs( dataUpperBound[0] - dataLowerBound[0] );
557 double dMassCorrectU = 0.0;
558 double dMassCorrectL = 0.0;
559 for(
size_t i = 0; i < nrows; i++ )
561 dataCorrection[i] = fmax( dataLowerBound[i], fmin( dataUpperBound[i], 0.0 ) );
562 dMassL += dTargetAreas[i] * dataLowerBound[i];
563 dMassU += dTargetAreas[i] * dataUpperBound[i];
564 dMassDiff -= dTargetAreas[i] * dataCorrection[i];
565 dLMinusU = fmax( dLMinusU, fabs( dataUpperBound[i] - dataLowerBound[i] ) );
566 dMassCorrectL += dTargetAreas[i] * ( dataCorrection[i] - dataLowerBound[i] );
567 dMassCorrectU += dTargetAreas[i] * ( dataUpperBound[i] - dataCorrection[i] );
571 std::vector< double > localDefects( 5, 0.0 ), globalDefects( 5, 0.0 );
572 localDefects[0] = dMassL;
573 localDefects[1] = dMassU;
574 localDefects[2] = dMassDiff;
575 localDefects[3] = dMassCorrectL;
576 localDefects[4] = dMassCorrectU;
578 MPI_Allreduce( localDefects.data(), globalDefects.data(), 5, MPI_DOUBLE, MPI_SUM, m_pcomm->comm() );
580 dMassL = globalDefects[0];
581 dMassU = globalDefects[1];
582 dMassDiff = globalDefects[2];
583 dMassCorrectL = globalDefects[3];
584 dMassCorrectU = globalDefects[4];
588 if( fabs( dMassDiff ) < 1e-15 || fabs( dLMinusU ) < 1e-15 )
590 for(
size_t i = 0; i < nrows; i++ )
591 dataCorrectedField[i] += dataCorrection[i];
596 if( dMassL > dMassDiff )
598 Announce(
"%d: Lower bound mass exceeds target mass by %1.15e: CAAS will need another iteration", rank,
599 dMassL - dMassDiff );
603 else if( dMassU < dMassDiff )
605 Announce(
"%d: Target mass exceeds upper bound mass by %1.15e: CAAS will need another iteration", rank,
606 dMassDiff - dMassU );
612 DataArray1D< double > dataMassVec( nrows );
613 if( dMassDiff > 0.0 )
615 for(
size_t i = 0; i < nrows; i++ )
617 dataMassVec[i] = ( dataUpperBound[i] - dataCorrection[i] ) / dMassCorrectU;
618 dataCorrection[i] += dMassDiff * dataMassVec[i];
623 for(
size_t i = 0; i < nrows; i++ )
625 dataMassVec[i] = ( dataCorrection[i] - dataLowerBound[i] ) / dMassCorrectL;
626 dataCorrection[i] += dMassDiff * dataMassVec[i];
630 for(
size_t i = 0; i < nrows; i++ )
631 dataCorrectedField[i] += dataCorrection[i];
638 std::vector< double >& dataOutDouble,
645 assert( !dataGLLNodesSrcCov.IsAttached() && !dataGLLNodesDest.IsAttached() );
647 std::pair< double, double > massDefect( 0.0, 0.0 );
650 const size_t nTargetCount = dataOutDouble.size();
651 const DataArray1D< double >& m_dOverlapAreas = this->m_remapper->m_overlap->vecFaceArea;
654 double dMassDiff = 0.0;
655 std::vector< double > x( nTargetCount );
656 std::vector< double > dataLowerBound( nTargetCount );
657 std::vector< double > dataUpperBound( nTargetCount );
658 std::vector< double > massVector( nTargetCount );
659 std::vector< std::unordered_set< int > > vecSourceOvTarget( nTargetCount );
661 #undef USE_ComputeAdjacencyRelations
662 constexpr
bool useMOABAdjacencies =
true;
663 #ifdef USE_ComputeAdjacencyRelations
667 if( caasType == CAAS_QLT || caasType == CAAS_LOCAL_ADJACENT )
669 if( useMOABAdjacencies )
672 ComputeAdjacencyRelations( vecSourceOvTarget, caasIteration, m_remapper->m_covering_source_entities,
678 ComputeAdjacencyRelations( vecSourceOvTarget, caasIteration, m_remapper->m_covering_source_entities,
679 useMOABAdjacencies, m_meshInputCov );
MB_CHK_SET_ERR_CONT( rval,
"Failed to get adjacent faces" );
687 double dSourceMin = dataInDouble[0];
688 double dSourceMax = dataInDouble[0];
689 double dTargetMin = dataOutDouble[0];
690 double dTargetMax = dataOutDouble[0];
691 for(
size_t i = 0; i < m_meshOverlap->faces.size(); i++ )
693 const int ixS = m_meshOverlap->vecSourceFaceIx[i];
694 const int ixT = m_meshOverlap->vecTargetFaceIx[i];
696 if( ixT < 0 )
continue;
698 assert( m_dOverlapAreas[i] > 0.0 );
702 #ifndef USE_ComputeAdjacencyRelations
704 vecSourceOvTarget[ixT].insert( ixS );
705 if( ( caasType == CAAS_QLT || caasType == CAAS_LOCAL_ADJACENT ) )
707 if( useMOABAdjacencies )
710 ents.
insert( m_remapper->m_covering_source_entities[ixS] );
715 int adjIndex = m_remapper->m_covering_source_entities.index( *it );
716 if( adjIndex >= 0 ) vecSourceOvTarget[ixT].insert( adjIndex );
723 GetAdjacentFaceVectorByEdge( *m_meshInputCov, ixS,
724 ( caasIteration ) * ( m_input_order + 1 ) * ( m_input_order + 1 ),
728 for(
size_t iadj = 0; iadj < vecAdjFaces.size(); iadj++ )
729 vecSourceOvTarget[ixT].insert( vecAdjFaces[iadj].
first );
735 dSourceMax = fmax( dSourceMax, dataInDouble[ixS] );
736 dSourceMin = fmin( dSourceMin, dataInDouble[ixS] );
739 dTargetMin = fmin( dTargetMin, dataOutDouble[ixT] );
740 dTargetMax = fmax( dTargetMax, dataOutDouble[ixT] );
742 const double locMassDiff = ( dataInDouble[ixS] * m_dOverlapAreas[i] ) -
743 ( dataOutDouble[ixT] * m_dOverlapAreas[i] );
747 dMassDiff += locMassDiff;
748 massVector[ixT] += locMassDiff;
752 std::vector< double > localMinMaxDefects( 5, 0.0 ), globalMinMaxDefects( 5, 0.0 );
753 localMinMaxDefects[0] = dSourceMin;
754 localMinMaxDefects[1] = dTargetMin;
755 localMinMaxDefects[2] = dSourceMax;
756 localMinMaxDefects[3] = dTargetMax;
757 localMinMaxDefects[4] = dMassDiff;
759 if( caasType == CAAS_GLOBAL )
761 MPI_Allreduce( localMinMaxDefects.data(), globalMinMaxDefects.data(), 2, MPI_DOUBLE, MPI_MIN, m_pcomm->comm() );
762 MPI_Allreduce( localMinMaxDefects.data() + 2, globalMinMaxDefects.data() + 2, 2, MPI_DOUBLE, MPI_MAX,
764 dSourceMin = globalMinMaxDefects[0];
765 dSourceMax = globalMinMaxDefects[2];
766 dTargetMin = globalMinMaxDefects[1];
767 dTargetMax = globalMinMaxDefects[3];
769 if( caasIteration == 1 )
770 MPI_Allreduce( localMinMaxDefects.data() + 4, globalMinMaxDefects.data() + 4, 1, MPI_DOUBLE, MPI_SUM,
773 globalMinMaxDefects[4] = mismatch;
775 dMassDiff = localMinMaxDefects[4];
777 massDefect.first = globalMinMaxDefects[4];
781 massDefect.first = dMassDiff;
786 if( fabs( massDefect.first ) > 1e-20 )
788 if( caasType == CAAS_GLOBAL )
790 for(
size_t i = 0; i < nTargetCount; i++ )
792 dataLowerBound[i] = dSourceMin - dataOutDouble[i];
793 dataUpperBound[i] = dSourceMax - dataOutDouble[i];
799 std::vector< double > vecLocalUpperBound( nTargetCount );
800 std::vector< double > vecLocalLowerBound( nTargetCount );
803 for(
size_t i = 0; i < nTargetCount; i++ )
805 assert( vecSourceOvTarget[i].
size() );
808 double dMaxI = -1E10;
811 for(
const auto& srcElem : vecSourceOvTarget[i] )
813 dMinI = fmin( dMinI, dataInDouble[srcElem] );
814 dMaxI = fmax( dMaxI, dataInDouble[srcElem] );
818 vecLocalLowerBound[i] = dMinI;
819 vecLocalUpperBound[i] = dMaxI;
822 for(
size_t i = 0; i < nTargetCount; i++ )
824 dataLowerBound[i] = vecLocalLowerBound[i] - dataOutDouble[i];
825 dataUpperBound[i] = vecLocalUpperBound[i] - dataOutDouble[i];
830 if( fabs( dMassDiff ) > 1e-20 )
832 if( caasType == CAAS_QLT )
833 dMassDiff = QLTLimiter( caasIteration, dataOutDouble, dataLowerBound, dataUpperBound, massVector );
835 CAASLimiter( dataOutDouble, dataLowerBound, dataUpperBound, dMassDiff );
839 double dMassDiffPost = 0.0;
840 for(
size_t i = 0; i < m_meshOverlap->faces.size(); i++ )
842 const int ixS = m_meshOverlap->vecSourceFaceIx[i];
843 const int ixT = m_meshOverlap->vecTargetFaceIx[i];
845 if( ixT < 0 )
continue;
849 dMassDiffPost += ( dataInDouble[ixS] * m_dOverlapAreas[i] ) -
850 ( dataOutDouble[ixT] * m_dOverlapAreas[i] );
853 massDefect.second = dMassDiffPost;
867 double correction = 0.0;
869 void add(
double value )
871 double y = value - correction;
873 correction = ( t -
sum ) - y;
877 double result()
const
884 inline double pairwiseSum(
const std::set< double >& sorted )
886 if( sorted.empty() )
return 0.0;
887 if( sorted.size() == 1 )
return *sorted.begin();
891 for(
double val : sorted )
897 inline double pairwiseKahanSum(
const std::set< double >& sorted )
899 if( sorted.empty() )
return 0.0;
900 if( sorted.size() == 1 )
return *sorted.begin();
905 for(
double val : sorted )
907 return kahan.result();
911 inline void deterministicSparseMatVecMul(
const typename moab::TempestOnlineMap::WeightMatrix& A,
912 const typename moab::TempestOnlineMap::WeightColVector& x,
913 typename moab::TempestOnlineMap::WeightRowVector& result )
915 constexpr
bool useKahanSum =
false;
916 constexpr
bool usePairwiseSum =
false;
921 for(
int row = 0; row < A.outerSize(); ++row )
923 std::set< double > accumulators;
924 for(
typename moab::TempestOnlineMap::WeightMatrix::InnerIterator it( A, row ); it; ++it )
927 accumulators.insert( it.value() * x( it.col() ) );
929 if( usePairwiseSum ) result( row ) = pairwiseSum( accumulators );
930 if( useKahanSum ) result( row ) = pairwiseKahanSum( accumulators );
932 if( !usePairwiseSum && !useKahanSum )
935 for(
double val : accumulators )
944 inline void deterministicSparseMatVecMulKahan(
const typename moab::TempestOnlineMap::WeightMatrix& A,
945 const typename moab::TempestOnlineMap::WeightColVector& x,
946 typename moab::TempestOnlineMap::WeightRowVector& result )
951 for(
int row = 0; row < A.outerSize(); ++row )
954 for(
typename moab::TempestOnlineMap::WeightMatrix::InnerIterator it( A, row ); it; ++it )
956 double product = it.value() * x( it.col() );
960 result( row ) = kahan.result();
965 inline void deterministicSparseMatVecMulClean(
const typename moab::TempestOnlineMap::WeightMatrix& A,
966 const typename moab::TempestOnlineMap::WeightColVector& x,
967 typename moab::TempestOnlineMap::WeightRowVector& result )
972 for(
int row = 0; row < A.outerSize(); ++row )
974 for(
typename moab::TempestOnlineMap::WeightMatrix::InnerIterator it( A, row ); it; ++it )
976 const double product = it.value() * x( it.col() );
982 inline void deterministicSparseMatVecMulNative(
const typename moab::TempestOnlineMap::WeightMatrix& A,
983 const typename moab::TempestOnlineMap::WeightColVector& x,
984 typename moab::TempestOnlineMap::WeightRowVector& result )
990 inline void deterministicSparseMatTransposeVecMul(
const typename moab::TempestOnlineMap::WeightMatrix& A,
991 const typename moab::TempestOnlineMap::WeightRowVector& x,
992 typename moab::TempestOnlineMap::WeightColVector& result )
997 std::vector< std::set< double > > accumulators( A.cols() );
1000 for(
int row = 0; row < A.outerSize(); ++row )
1002 for(
typename moab::TempestOnlineMap::WeightMatrix::InnerIterator it( A, row ); it; ++it )
1004 accumulators[it.col()].insert( it.value() * x( row ) );
1009 for(
int col = 0; col < A.cols(); ++col )
1012 result( col ) = pairwiseKahanSum( accumulators[col] );
1017 inline void deterministicSparseMatTransposeVecMulClean(
const typename moab::TempestOnlineMap::WeightMatrix& A,
1018 const typename moab::TempestOnlineMap::WeightRowVector& x,
1019 typename moab::TempestOnlineMap::WeightColVector& result )
1024 for(
int row = 0; row < A.outerSize(); ++row )
1026 for(
typename moab::TempestOnlineMap::WeightMatrix::InnerIterator it( A, row ); it; ++it )
1028 const double product = it.value() * x( row );
1029 result( it.col() ) +=
product;
1035 inline void deterministicSparseMatTransposeVecMulNative(
const typename moab::TempestOnlineMap::WeightMatrix& A,
1036 const typename moab::TempestOnlineMap::WeightRowVector& x,
1037 typename moab::TempestOnlineMap::WeightColVector& result )
1039 result = A.adjoint() * x;
1044 std::vector< double >& tgtVals,
1048 m_rowVector.setZero();
1049 m_colVector.setZero();
1051 std::stringstream sstr;
1052 static int callId = 0;
1054 sstr <<
"projection_id_" << callId <<
"_s_" <<
size <<
"_rk_" << rank <<
".txt";
1055 std::ofstream output_file( sstr.str() );
1062 for(
unsigned i = 0; i < srcVals.size(); ++i )
1064 if( row_dtoc_dofmap[i] >= 0 && row_dtoc_dofmap[i] < m_rowVector.size() )
1065 m_rowVector( row_dtoc_dofmap[i] ) = srcVals[i];
1069 deterministicSparseMatTransposeVecMul( m_weightMatrix, m_rowVector, m_colVector );
1073 for(
unsigned i = 0; i < tgtVals.size(); ++i )
1075 if( col_dtoc_dofmap[i] >= 0 && col_dtoc_dofmap[i] < m_colVector.size() )
1076 tgtVals[i] = m_colVector( col_dtoc_dofmap[i] );
1083 output_file <<
"ColVector: " << m_colVector.size() <<
", SrcVals: " << srcVals.size()
1084 <<
", Sizes: " << m_nTotDofs_SrcCov <<
", " << col_dtoc_dofmap.size() <<
"\n";
1086 for(
unsigned i = 0; i < srcVals.size(); ++i )
1088 if( col_dtoc_dofmap[i] >= 0 && col_dtoc_dofmap[i] < m_colVector.size() )
1090 m_colVector( col_dtoc_dofmap[i] ) = srcVals[i];
1092 output_file << i <<
" " << col_gdofmap[col_dtoc_dofmap[i]] + 1 <<
" " << srcVals[i] <<
"\n";
1098 deterministicSparseMatVecMul( m_weightMatrix, m_colVector, m_rowVector );
1105 <<
"RowVector: " << m_rowVector.size() <<
", TgtVals:" << tgtVals.size() <<
", Sizes: " << m_nTotDofs_Dest
1106 <<
", " << row_gdofmap.size() <<
"\n";
1108 for(
unsigned i = 0; i < tgtVals.size(); ++i )
1110 if( row_dtoc_dofmap[i] >= 0 && row_dtoc_dofmap[i] < m_rowVector.size() )
1112 tgtVals[i] = m_rowVector( row_dtoc_dofmap[i] );
1114 output_file << i <<
" " << row_gdofmap[row_dtoc_dofmap[i]] + 1 <<
" " << tgtVals[i] <<
"\n";
1137 output_file.flush();
1138 output_file.close();
1150 const DataArray1D< double >& vecTargetArea,
1151 DataArray2D< double >& dCoeff,
1153 bool fSparseConstraints =
false );
1158 const DataArray1D< double >& vecTargetArea,
1159 DataArray2D< double >& dCoeff,
1165 const DataArray3D< double >& dataGLLJacobian,
1168 bool fNoConservation )
1171 int nP = dataGLLNodes.GetRows();
1174 const int TriQuadRuleOrder = 4;
1177 TriangularQuadratureRule triquadrule( TriQuadRuleOrder );
1179 int TriQuadraturePoints = triquadrule.GetPoints();
1181 const DataArray2D< double >& TriQuadratureG = triquadrule.GetG();
1183 const DataArray1D< double >& TriQuadratureW = triquadrule.GetW();
1186 DataArray2D< double > dSampleCoeff( nP, nP );
1189 DataArray1D< double > dG;
1190 DataArray1D< double > dW;
1191 GaussLobattoQuadrature::GetPoints( nP, 0.0, 1.0, dG, dW );
1195 dbgprint.set_prefix(
"[LinearRemapSE4_Tempest_MOAB]: " );
1198 dbgprint.printf( 0,
"Finite Element to Finite Volume Projection\n" );
1199 dbgprint.printf( 0,
"Triangular quadrature rule order %i\n", TriQuadRuleOrder );
1200 dbgprint.printf( 0,
"Order of the FE polynomial interpolant: %i\n", nP );
1204 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
1207 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
1208 const NodeVector& nodesFirst = m_meshInputCov->nodes;
1211 DataArray1D< double > vecSourceArea( nP * nP );
1213 DataArray1D< double > vecTargetArea;
1214 DataArray2D< double > dCoeff;
1217 std::stringstream sstr;
1218 sstr <<
"remapdata_" << rank <<
".txt";
1219 std::ofstream output_file( sstr.str() );
1225 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
1233 NodeVector nodes( 3 );
1234 faceTri.SetNode( 0, 0 );
1235 faceTri.SetNode( 1, 1 );
1236 faceTri.SetNode( 2, 2 );
1239 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1241 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
1243 if( faceFirst.edges.size() != 4 )
1245 _EXCEPTIONT(
"Only quadrilateral elements allowed for SE remapping" );
1249 if( ixFirst % outputFrequency == 0 && is_root )
1251 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1259 int nOverlapFaces = 0;
1260 size_t ixOverlapTemp = ixOverlap;
1261 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
1265 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
break;
1271 if( nOverlapFaces == 0 )
1277 DataArray3D< double > dRemapCoeff( nP, nP, nOverlapFaces );
1280 for(
int j = 0; j < nOverlapFaces; j++ )
1282 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + j];
1283 if( m_meshOverlap->vecFaceArea[ixOverlap + j] < 1.e-16 )
1285 Announce(
"Very small overlap at index %i area polygon: (%1.10e )", ixOverlap + j,
1286 m_meshOverlap->vecFaceArea[ixOverlap + j] );
1287 int n = faceOverlap.edges.size();
1288 Announce(
"Number nodes: %d", n );
1289 for(
int k = 0; k < n; k++ )
1291 Node nd = nodesOverlap[faceOverlap[k]];
1292 Announce(
"Node %d %d : %1.10e %1.10e %1.10e ", k, faceOverlap[k], nd.x, nd.y, nd.z );
1304 int nbEdges = faceOverlap.edges.size();
1305 int nOverlapTriangles = 1;
1309 nOverlapTriangles = nbEdges;
1310 for(
int k = 0; k < nbEdges; k++ )
1312 const Node& node = nodesOverlap[faceOverlap[k]];
1319 Node node0, node1, node2;
1320 double dTriangleArea;
1323 for(
int k = 0; k < nOverlapTriangles; k++ )
1327 node0 = nodesOverlap[faceOverlap[0]];
1328 node1 = nodesOverlap[faceOverlap[1]];
1329 node2 = nodesOverlap[faceOverlap[2]];
1330 dTriangleArea = CalculateFaceArea( faceOverlap, nodesOverlap );
1335 node1 = nodesOverlap[faceOverlap[k]];
1336 int k1 = ( k + 1 ) % nbEdges;
1337 node2 = nodesOverlap[faceOverlap[k1]];
1341 dTriangleArea = CalculateFaceArea( faceTri, nodes );
1344 for(
int l = 0; l < TriQuadraturePoints; l++ )
1346 Node nodeQuadrature;
1347 nodeQuadrature.x = TriQuadratureG[l][0] * node0.x + TriQuadratureG[l][1] * node1.x +
1348 TriQuadratureG[l][2] * node2.x;
1350 nodeQuadrature.y = TriQuadratureG[l][0] * node0.y + TriQuadratureG[l][1] * node1.y +
1351 TriQuadratureG[l][2] * node2.y;
1353 nodeQuadrature.z = TriQuadratureG[l][0] * node0.z + TriQuadratureG[l][1] * node1.z +
1354 TriQuadratureG[l][2] * node2.z;
1356 nodeQuadrature = nodeQuadrature.Normalized();
1363 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlpha, dBeta );
1366 if( ( dAlpha < -1.0e-13 ) || ( dAlpha > 1.0 + 1.0e-13 ) || ( dBeta < -1.0e-13 ) ||
1367 ( dBeta > 1.0 + 1.0e-13 ) )
1369 _EXCEPTION4(
"Inverse Map for element %d and subtriangle %d out of range "
1371 j, l, dAlpha, dBeta );
1375 SampleGLLFiniteElement( nMonotoneType, nP, dAlpha, dBeta, dSampleCoeff );
1378 for(
int p = 0; p < nP; p++ )
1380 for(
int q = 0; q < nP; q++ )
1382 dRemapCoeff[p][q][j] += TriQuadratureW[l] * dTriangleArea * dSampleCoeff[p][q] /
1383 m_meshOverlap->vecFaceArea[ixOverlap + j];
1391 output_file <<
"[" << m_remapper->lid_to_gid_covsrc[ixFirst] <<
"] \t";
1392 for(
int j = 0; j < nOverlapFaces; j++ )
1394 for(
int p = 0; p < nP; p++ )
1396 for(
int q = 0; q < nP; q++ )
1398 output_file << dRemapCoeff[p][q][j] <<
" ";
1402 output_file << std::endl;
1406 if( !fNoConservation )
1408 double dTargetArea = 0.0;
1409 for(
int j = 0; j < nOverlapFaces; j++ )
1411 dTargetArea += m_meshOverlap->vecFaceArea[ixOverlap + j];
1414 for(
int p = 0; p < nP; p++ )
1416 for(
int q = 0; q < nP; q++ )
1418 vecSourceArea[p * nP + q] = dataGLLJacobian[p][q][ixFirst];
1422 const double areaTolerance = 1e-10;
1424 if( fabs( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea ) <= areaTolerance )
1426 vecTargetArea.Allocate( nOverlapFaces );
1427 for(
int j = 0; j < nOverlapFaces; j++ )
1429 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
1432 dCoeff.Allocate( nOverlapFaces, nP * nP );
1434 for(
int j = 0; j < nOverlapFaces; j++ )
1436 for(
int p = 0; p < nP; p++ )
1438 for(
int q = 0; q < nP; q++ )
1440 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
1447 else if( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea > areaTolerance )
1449 double dExtraneousArea = m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea;
1451 vecTargetArea.Allocate( nOverlapFaces + 1 );
1452 for(
int j = 0; j < nOverlapFaces; j++ )
1454 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
1456 vecTargetArea[nOverlapFaces] = dExtraneousArea;
1459 Announce(
"Partial volume: %i (%1.10e / %1.10e)", ixFirst, dTargetArea,
1460 m_meshInputCov->vecFaceArea[ixFirst] );
1462 if( dTargetArea > m_meshInputCov->vecFaceArea[ixFirst] )
1464 _EXCEPTIONT(
"Partial element area exceeds total element area" );
1467 dCoeff.Allocate( nOverlapFaces + 1, nP * nP );
1469 for(
int j = 0; j < nOverlapFaces; j++ )
1471 for(
int p = 0; p < nP; p++ )
1473 for(
int q = 0; q < nP; q++ )
1475 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
1479 for(
int p = 0; p < nP; p++ )
1481 for(
int q = 0; q < nP; q++ )
1483 dCoeff[nOverlapFaces][p * nP + q] = dataGLLJacobian[p][q][ixFirst];
1486 for(
int j = 0; j < nOverlapFaces; j++ )
1488 for(
int p = 0; p < nP; p++ )
1490 for(
int q = 0; q < nP; q++ )
1492 dCoeff[nOverlapFaces][p * nP + q] -=
1493 dRemapCoeff[p][q][j] * m_meshOverlap->vecFaceArea[ixOverlap + j];
1497 for(
int p = 0; p < nP; p++ )
1499 for(
int q = 0; q < nP; q++ )
1501 dCoeff[nOverlapFaces][p * nP + q] /= dExtraneousArea;
1509 Announce(
"Coverage area: %1.10e, and target element area: %1.10e)", ixFirst,
1510 m_meshInputCov->vecFaceArea[ixFirst], dTargetArea );
1511 _EXCEPTIONT(
"Target grid must be a subset of source grid" );
1517 for(
int j = 0; j < nOverlapFaces; j++ )
1519 for(
int p = 0; p < nP; p++ )
1521 for(
int q = 0; q < nP; q++ )
1523 dRemapCoeff[p][q][j] = dCoeff[j][p * nP + q];
1545 for(
int j = 0; j < nOverlapFaces; j++ )
1547 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
1550 if( ixSecondFace < 0 )
continue;
1552 for(
int p = 0; p < nP; p++ )
1554 for(
int q = 0; q < nP; q++ )
1558 int ixFirstNode = dataGLLNodes[p][q][ixFirst] - 1;
1560 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
1561 m_meshOverlap->vecFaceArea[ixOverlap + j] /
1562 m_meshOutput->vecFaceArea[ixSecondFace];
1566 int ixFirstNode = ixFirst * nP * nP + p * nP + q;
1568 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
1569 m_meshOverlap->vecFaceArea[ixOverlap + j] /
1570 m_meshOutput->vecFaceArea[ixSecondFace];
1576 ixOverlap += nOverlapFaces;
1579 output_file.flush();
1580 output_file.close();
1589 const DataArray3D< double >& dataGLLJacobianIn,
1590 const DataArray3D< int >& dataGLLNodesOut,
1591 const DataArray3D< double >& dataGLLJacobianOut,
1592 const DataArray1D< double >& dataNodalAreaOut,
1597 bool fContinuousOut,
1598 bool fNoConservation )
1601 TriangularQuadratureRule triquadrule( 8 );
1603 const DataArray2D< double >& dG = triquadrule.GetG();
1604 const DataArray1D< double >& dW = triquadrule.GetW();
1607 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
1610 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
1611 DataArray2D< double > dSampleCoeffOut( nPout, nPout );
1615 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_MOAB]: " );
1618 dbgprint.printf( 0,
"Finite Element to Finite Element Projection\n" );
1619 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
1620 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
1624 DataArray3D< double > dGlobalIntArray( nPin * nPin, m_meshOverlap->faces.size(), nPout * nPout );
1627 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
1630 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1633 int nOverlapFaces = 0;
1634 size_t ixOverlapTemp = ixOverlap;
1635 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
1638 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
1646 nAllOverlapFaces[ixFirst] = nOverlapFaces;
1649 ixOverlap += nAllOverlapFaces[ixFirst];
1653 DataArray2D< double > dGeometricOutputArea( m_meshOutput->faces.size(), nPout * nPout );
1656 DataArray2D< double > dOverlapOutputArea( m_meshOverlap->faces.size(), nPout * nPout );
1661 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
1663 if( is_root )
dbgprint.printf( 0,
"Building conservative distribution maps\n" );
1671 NodeVector nodes( 3 );
1672 faceTri.SetNode( 0, 0 );
1673 faceTri.SetNode( 1, 1 );
1674 faceTri.SetNode( 2, 2 );
1676 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1680 if( ixFirst % outputFrequency == 0 && is_root )
1682 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1686 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
1688 const NodeVector& nodesFirst = m_meshInputCov->nodes;
1691 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1693 if( !nOverlapFaces )
continue;
1704 for(
int i = 0; i < nOverlapFaces; i++ )
1707 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + i];
1709 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
1712 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
1715 if( ixSecond < 0 )
continue;
1717 const NodeVector& nodesSecond = m_meshOutput->nodes;
1719 const Face& faceSecond = m_meshOutput->faces[ixSecond];
1721 int nbEdges = faceOverlap.edges.size();
1722 int nOverlapTriangles = 1;
1726 nOverlapTriangles = nbEdges;
1727 for(
int k = 0; k < nbEdges; k++ )
1729 const Node& node = nodesOverlap[faceOverlap[k]];
1736 Node node0, node1, node2;
1740 for(
int j = 0; j < nOverlapTriangles; j++ )
1744 node0 = nodesOverlap[faceOverlap[0]];
1745 node1 = nodesOverlap[faceOverlap[1]];
1746 node2 = nodesOverlap[faceOverlap[2]];
1747 dTriArea = CalculateFaceArea( faceOverlap, nodesOverlap );
1752 node1 = nodesOverlap[faceOverlap[j]];
1753 int j1 = ( j + 1 ) % nbEdges;
1754 node2 = nodesOverlap[faceOverlap[j1]];
1758 dTriArea = CalculateFaceArea( faceTri, nodes );
1761 for(
int k = 0; k < triquadrule.GetPoints(); k++ )
1766 dX[0] = dG( k, 0 ) * node0.x + dG( k, 1 ) * node1.x + dG( k, 2 ) * node2.x;
1767 dX[1] = dG( k, 0 ) * node0.y + dG( k, 1 ) * node1.y + dG( k, 2 ) * node2.y;
1768 dX[2] = dG( k, 0 ) * node0.z + dG( k, 1 ) * node1.z + dG( k, 2 ) * node2.z;
1770 double dMag = sqrt( dX[0] * dX[0] + dX[1] * dX[1] + dX[2] * dX[2] );
1776 Node nodeQuadrature( dX[0], dX[1], dX[2] );
1783 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlphaIn, dBetaIn );
1790 ApplyInverseMap( faceSecond, nodesSecond, nodeQuadrature, dAlphaOut, dBetaOut );
1810 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
1813 SampleGLLFiniteElement( nMonotoneType, nPout, dAlphaOut, dBetaOut, dSampleCoeffOut );
1816 for(
int s = 0; s < nPout; s++ )
1818 for(
int t = 0; t < nPout; t++ )
1820 double dNodeArea = dSampleCoeffOut[s][t] * dW[k] * dTriArea;
1822 dOverlapOutputArea[ixOverlap + i][s * nPout + t] += dNodeArea;
1824 dGeometricOutputArea[ixSecond][s * nPout + t] += dNodeArea;
1830 for(
int p = 0; p < nPin; p++ )
1832 for(
int q = 0; q < nPin; q++ )
1835 for(
int s = 0; s < nPout; s++ )
1837 for(
int t = 0; t < nPout; t++ )
1840 dGlobalIntArray[ixp][ixOverlap + i][ixs] +=
1841 dSampleCoeffOut[s][t] * dSampleCoeffIn[p][q] * dW[k] * dTriArea;
1855 DataArray2D< double > dCoeff( nOverlapFaces * nPout * nPout, nPin * nPin );
1857 for(
int i = 0; i < nOverlapFaces; i++ )
1862 for(
int p = 0; p < nPin; p++ )
1864 for(
int q = 0; q < nPin; q++ )
1867 for(
int s = 0; s < nPout; s++ )
1869 for(
int t = 0; t < nPout; t++ )
1871 dCoeff[i * nPout * nPout + ixs][ixp] = dGlobalIntArray[ixp][ixOverlap + i][ixs] /
1872 dOverlapOutputArea[ixOverlap + i][s * nPout + t];
1884 DataArray1D< double > vecSourceArea( nPin * nPin );
1886 for(
int p = 0; p < nPin; p++ )
1888 for(
int q = 0; q < nPin; q++ )
1890 vecSourceArea[p * nPin + q] = dataGLLJacobianIn[p][q][ixFirst];
1895 DataArray1D< double > vecTargetArea( nOverlapFaces * nPout * nPout );
1897 for(
int i = 0; i < nOverlapFaces; i++ )
1901 for(
int s = 0; s < nPout; s++ )
1903 for(
int t = 0; t < nPout; t++ )
1905 vecTargetArea[i * nPout * nPout + ixs] = dOverlapOutputArea[ixOverlap + i][nPout * s + t];
1913 if( !fNoConservation )
1919 for(
int i = 0; i < nOverlapFaces; i++ )
1922 for(
int p = 0; p < nPin; p++ )
1924 for(
int q = 0; q < nPin; q++ )
1927 for(
int s = 0; s < nPout; s++ )
1929 for(
int t = 0; t < nPout; t++ )
1931 dGlobalIntArray[ixp][ixOverlap + i][ixs] =
1932 dCoeff[i * nPout * nPout + ixs][ixp] * dOverlapOutputArea[ixOverlap + i][s * nPout + t];
1945 for(
int i = 0; i < nPin * nPin; i++ )
1947 double dColSum = 0.0;
1948 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1950 dColSum += dCoeff[j][i] * vecTargetArea[j];
1952 printf(
"Col %i: %1.15e\n", i, dColSum / vecSourceArea[i] );
1956 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1958 double dRowSum = 0.0;
1959 for(
int i = 0; i < nPin * nPin; i++ )
1961 dRowSum += dCoeff[j][i];
1963 printf(
"Row %i: %1.15e\n", j, dRowSum );
1968 ixOverlap += nOverlapFaces;
1972 if( is_root )
dbgprint.printf( 0,
"Building redistribution maps on target mesh\n" );
1973 DataArray1D< double > dRedistSourceArea( nPout * nPout );
1974 DataArray1D< double > dRedistTargetArea( nPout * nPout );
1975 std::vector< DataArray2D< double > > dRedistributionMaps;
1976 dRedistributionMaps.resize( m_meshOutput->faces.size() );
1978 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
1980 dRedistributionMaps[ixSecond].Allocate( nPout * nPout, nPout * nPout );
1982 for(
int i = 0; i < nPout * nPout; i++ )
1984 dRedistributionMaps[ixSecond][i][i] = 1.0;
1987 for(
int s = 0; s < nPout * nPout; s++ )
1989 dRedistSourceArea[s] = dGeometricOutputArea[ixSecond][s];
1992 for(
int s = 0; s < nPout * nPout; s++ )
1994 dRedistTargetArea[s] = dataGLLJacobianOut[s / nPout][s % nPout][ixSecond];
1997 if( !fNoConservation )
2000 ( nMonotoneType != 0 ) );
2002 for(
int s = 0; s < nPout * nPout; s++ )
2004 for(
int t = 0; t < nPout * nPout; t++ )
2006 dRedistributionMaps[ixSecond][s][t] *= dRedistTargetArea[s] / dRedistSourceArea[t];
2013 DataArray1D< double > dTotalGeometricArea( dataNodalAreaOut.GetRows() );
2014 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
2016 for(
int s = 0; s < nPout; s++ )
2018 for(
int t = 0; t < nPout; t++ )
2020 dTotalGeometricArea[dataGLLNodesOut[s][t][ixSecond] - 1] +=
2021 dGeometricOutputArea[ixSecond][s * nPout + t];
2029 if( is_root )
dbgprint.printf( 0,
"Assembling map\n" );
2032 DataArray2D< double > dRedistributedOp( nPin * nPin, nPout * nPout );
2034 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
2038 if( ixFirst % outputFrequency == 0 && is_root )
2040 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
2044 int nOverlapFaces = nAllOverlapFaces[ixFirst];
2046 if( !nOverlapFaces )
continue;
2049 for(
int j = 0; j < nOverlapFaces; j++ )
2051 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
2054 if( ixSecondFace < 0 )
continue;
2056 dRedistributedOp.Zero();
2057 for(
int p = 0; p < nPin * nPin; p++ )
2059 for(
int s = 0; s < nPout * nPout; s++ )
2061 for(
int t = 0; t < nPout * nPout; t++ )
2063 dRedistributedOp[p][s] +=
2064 dRedistributionMaps[ixSecondFace][s][t] * dGlobalIntArray[p][ixOverlap + j][t];
2070 for(
int p = 0; p < nPin; p++ )
2072 for(
int q = 0; q < nPin; q++ )
2077 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
2081 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
2085 for(
int s = 0; s < nPout; s++ )
2087 for(
int t = 0; t < nPout; t++ )
2090 if( fContinuousOut )
2092 ixSecondNode = dataGLLNodesOut[s][t][ixSecondFace] - 1;
2094 if( !fNoConservation )
2096 smatMap( ixSecondNode, ixFirstNode ) +=
2097 dRedistributedOp[ixp][ixs] / dataNodalAreaOut[ixSecondNode];
2101 smatMap( ixSecondNode, ixFirstNode ) +=
2102 dRedistributedOp[ixp][ixs] / dTotalGeometricArea[ixSecondNode];
2107 ixSecondNode = ixSecondFace * nPout * nPout + s * nPout + t;
2109 if( !fNoConservation )
2111 smatMap( ixSecondNode, ixFirstNode ) +=
2112 dRedistributedOp[ixp][ixs] / dataGLLJacobianOut[s][t][ixSecondFace];
2116 smatMap( ixSecondNode, ixFirstNode ) +=
2117 dRedistributedOp[ixp][ixs] / dGeometricOutputArea[ixSecondFace][s * nPout + t];
2131 ixOverlap += nOverlapFaces;
2140 const DataArray3D< double >& ,
2141 const DataArray3D< int >& dataGLLNodesOut,
2142 const DataArray3D< double >& ,
2143 const DataArray1D< double >& dataNodalAreaOut,
2148 bool fContinuousOut )
2151 DataArray1D< double > dGL;
2152 DataArray1D< double > dWL;
2154 GaussLobattoQuadrature::GetPoints( nPout, 0.0, 1.0, dGL, dWL );
2157 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
2160 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
2164 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_Pointwise_MOAB]: " );
2167 dbgprint.printf( 0,
"Finite Element to Finite Element (Pointwise) Projection\n" );
2168 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
2169 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
2173 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
2177 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
2179 size_t ixOverlapTemp = ixOverlap;
2180 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
2184 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
break;
2186 nAllOverlapFaces[ixFirst]++;
2190 ixOverlap += nAllOverlapFaces[ixFirst];
2194 DataArray1D< bool > fSecondNodeFound( dataNodalAreaOut.GetRows() );
2198 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
2201 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
2205 if( ixFirst % outputFrequency == 0 && is_root )
2207 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
2211 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
2213 const NodeVector& nodesFirst = m_meshInputCov->nodes;
2216 int nOverlapFaces = nAllOverlapFaces[ixFirst];
2219 for(
int i = 0; i < nOverlapFaces; i++ )
2222 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
2225 if( ixSecond < 0 )
continue;
2227 const NodeVector& nodesSecond = m_meshOutput->nodes;
2228 const Face& faceSecond = m_meshOutput->faces[ixSecond];
2231 for(
int s = 0; s < nPout; s++ )
2233 for(
int t = 0; t < nPout; t++ )
2235 size_t ixSecondNode;
2236 if( fContinuousOut )
2238 ixSecondNode = dataGLLNodesOut[s][t][ixSecond] - 1;
2242 ixSecondNode = ixSecond * nPout * nPout + s * nPout + t;
2245 if( ixSecondNode >= fSecondNodeFound.GetRows() ) _EXCEPTIONT(
"Logic error" );
2248 if( fSecondNodeFound[ixSecondNode] )
continue;
2255 ApplyLocalMap( faceSecond, nodesSecond, dGL[t], dGL[s], node, dDx1G, dDx2G );
2262 ApplyInverseMap( faceFirst, nodesFirst, node, dAlphaIn, dBetaIn );
2265 if( ( dAlphaIn < -1.0e-10 ) || ( dAlphaIn > 1.0 + 1.0e-10 ) || ( dBetaIn < -1.0e-10 ) ||
2266 ( dBetaIn > 1.0 + 1.0e-10 ) )
2270 fSecondNodeFound[ixSecondNode] =
true;
2273 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
2276 for(
int p = 0; p < nPin; p++ )
2278 for(
int q = 0; q < nPin; q++ )
2283 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
2287 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
2290 smatMap( ixSecondNode, ixFirstNode ) += dSampleCoeffIn[p][q];
2298 ixOverlap += nOverlapFaces;
2302 for(
size_t i = 0; i < fSecondNodeFound.GetRows(); i++ )
2304 if( !fSecondNodeFound[i] )
2306 _EXCEPTION1(
"Can't sample point %i", i );