9 #define _USE_MATH_DEFINES
12 #pragma GCC diagnostic push
13 #pragma GCC diagnostic ignored "-Wdeprecated"
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 );
67 output_file <<
"Rows \n";
68 for(
unsigned iv = 0; iv <
row_gdofmap.size(); iv++ )
69 output_file << iv <<
" " <<
row_gdofmap[iv] <<
"\n";
70 output_file <<
"Cols \n";
71 for(
unsigned iv = 0; iv <
col_gdofmap.size(); iv++ )
72 output_file << iv <<
" " <<
col_gdofmap[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];
265 if( ixSecondFaceLoc < 0 )
continue;
267 m_mapRemap( ixSecondFaceLoc, ixFirstFaceLoc ) +=
268 dComposedArray[i][j] / m_meshOutput->vecFaceArea[ixSecondFaceLoc];
273 ixOverlap += nOverlapFaces;
283 int nrows = m_weightMatrix.rows();
284 int ncols = m_weightMatrix.cols();
285 int NNZ = m_weightMatrix.nonZeros();
289 int arr3[6] = { NNZ, nrows, ncols, -NNZ, -nrows, -ncols };
290 int rarr3[6] = {0, 0, 0, 0, 0, 0};
291 MPI_Reduce( arr3, rarr3, 6, MPI_INT, MPI_MIN, 0, m_pcomm->comm() );
293 int total[3] = {0, 0, 0};
294 MPI_Reduce( arr3, total, 3, MPI_INT, MPI_SUM, 0, m_pcomm->comm() );
296 std::cout <<
"-> Rows (min/max/sum): (" << rarr3[1] <<
" / " << -rarr3[4] <<
" / " << total[1] <<
"), "
297 <<
" Cols (min/max/sum): (" << rarr3[2] <<
" / " << -rarr3[5] <<
" / " << total[2] <<
"), "
298 <<
" NNZ (min/max/sum): (" << rarr3[0] <<
" / " << -rarr3[3] <<
" / " << total[0] <<
")\n";
300 std::cout <<
"-> Rows: " << nrows <<
", Cols: " << ncols <<
", NNZ: " << NNZ <<
"\n";
304 #ifdef MOAB_HAVE_EIGEN3
305 void moab::TempestOnlineMap::copy_tempest_sparsemat_to_eigen3()
308 #define VERBOSE_ACTIVATED
313 m_weightMatrix.resize( m_nTotDofs_Dest, m_nTotDofs_SrcCov );
314 m_rowVector.resize( m_weightMatrix.rows() );
315 m_colVector.resize( m_weightMatrix.cols() );
318 int locrows = std::max( m_mapRemap.GetRows(), m_nTotDofs_Dest );
319 int loccols = std::max( m_mapRemap.GetColumns(), m_nTotDofs_SrcCov );
321 std::cout << m_weightMatrix.rows() <<
", " << locrows <<
", " << m_weightMatrix.cols() <<
", " << loccols <<
"\n";
325 DataArray1D< int > lrows;
326 DataArray1D< int > lcols;
327 DataArray1D< double > lvals;
328 m_mapRemap.GetEntries( lrows, lcols, lvals );
329 size_t locvals = lvals.GetRows();
332 typedef Eigen::Triplet< double >
Triplet;
333 std::vector< Triplet > tripletList;
334 tripletList.reserve( locvals );
335 for(
size_t iv = 0; iv < locvals; iv++ )
337 tripletList.push_back(
Triplet( lrows[iv], lcols[iv], lvals[iv] ) );
339 m_weightMatrix.setFromTriplets( tripletList.begin(), tripletList.end() );
340 m_weightMatrix.makeCompressed();
343 std::stringstream sstr;
344 sstr <<
"tempestmatrix.txt.0000" << rank;
345 std::ofstream output_file( sstr.str(), std::ios::out );
346 output_file <<
"0 " << locrows <<
" 0 " << loccols <<
"\n";
347 for(
unsigned iv = 0; iv < locvals; iv++ )
349 output_file << GetRowGlobalDoF( lrows[iv] ) <<
" " << GetColGlobalDoF( lcols[iv] ) <<
" " << lvals[iv]
356 #ifdef VERBOSE_ACTIVATED
357 #undef VERBOSE_ACTIVATED
366 template <
typename T >
370 std::vector< size_t > idx( v.size() );
371 std::iota( idx.begin(), idx.end(), 0 );
377 std::stable_sort( idx.begin(), idx.end(), [&v](
size_t i1,
size_t i2 ) { return fabs( v[i1] ) > fabs( v[i2] ); } );
383 std::vector< double >& dataCorrectedField,
384 std::vector< double >& dataLowerBound,
385 std::vector< double >& dataUpperBound,
386 std::vector< double >& dMassDefect )
388 const size_t nrows = dataCorrectedField.size();
391 std::vector< double > dataCorrection( nrows );
392 double dMassDiffCum = 0.0;
393 double dLMinusU = fabs( dataUpperBound[0] - dataLowerBound[0] );
394 const DataArray1D< double >& dTargetAreas = this->m_remapper->m_target->vecFaceArea;
397 std::vector< std::unordered_set< int > > vecAdjTargetFaces( nrows );
398 constexpr
bool useMOABAdjacencies =
true;
399 #ifdef USE_ComputeAdjacencyRelations
400 if( useMOABAdjacencies )
401 ComputeAdjacencyRelations( vecAdjTargetFaces, caasIteration, m_remapper->m_target_entities,
402 useMOABAdjacencies );
404 ComputeAdjacencyRelations( vecAdjTargetFaces, caasIteration, m_remapper->m_target_entities, useMOABAdjacencies,
405 this->m_remapper->m_target );
411 for(
size_t i = 0; i < nrows; i++ )
415 dataCorrection[
index] = fmax( dataLowerBound[
index], fmin( dataUpperBound[
index], 0.0 ) );
419 dMassL += dTargetAreas[
index] * dataLowerBound[
index];
420 dMassU += dTargetAreas[
index] * dataUpperBound[
index];
421 dLMinusU = fmax( dLMinusU, fabs( dataUpperBound[
index] - dataLowerBound[
index] ) );
422 dMassDiffCum += dMassDefect[
index] - dTargetAreas[
index] * dataCorrection[
index];
424 #ifndef USE_ComputeAdjacencyRelations
428 if( useMOABAdjacencies )
432 ents.
insert( m_remapper->m_target_entities[
index] );
438 int adjIndex = m_remapper->m_target_entities.index( *it );
440 if( adjIndex >= 0 ) vecAdjTargetFaces[
index].insert( adjIndex );
446 GetAdjacentFaceVectorByEdge( *this->m_remapper->m_target,
index,
447 ( m_output_order + 1 ) * ( m_output_order + 1 ) * ( m_output_order + 1 ),
453 for(
auto adjFace : vecAdjFaces )
454 if( adjFace.first >= 0 )
455 vecAdjTargetFaces[
index].insert( adjFace.first );
462 std::vector< double > localDefects( 5, 0.0 ), globalDefects( 5, 0.0 );
463 localDefects[0] = dMassL;
464 localDefects[1] = dMassU;
465 localDefects[2] = dMassDiffCum;
466 localDefects[3] = dLMinusU;
469 MPI_Allreduce( localDefects.data(), globalDefects.data(), 4, MPI_DOUBLE, MPI_SUM, m_pcomm->comm() );
471 dMassL = globalDefects[0];
472 dMassU = globalDefects[1];
473 dMassDiffCum = globalDefects[2];
474 dLMinusU = globalDefects[3];
479 if( fabs( dMassDiffCum ) < 1e-15 || dLMinusU < 1e-15 )
481 for(
size_t i = 0; i < nrows; i++ )
482 dataCorrectedField[i] += dataCorrection[i];
487 if( dMassL > dMassDiffCum )
489 Announce(
"Lower bound mass exceeds target mass by %1.15e: CAAS will need another iteration",
490 dMassL - dMassDiffCum );
491 dMassDiffCum = dMassL;
494 else if( dMassU < dMassDiffCum )
496 Announce(
"Target mass exceeds upper bound mass by %1.15e: CAAS will need another iteration",
497 dMassDiffCum - dMassU );
498 dMassDiffCum = dMassU;
504 for(
size_t i = 0; i < nrows; i++ )
508 const std::unordered_set< int >& neighbors = vecAdjTargetFaces[
index];
509 if( dMassDefect[
index] > 0.0 )
511 double dMassCorrectU = 0.0;
512 for(
auto it : neighbors )
513 dMassCorrectU += dTargetAreas[it] * ( dataUpperBound[it] - dataCorrection[it] );
516 for(
auto it : neighbors )
517 dataCorrection[it] +=
518 dMassDefect[
index] * ( dataUpperBound[it] - dataCorrection[it] ) / dMassCorrectU;
522 double dMassCorrectL = 0.0;
523 for(
auto it : neighbors )
524 dMassCorrectL += dTargetAreas[it] * ( dataCorrection[it] - dataLowerBound[it] );
527 for(
auto it : neighbors )
528 dataCorrection[it] +=
529 dMassDefect[
index] * ( dataCorrection[it] - dataLowerBound[it] ) / dMassCorrectL;
533 for(
size_t i = 0; i < nrows; i++ )
534 dataCorrectedField[i] += dataCorrection[i];
541 std::vector< double >& dataLowerBound,
542 std::vector< double >& dataUpperBound,
545 const size_t nrows = dataCorrectedField.size();
548 std::vector< double > dataCorrection( nrows );
549 const DataArray1D< double >& dTargetAreas = this->m_remapper->m_target->vecFaceArea;
550 double dMassDiff = dMass;
551 double dLMinusU = fabs( dataUpperBound[0] - dataLowerBound[0] );
552 double dMassCorrectU = 0.0;
553 double dMassCorrectL = 0.0;
554 for(
size_t i = 0; i < nrows; i++ )
556 dataCorrection[i] = fmax( dataLowerBound[i], fmin( dataUpperBound[i], 0.0 ) );
557 dMassL += dTargetAreas[i] * dataLowerBound[i];
558 dMassU += dTargetAreas[i] * dataUpperBound[i];
559 dMassDiff -= dTargetAreas[i] * dataCorrection[i];
560 dLMinusU = fmax( dLMinusU, fabs( dataUpperBound[i] - dataLowerBound[i] ) );
561 dMassCorrectL += dTargetAreas[i] * ( dataCorrection[i] - dataLowerBound[i] );
562 dMassCorrectU += dTargetAreas[i] * ( dataUpperBound[i] - dataCorrection[i] );
566 std::vector< double > localDefects( 5, 0.0 ), globalDefects( 5, 0.0 );
567 localDefects[0] = dMassL;
568 localDefects[1] = dMassU;
569 localDefects[2] = dMassDiff;
570 localDefects[3] = dMassCorrectL;
571 localDefects[4] = dMassCorrectU;
573 MPI_Allreduce( localDefects.data(), globalDefects.data(), 5, MPI_DOUBLE, MPI_SUM, m_pcomm->comm() );
575 dMassL = globalDefects[0];
576 dMassU = globalDefects[1];
577 dMassDiff = globalDefects[2];
578 dMassCorrectL = globalDefects[3];
579 dMassCorrectU = globalDefects[4];
583 if( fabs( dMassDiff ) < 1e-15 || fabs( dLMinusU ) < 1e-15 )
585 for(
size_t i = 0; i < nrows; i++ )
586 dataCorrectedField[i] += dataCorrection[i];
591 if( dMassL > dMassDiff )
593 Announce(
"%d: Lower bound mass exceeds target mass by %1.15e: CAAS will need another iteration", rank,
594 dMassL - dMassDiff );
598 else if( dMassU < dMassDiff )
600 Announce(
"%d: Target mass exceeds upper bound mass by %1.15e: CAAS will need another iteration", rank,
601 dMassDiff - dMassU );
607 DataArray1D< double > dataMassVec( nrows );
608 if( dMassDiff > 0.0 )
610 for(
size_t i = 0; i < nrows; i++ )
612 dataMassVec[i] = ( dataUpperBound[i] - dataCorrection[i] ) / dMassCorrectU;
613 dataCorrection[i] += dMassDiff * dataMassVec[i];
618 for(
size_t i = 0; i < nrows; i++ )
620 dataMassVec[i] = ( dataCorrection[i] - dataLowerBound[i] ) / dMassCorrectL;
621 dataCorrection[i] += dMassDiff * dataMassVec[i];
625 for(
size_t i = 0; i < nrows; i++ )
626 dataCorrectedField[i] += dataCorrection[i];
633 std::vector< double >& dataOutDouble,
640 assert( !dataGLLNodesSrcCov.IsAttached() && !dataGLLNodesDest.IsAttached() );
642 std::pair< double, double > massDefect( 0.0, 0.0 );
645 const size_t nTargetCount = dataOutDouble.size();
646 const DataArray1D< double >& m_dOverlapAreas = this->m_remapper->m_overlap->vecFaceArea;
649 double dMassDiff = 0.0;
650 std::vector< double > x( nTargetCount );
651 std::vector< double > dataLowerBound( nTargetCount );
652 std::vector< double > dataUpperBound( nTargetCount );
653 std::vector< double > massVector( nTargetCount );
654 std::vector< std::unordered_set< int > > vecSourceOvTarget( nTargetCount );
656 #undef USE_ComputeAdjacencyRelations
657 constexpr
bool useMOABAdjacencies =
true;
658 #ifdef USE_ComputeAdjacencyRelations
662 if( caasType == CAAS_QLT || caasType == CAAS_LOCAL_ADJACENT )
664 if( useMOABAdjacencies )
667 ComputeAdjacencyRelations( vecSourceOvTarget, caasIteration, m_remapper->m_covering_source_entities,
673 ComputeAdjacencyRelations( vecSourceOvTarget, caasIteration, m_remapper->m_covering_source_entities,
674 useMOABAdjacencies, m_meshInputCov );
MB_CHK_SET_ERR_CONT( rval,
"Failed to get adjacent faces" );
682 double dSourceMin = dataInDouble[0];
683 double dSourceMax = dataInDouble[0];
684 double dTargetMin = dataOutDouble[0];
685 double dTargetMax = dataOutDouble[0];
686 for(
size_t i = 0; i < m_meshOverlap->faces.size(); i++ )
688 const int ixS = m_meshOverlap->vecSourceFaceIx[i];
689 const int ixT = m_meshOverlap->vecTargetFaceIx[i];
691 if( ixT < 0 )
continue;
693 assert( m_dOverlapAreas[i] > 0.0 );
697 #ifndef USE_ComputeAdjacencyRelations
699 vecSourceOvTarget[ixT].insert( ixS );
700 if( ( caasType == CAAS_QLT || caasType == CAAS_LOCAL_ADJACENT ) )
702 if( useMOABAdjacencies )
705 ents.
insert( m_remapper->m_covering_source_entities[ixS] );
710 int adjIndex = m_remapper->m_covering_source_entities.index( *it );
711 if( adjIndex >= 0 ) vecSourceOvTarget[ixT].insert( adjIndex );
718 GetAdjacentFaceVectorByEdge( *m_meshInputCov, ixS,
719 ( caasIteration ) * ( m_input_order + 1 ) * ( m_input_order + 1 ),
723 for(
size_t iadj = 0; iadj < vecAdjFaces.size(); iadj++ )
724 vecSourceOvTarget[ixT].insert( vecAdjFaces[iadj].
first );
730 dSourceMax = fmax( dSourceMax, dataInDouble[ixS] );
731 dSourceMin = fmin( dSourceMin, dataInDouble[ixS] );
734 dTargetMin = fmin( dTargetMin, dataOutDouble[ixT] );
735 dTargetMax = fmax( dTargetMax, dataOutDouble[ixT] );
737 const double locMassDiff = ( dataInDouble[ixS] * m_dOverlapAreas[i] ) -
738 ( dataOutDouble[ixT] * m_dOverlapAreas[i] );
742 dMassDiff += locMassDiff;
743 massVector[ixT] += locMassDiff;
747 std::vector< double > localMinMaxDefects( 5, 0.0 ), globalMinMaxDefects( 5, 0.0 );
748 localMinMaxDefects[0] = dSourceMin;
749 localMinMaxDefects[1] = dTargetMin;
750 localMinMaxDefects[2] = dSourceMax;
751 localMinMaxDefects[3] = dTargetMax;
752 localMinMaxDefects[4] = dMassDiff;
754 if( caasType == CAAS_GLOBAL )
756 MPI_Allreduce( localMinMaxDefects.data(), globalMinMaxDefects.data(), 2, MPI_DOUBLE, MPI_MIN, m_pcomm->comm() );
757 MPI_Allreduce( localMinMaxDefects.data() + 2, globalMinMaxDefects.data() + 2, 2, MPI_DOUBLE, MPI_MAX,
759 dSourceMin = globalMinMaxDefects[0];
760 dSourceMax = globalMinMaxDefects[2];
761 dTargetMin = globalMinMaxDefects[1];
762 dTargetMax = globalMinMaxDefects[3];
764 if( caasIteration == 1 )
765 MPI_Allreduce( localMinMaxDefects.data() + 4, globalMinMaxDefects.data() + 4, 1, MPI_DOUBLE, MPI_SUM,
768 globalMinMaxDefects[4] = mismatch;
770 dMassDiff = localMinMaxDefects[4];
772 massDefect.first = globalMinMaxDefects[4];
776 massDefect.first = dMassDiff;
781 if( fabs( massDefect.first ) > 1e-20 )
783 if( caasType == CAAS_GLOBAL )
785 for(
size_t i = 0; i < nTargetCount; i++ )
787 dataLowerBound[i] = dSourceMin - dataOutDouble[i];
788 dataUpperBound[i] = dSourceMax - dataOutDouble[i];
794 std::vector< double > vecLocalUpperBound( nTargetCount );
795 std::vector< double > vecLocalLowerBound( nTargetCount );
798 for(
size_t i = 0; i < nTargetCount; i++ )
800 assert( vecSourceOvTarget[i].size() );
803 double dMaxI = -1E10;
806 for(
const auto& srcElem : vecSourceOvTarget[i] )
808 dMinI = fmin( dMinI, dataInDouble[srcElem] );
809 dMaxI = fmax( dMaxI, dataInDouble[srcElem] );
813 vecLocalLowerBound[i] = dMinI;
814 vecLocalUpperBound[i] = dMaxI;
817 for(
size_t i = 0; i < nTargetCount; i++ )
819 dataLowerBound[i] = vecLocalLowerBound[i] - dataOutDouble[i];
820 dataUpperBound[i] = vecLocalUpperBound[i] - dataOutDouble[i];
825 if( fabs( dMassDiff ) > 1e-20 )
827 if( caasType == CAAS_QLT )
828 dMassDiff = QLTLimiter( caasIteration, dataOutDouble, dataLowerBound, dataUpperBound, massVector );
830 CAASLimiter( dataOutDouble, dataLowerBound, dataUpperBound, dMassDiff );
834 double dMassDiffPost = 0.0;
835 for(
size_t i = 0; i < m_meshOverlap->faces.size(); i++ )
837 const int ixS = m_meshOverlap->vecSourceFaceIx[i];
838 const int ixT = m_meshOverlap->vecTargetFaceIx[i];
840 if( ixT < 0 )
continue;
844 dMassDiffPost += ( dataInDouble[ixS] * m_dOverlapAreas[i] ) -
845 ( dataOutDouble[ixT] * m_dOverlapAreas[i] );
848 massDefect.second = dMassDiffPost;
859 const DataArray1D< double >& vecTargetArea,
860 DataArray2D< double >& dCoeff,
862 bool fSparseConstraints =
false );
867 const DataArray1D< double >& vecTargetArea,
868 DataArray2D< double >& dCoeff,
874 const DataArray3D< double >& dataGLLJacobian,
877 bool fNoConservation,
878 bool fSparseConstraints )
881 int nP = dataGLLNodes.GetRows();
884 const int TriQuadRuleOrder = 4;
887 TriangularQuadratureRule triquadrule( TriQuadRuleOrder );
889 int TriQuadraturePoints = triquadrule.GetPoints();
891 const DataArray2D< double >& TriQuadratureG = triquadrule.GetG();
893 const DataArray1D< double >& TriQuadratureW = triquadrule.GetW();
896 DataArray2D< double > dSampleCoeff( nP, nP );
899 DataArray1D< double > dG;
900 DataArray1D< double > dW;
901 GaussLobattoQuadrature::GetPoints( nP, 0.0, 1.0, dG, dW );
905 dbgprint.set_prefix(
"[LinearRemapSE4_Tempest_MOAB]: " );
908 dbgprint.printf( 0,
"Finite Element to Finite Volume Projection\n" );
909 dbgprint.printf( 0,
"Triangular quadrature rule order %i\n", TriQuadRuleOrder );
910 dbgprint.printf( 0,
"Order of the FE polynomial interpolant: %i\n", nP );
914 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
917 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
918 const NodeVector& nodesFirst = m_meshInputCov->nodes;
921 DataArray1D< double > vecSourceArea( nP * nP );
923 DataArray1D< double > vecTargetArea;
924 DataArray2D< double > dCoeff;
927 std::stringstream sstr;
928 sstr <<
"remapdata_" << rank <<
".txt";
929 std::ofstream output_file( sstr.str() );
935 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
943 NodeVector nodes( 3 );
944 faceTri.SetNode( 0, 0 );
945 faceTri.SetNode( 1, 1 );
946 faceTri.SetNode( 2, 2 );
949 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
951 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
953 if( faceFirst.edges.size() != 4 )
955 _EXCEPTIONT(
"Only quadrilateral elements allowed for SE remapping" );
959 if( ixFirst % outputFrequency == 0 && is_root )
961 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
969 int nOverlapFaces = 0;
970 size_t ixOverlapTemp = ixOverlap;
971 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
975 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
break;
981 if( nOverlapFaces == 0 )
continue;
984 DataArray3D< double > dRemapCoeff( nP, nP, nOverlapFaces );
987 for(
int j = 0; j < nOverlapFaces; j++ )
989 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + j];
990 if( m_meshOverlap->vecFaceArea[ixOverlap + j] < std::numeric_limits<double>::epsilon() )
993 Announce(
"Very small overlap at index %i area polygon: (%1.10e )", ixOverlap + j,
994 m_meshOverlap->vecFaceArea[ixOverlap + j] );
995 int n = faceOverlap.edges.size();
996 Announce(
"Number nodes: %d", n );
997 for(
int k = 0; k < n; k++ )
999 Node nd = nodesOverlap[faceOverlap[k]];
1000 Announce(
"Node %d %d : %1.10e %1.10e %1.10e ", k, faceOverlap[k], nd.x, nd.y, nd.z );
1006 int nbEdges = faceOverlap.edges.size();
1007 int nOverlapTriangles = 1;
1011 nOverlapTriangles = nbEdges;
1012 for(
int k = 0; k < nbEdges; k++ )
1014 const Node& node = nodesOverlap[faceOverlap[k]];
1021 Node node0, node1, node2;
1022 double dTriangleArea;
1025 for(
int k = 0; k < nOverlapTriangles; k++ )
1029 node0 = nodesOverlap[faceOverlap[0]];
1030 node1 = nodesOverlap[faceOverlap[1]];
1031 node2 = nodesOverlap[faceOverlap[2]];
1032 dTriangleArea = CalculateFaceArea( faceOverlap, nodesOverlap );
1037 node1 = nodesOverlap[faceOverlap[k]];
1038 int k1 = ( k + 1 ) % nbEdges;
1039 node2 = nodesOverlap[faceOverlap[k1]];
1043 dTriangleArea = CalculateFaceArea( faceTri, nodes );
1046 for(
int l = 0; l < TriQuadraturePoints; l++ )
1048 Node nodeQuadrature;
1049 nodeQuadrature.x = TriQuadratureG[l][0] * node0.x + TriQuadratureG[l][1] * node1.x +
1050 TriQuadratureG[l][2] * node2.x;
1052 nodeQuadrature.y = TriQuadratureG[l][0] * node0.y + TriQuadratureG[l][1] * node1.y +
1053 TriQuadratureG[l][2] * node2.y;
1055 nodeQuadrature.z = TriQuadratureG[l][0] * node0.z + TriQuadratureG[l][1] * node1.z +
1056 TriQuadratureG[l][2] * node2.z;
1058 nodeQuadrature = nodeQuadrature.Normalized();
1065 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlpha, dBeta );
1068 if( ( dAlpha < -1.0e-13 ) || ( dAlpha > 1.0 + 1.0e-13 ) || ( dBeta < -1.0e-13 ) ||
1069 ( dBeta > 1.0 + 1.0e-13 ) )
1071 _EXCEPTION4(
"Inverse Map for element %d and subtriangle %d out of range "
1073 j, l, dAlpha, dBeta );
1077 SampleGLLFiniteElement( nMonotoneType, nP, dAlpha, dBeta, dSampleCoeff );
1080 for(
int p = 0; p < nP; p++ )
1082 for(
int q = 0; q < nP; q++ )
1084 dRemapCoeff[p][q][j] += TriQuadratureW[l] * dTriangleArea * dSampleCoeff[p][q] /
1085 m_meshOverlap->vecFaceArea[ixOverlap + j];
1093 output_file <<
"[" << ( ixFirst < (int)col_gdofmap.size() ? (int)col_gdofmap[ixFirst] : -1 ) <<
"] \t";
1094 for(
int j = 0; j < nOverlapFaces; j++ )
1096 for(
int p = 0; p < nP; p++ )
1098 for(
int q = 0; q < nP; q++ )
1100 output_file << dRemapCoeff[p][q][j] <<
" ";
1104 output_file << std::endl;
1108 if( !fNoConservation )
1110 double dTargetArea = 0.0;
1111 for(
int j = 0; j < nOverlapFaces; j++ )
1113 dTargetArea += m_meshOverlap->vecFaceArea[ixOverlap + j];
1116 for(
int p = 0; p < nP; p++ )
1118 for(
int q = 0; q < nP; q++ )
1120 vecSourceArea[p * nP + q] = dataGLLJacobian[p][q][ixFirst];
1124 const double areaTolerance = 1e-10;
1126 if( fabs( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea ) <= areaTolerance )
1128 vecTargetArea.Allocate( nOverlapFaces );
1129 for(
int j = 0; j < nOverlapFaces; j++ )
1131 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
1134 dCoeff.Allocate( nOverlapFaces, nP * nP );
1136 for(
int j = 0; j < nOverlapFaces; j++ )
1138 for(
int p = 0; p < nP; p++ )
1140 for(
int q = 0; q < nP; q++ )
1142 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
1149 else if( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea > areaTolerance )
1151 double dExtraneousArea = m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea;
1153 vecTargetArea.Allocate( nOverlapFaces + 1 );
1154 for(
int j = 0; j < nOverlapFaces; j++ )
1156 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
1158 vecTargetArea[nOverlapFaces] = dExtraneousArea;
1161 Announce(
"Partial volume: %i (%1.10e / %1.10e)", ixFirst, dTargetArea,
1162 m_meshInputCov->vecFaceArea[ixFirst] );
1164 if( dTargetArea > m_meshInputCov->vecFaceArea[ixFirst] )
1166 _EXCEPTIONT(
"Partial element area exceeds total element area" );
1169 dCoeff.Allocate( nOverlapFaces + 1, nP * nP );
1171 for(
int j = 0; j < nOverlapFaces; j++ )
1173 for(
int p = 0; p < nP; p++ )
1175 for(
int q = 0; q < nP; q++ )
1177 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
1181 for(
int p = 0; p < nP; p++ )
1183 for(
int q = 0; q < nP; q++ )
1185 dCoeff[nOverlapFaces][p * nP + q] = dataGLLJacobian[p][q][ixFirst];
1188 for(
int j = 0; j < nOverlapFaces; j++ )
1190 for(
int p = 0; p < nP; p++ )
1192 for(
int q = 0; q < nP; q++ )
1194 dCoeff[nOverlapFaces][p * nP + q] -=
1195 dRemapCoeff[p][q][j] * m_meshOverlap->vecFaceArea[ixOverlap + j];
1199 for(
int p = 0; p < nP; p++ )
1201 for(
int q = 0; q < nP; q++ )
1203 dCoeff[nOverlapFaces][p * nP + q] /= dExtraneousArea;
1211 Announce(
"Coverage area: %1.10e, and target element area: %1.10e)", ixFirst,
1212 m_meshInputCov->vecFaceArea[ixFirst], dTargetArea );
1213 _EXCEPTIONT(
"Target grid must be a subset of source grid" );
1217 fSparseConstraints );
1219 for(
int j = 0; j < nOverlapFaces; j++ )
1221 for(
int p = 0; p < nP; p++ )
1223 for(
int q = 0; q < nP; q++ )
1225 dRemapCoeff[p][q][j] = dCoeff[j][p * nP + q];
1247 for(
int j = 0; j < nOverlapFaces; j++ )
1249 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
1252 if( ixSecondFace < 0 )
continue;
1254 for(
int p = 0; p < nP; p++ )
1256 for(
int q = 0; q < nP; q++ )
1260 int ixFirstNode = dataGLLNodes[p][q][ixFirst] - 1;
1262 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
1263 m_meshOverlap->vecFaceArea[ixOverlap + j] /
1264 m_meshOutput->vecFaceArea[ixSecondFace];
1268 int ixFirstNode = ixFirst * nP * nP + p * nP + q;
1270 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
1271 m_meshOverlap->vecFaceArea[ixOverlap + j] /
1272 m_meshOutput->vecFaceArea[ixSecondFace];
1278 ixOverlap += nOverlapFaces;
1281 output_file.flush();
1282 output_file.close();
1291 const DataArray3D< double >& dataGLLJacobianIn,
1292 const DataArray3D< int >& dataGLLNodesOut,
1293 const DataArray3D< double >& dataGLLJacobianOut,
1294 const DataArray1D< double >& dataNodalAreaOut,
1299 bool fContinuousOut,
1300 bool fNoConservation )
1303 TriangularQuadratureRule triquadrule( 8 );
1305 const DataArray2D< double >& dG = triquadrule.GetG();
1306 const DataArray1D< double >& dW = triquadrule.GetW();
1309 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
1312 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
1313 DataArray2D< double > dSampleCoeffOut( nPout, nPout );
1317 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_MOAB]: " );
1320 dbgprint.printf( 0,
"Finite Element to Finite Element Projection\n" );
1321 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
1322 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
1326 DataArray3D< double > dGlobalIntArray( nPin * nPin, m_meshOverlap->faces.size(), nPout * nPout );
1329 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
1332 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1335 int nOverlapFaces = 0;
1336 size_t ixOverlapTemp = ixOverlap;
1337 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
1340 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
1348 nAllOverlapFaces[ixFirst] = nOverlapFaces;
1351 ixOverlap += nAllOverlapFaces[ixFirst];
1355 DataArray2D< double > dGeometricOutputArea( m_meshOutput->faces.size(), nPout * nPout );
1358 DataArray2D< double > dOverlapOutputArea( m_meshOverlap->faces.size(), nPout * nPout );
1363 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
1365 if( is_root )
dbgprint.printf( 0,
"Building conservative distribution maps\n" );
1373 NodeVector nodes( 3 );
1374 faceTri.SetNode( 0, 0 );
1375 faceTri.SetNode( 1, 1 );
1376 faceTri.SetNode( 2, 2 );
1378 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1382 if( ixFirst % outputFrequency == 0 && is_root )
1384 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1388 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
1390 const NodeVector& nodesFirst = m_meshInputCov->nodes;
1393 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1395 if( !nOverlapFaces )
continue;
1406 for(
int i = 0; i < nOverlapFaces; i++ )
1409 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + i];
1411 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
1414 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
1417 if( ixSecond < 0 )
continue;
1419 const NodeVector& nodesSecond = m_meshOutput->nodes;
1421 const Face& faceSecond = m_meshOutput->faces[ixSecond];
1423 int nbEdges = faceOverlap.edges.size();
1424 int nOverlapTriangles = 1;
1428 nOverlapTriangles = nbEdges;
1429 for(
int k = 0; k < nbEdges; k++ )
1431 const Node& node = nodesOverlap[faceOverlap[k]];
1438 Node node0, node1, node2;
1442 for(
int j = 0; j < nOverlapTriangles; j++ )
1446 node0 = nodesOverlap[faceOverlap[0]];
1447 node1 = nodesOverlap[faceOverlap[1]];
1448 node2 = nodesOverlap[faceOverlap[2]];
1449 dTriArea = CalculateFaceArea( faceOverlap, nodesOverlap );
1454 node1 = nodesOverlap[faceOverlap[j]];
1455 int j1 = ( j + 1 ) % nbEdges;
1456 node2 = nodesOverlap[faceOverlap[j1]];
1460 dTriArea = CalculateFaceArea( faceTri, nodes );
1463 for(
int k = 0; k < triquadrule.GetPoints(); k++ )
1468 dX[0] = dG( k, 0 ) * node0.x + dG( k, 1 ) * node1.x + dG( k, 2 ) * node2.x;
1469 dX[1] = dG( k, 0 ) * node0.y + dG( k, 1 ) * node1.y + dG( k, 2 ) * node2.y;
1470 dX[2] = dG( k, 0 ) * node0.z + dG( k, 1 ) * node1.z + dG( k, 2 ) * node2.z;
1472 double dMag = sqrt( dX[0] * dX[0] + dX[1] * dX[1] + dX[2] * dX[2] );
1478 Node nodeQuadrature( dX[0], dX[1], dX[2] );
1485 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlphaIn, dBetaIn );
1492 ApplyInverseMap( faceSecond, nodesSecond, nodeQuadrature, dAlphaOut, dBetaOut );
1512 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
1515 SampleGLLFiniteElement( nMonotoneType, nPout, dAlphaOut, dBetaOut, dSampleCoeffOut );
1518 for(
int s = 0; s < nPout; s++ )
1520 for(
int t = 0; t < nPout; t++ )
1522 double dNodeArea = dSampleCoeffOut[s][t] * dW[k] * dTriArea;
1524 dOverlapOutputArea[ixOverlap + i][s * nPout + t] += dNodeArea;
1526 dGeometricOutputArea[ixSecond][s * nPout + t] += dNodeArea;
1532 for(
int p = 0; p < nPin; p++ )
1534 for(
int q = 0; q < nPin; q++ )
1537 for(
int s = 0; s < nPout; s++ )
1539 for(
int t = 0; t < nPout; t++ )
1542 dGlobalIntArray[ixp][ixOverlap + i][ixs] +=
1543 dSampleCoeffOut[s][t] * dSampleCoeffIn[p][q] * dW[k] * dTriArea;
1557 DataArray2D< double > dCoeff( nOverlapFaces * nPout * nPout, nPin * nPin );
1559 for(
int i = 0; i < nOverlapFaces; i++ )
1564 for(
int p = 0; p < nPin; p++ )
1566 for(
int q = 0; q < nPin; q++ )
1569 for(
int s = 0; s < nPout; s++ )
1571 for(
int t = 0; t < nPout; t++ )
1573 dCoeff[i * nPout * nPout + ixs][ixp] = dGlobalIntArray[ixp][ixOverlap + i][ixs] /
1574 dOverlapOutputArea[ixOverlap + i][s * nPout + t];
1586 DataArray1D< double > vecSourceArea( nPin * nPin );
1588 for(
int p = 0; p < nPin; p++ )
1590 for(
int q = 0; q < nPin; q++ )
1592 vecSourceArea[p * nPin + q] = dataGLLJacobianIn[p][q][ixFirst];
1597 DataArray1D< double > vecTargetArea( nOverlapFaces * nPout * nPout );
1599 for(
int i = 0; i < nOverlapFaces; i++ )
1603 for(
int s = 0; s < nPout; s++ )
1605 for(
int t = 0; t < nPout; t++ )
1607 vecTargetArea[i * nPout * nPout + ixs] = dOverlapOutputArea[ixOverlap + i][nPout * s + t];
1615 if( !fNoConservation )
1621 for(
int i = 0; i < nOverlapFaces; i++ )
1624 for(
int p = 0; p < nPin; p++ )
1626 for(
int q = 0; q < nPin; q++ )
1629 for(
int s = 0; s < nPout; s++ )
1631 for(
int t = 0; t < nPout; t++ )
1633 dGlobalIntArray[ixp][ixOverlap + i][ixs] =
1634 dCoeff[i * nPout * nPout + ixs][ixp] * dOverlapOutputArea[ixOverlap + i][s * nPout + t];
1647 for(
int i = 0; i < nPin * nPin; i++ )
1649 double dColSum = 0.0;
1650 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1652 dColSum += dCoeff[j][i] * vecTargetArea[j];
1654 printf(
"Col %i: %1.15e\n", i, dColSum / vecSourceArea[i] );
1658 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1660 double dRowSum = 0.0;
1661 for(
int i = 0; i < nPin * nPin; i++ )
1663 dRowSum += dCoeff[j][i];
1665 printf(
"Row %i: %1.15e\n", j, dRowSum );
1670 ixOverlap += nOverlapFaces;
1674 if( is_root )
dbgprint.printf( 0,
"Building redistribution maps on target mesh\n" );
1675 DataArray1D< double > dRedistSourceArea( nPout * nPout );
1676 DataArray1D< double > dRedistTargetArea( nPout * nPout );
1677 std::vector< DataArray2D< double > > dRedistributionMaps;
1678 dRedistributionMaps.resize( m_meshOutput->faces.size() );
1680 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
1682 dRedistributionMaps[ixSecond].Allocate( nPout * nPout, nPout * nPout );
1684 for(
int i = 0; i < nPout * nPout; i++ )
1686 dRedistributionMaps[ixSecond][i][i] = 1.0;
1689 for(
int s = 0; s < nPout * nPout; s++ )
1691 dRedistSourceArea[s] = dGeometricOutputArea[ixSecond][s];
1694 for(
int s = 0; s < nPout * nPout; s++ )
1696 dRedistTargetArea[s] = dataGLLJacobianOut[s / nPout][s % nPout][ixSecond];
1699 if( !fNoConservation )
1702 ( nMonotoneType != 0 ) );
1704 for(
int s = 0; s < nPout * nPout; s++ )
1706 for(
int t = 0; t < nPout * nPout; t++ )
1708 dRedistributionMaps[ixSecond][s][t] *= dRedistTargetArea[s] / dRedistSourceArea[t];
1715 DataArray1D< double > dTotalGeometricArea( dataNodalAreaOut.GetRows() );
1716 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
1718 for(
int s = 0; s < nPout; s++ )
1720 for(
int t = 0; t < nPout; t++ )
1722 dTotalGeometricArea[dataGLLNodesOut[s][t][ixSecond] - 1] +=
1723 dGeometricOutputArea[ixSecond][s * nPout + t];
1731 if( is_root )
dbgprint.printf( 0,
"Assembling map\n" );
1734 DataArray2D< double > dRedistributedOp( nPin * nPin, nPout * nPout );
1736 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1740 if( ixFirst % outputFrequency == 0 && is_root )
1742 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1746 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1748 if( !nOverlapFaces )
continue;
1751 for(
int j = 0; j < nOverlapFaces; j++ )
1753 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
1756 if( ixSecondFace < 0 )
continue;
1758 dRedistributedOp.Zero();
1759 for(
int p = 0; p < nPin * nPin; p++ )
1761 for(
int s = 0; s < nPout * nPout; s++ )
1763 for(
int t = 0; t < nPout * nPout; t++ )
1765 dRedistributedOp[p][s] +=
1766 dRedistributionMaps[ixSecondFace][s][t] * dGlobalIntArray[p][ixOverlap + j][t];
1772 for(
int p = 0; p < nPin; p++ )
1774 for(
int q = 0; q < nPin; q++ )
1779 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
1783 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
1787 for(
int s = 0; s < nPout; s++ )
1789 for(
int t = 0; t < nPout; t++ )
1792 if( fContinuousOut )
1794 ixSecondNode = dataGLLNodesOut[s][t][ixSecondFace] - 1;
1796 if( !fNoConservation )
1798 smatMap( ixSecondNode, ixFirstNode ) +=
1799 dRedistributedOp[ixp][ixs] / dataNodalAreaOut[ixSecondNode];
1803 smatMap( ixSecondNode, ixFirstNode ) +=
1804 dRedistributedOp[ixp][ixs] / dTotalGeometricArea[ixSecondNode];
1809 ixSecondNode = ixSecondFace * nPout * nPout + s * nPout + t;
1811 if( !fNoConservation )
1813 smatMap( ixSecondNode, ixFirstNode ) +=
1814 dRedistributedOp[ixp][ixs] / dataGLLJacobianOut[s][t][ixSecondFace];
1818 smatMap( ixSecondNode, ixFirstNode ) +=
1819 dRedistributedOp[ixp][ixs] / dGeometricOutputArea[ixSecondFace][s * nPout + t];
1833 ixOverlap += nOverlapFaces;
1842 const DataArray3D< double >& ,
1843 const DataArray3D< int >& dataGLLNodesOut,
1844 const DataArray3D< double >& ,
1845 const DataArray1D< double >& dataNodalAreaOut,
1850 bool fContinuousOut )
1853 DataArray1D< double > dGL;
1854 DataArray1D< double > dWL;
1856 GaussLobattoQuadrature::GetPoints( nPout, 0.0, 1.0, dGL, dWL );
1859 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
1862 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
1866 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_Pointwise_MOAB]: " );
1869 dbgprint.printf( 0,
"Finite Element to Finite Element (Pointwise) Projection\n" );
1870 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
1871 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
1875 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
1879 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1881 size_t ixOverlapTemp = ixOverlap;
1882 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
1886 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
break;
1888 nAllOverlapFaces[ixFirst]++;
1892 ixOverlap += nAllOverlapFaces[ixFirst];
1896 DataArray1D< bool > fSecondNodeFound( dataNodalAreaOut.GetRows() );
1900 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
1903 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1907 if( ixFirst % outputFrequency == 0 && is_root )
1909 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1913 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
1915 const NodeVector& nodesFirst = m_meshInputCov->nodes;
1918 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1921 for(
int i = 0; i < nOverlapFaces; i++ )
1924 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
1927 if( ixSecond < 0 )
continue;
1929 const NodeVector& nodesSecond = m_meshOutput->nodes;
1930 const Face& faceSecond = m_meshOutput->faces[ixSecond];
1933 for(
int s = 0; s < nPout; s++ )
1935 for(
int t = 0; t < nPout; t++ )
1937 size_t ixSecondNode;
1938 if( fContinuousOut )
1940 ixSecondNode = dataGLLNodesOut[s][t][ixSecond] - 1;
1944 ixSecondNode = ixSecond * nPout * nPout + s * nPout + t;
1947 if( ixSecondNode >= fSecondNodeFound.GetRows() ) _EXCEPTIONT(
"Logic error" );
1950 if( fSecondNodeFound[ixSecondNode] )
continue;
1957 ApplyLocalMap( faceSecond, nodesSecond, dGL[t], dGL[s], node, dDx1G, dDx2G );
1964 ApplyInverseMap( faceFirst, nodesFirst, node, dAlphaIn, dBetaIn );
1967 if( ( dAlphaIn < -1.0e-10 ) || ( dAlphaIn > 1.0 + 1.0e-10 ) || ( dBetaIn < -1.0e-10 ) ||
1968 ( dBetaIn > 1.0 + 1.0e-10 ) )
1972 fSecondNodeFound[ixSecondNode] =
true;
1975 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
1978 for(
int p = 0; p < nPin; p++ )
1980 for(
int q = 0; q < nPin; q++ )
1985 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
1989 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
1992 smatMap( ixSecondNode, ixFirstNode ) += dSampleCoeffIn[p][q];
2000 ixOverlap += nOverlapFaces;
2004 for(
size_t i = 0; i < fSecondNodeFound.GetRows(); i++ )
2006 if( !fSecondNodeFound[i] )
2008 _EXCEPTION1(
"Can't sample point %i", i );