9 #define _USE_MATH_DEFINES
12 #include "DataArray3D.h"
13 #include "FiniteElementTools.h"
14 #include "FiniteVolumeTools.h"
15 #include "GaussLobattoQuadrature.h"
16 #include "TriangularQuadrature.h"
17 #include "MeshUtilitiesFuzzy.h"
18 #include "MeshUtilitiesExact.h"
19 #include "MathHelper.h"
20 #include "SparseMatrix.h"
21 #include "OverlapMesh.h"
29 #ifdef MOAB_HAVE_EIGEN3
30 #include <Eigen/Dense>
58 std::ofstream output_file(
"rowcolindices.txt", std::ios::out );
60 << row_ldofmap.size() <<
" " <<
col_gdofmap.size() <<
" " << col_ldofmap.size() <<
"\n";
61 output_file <<
"Rows \n";
62 for(
unsigned iv = 0; iv <
row_gdofmap.size(); iv++ )
63 output_file <<
row_gdofmap[iv] <<
" " << row_dofmap[iv] <<
"\n";
64 output_file <<
"Cols \n";
65 for(
unsigned iv = 0; iv <
col_gdofmap.size(); iv++ )
66 output_file <<
col_gdofmap[iv] <<
" " << col_dofmap[iv] <<
"\n";
72 if( use_GID_matching )
74 std::map< unsigned, unsigned > src_gl;
75 for(
unsigned it = 0; it <
col_gdofmap.size(); ++it )
78 std::map< unsigned, unsigned >::iterator iter;
79 for(
unsigned it = 0; it <
row_gdofmap.size(); ++it )
82 iter = src_gl.find( row );
83 if( strict_check && iter == src_gl.end() )
85 std::cout <<
"Searching for global target DOF " << row
86 <<
" but could not find correspondence in source mesh.\n";
89 else if( iter == src_gl.end() )
95 unsigned icol = src_gl[row];
99 m_mapRemap( irow, icol ) = 1.0;
118 const int TriQuadRuleOrder = 4;
121 if( m_meshInputCov->faces.size() > 0 && m_meshInputCov->revnodearray.size() == 0 )
123 _EXCEPTIONT(
"ReverseNodeArray has not been calculated for m_meshInput" );
127 TriangularQuadratureRule triquadrule( TriQuadRuleOrder );
130 #ifdef RECTANGULAR_TRUNCATION
131 int nCoefficients = nOrder * nOrder;
133 #ifdef TRIANGULAR_TRUNCATION
134 int nCoefficients = nOrder * ( nOrder + 1 ) / 2;
138 const int nRequiredFaceSetSize = nCoefficients;
141 const int nFitWeightsExponent = nOrder + 2;
145 dbgprint.set_prefix(
"[LinearRemapFVtoFV_Tempest_MOAB]: " );
148 dbgprint.printf( 0,
"Finite Volume to Finite Volume Projection\n" );
149 dbgprint.printf( 0,
"Triangular quadrature rule order %i\n", TriQuadRuleOrder );
150 dbgprint.printf( 0,
"Number of coefficients: %i\n", nCoefficients );
151 dbgprint.printf( 0,
"Required adjacency set size: %i\n", nRequiredFaceSetSize );
152 dbgprint.printf( 0,
"Fit weights exponent: %i\n", nFitWeightsExponent );
158 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
160 DataArray2D< double > dIntArray;
161 DataArray1D< double > dConstraint( nCoefficients );
164 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
168 if( ixFirst % outputFrequency == 0 && is_root )
170 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
174 int ixOverlapBegin = ixOverlap;
175 unsigned ixOverlapEnd = ixOverlapBegin;
177 for( ; ixOverlapEnd < m_meshOverlap->faces.size(); ixOverlapEnd++ )
179 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapEnd] != 0 )
break;
182 unsigned nOverlapFaces = ixOverlapEnd - ixOverlapBegin;
184 if( nOverlapFaces == 0 )
continue;
187 BuildIntegrationArray( *m_meshInputCov, *m_meshOverlap, triquadrule, ixFirst, ixOverlapBegin, ixOverlapEnd,
194 GetAdjacentFaceVectorByEdge( *m_meshInputCov, ixFirst, nRequiredFaceSetSize, vecAdjFaces );
197 int nAdjFaces = vecAdjFaces.size();
200 double dFirstArea = m_meshInputCov->vecFaceArea[ixFirst];
202 for(
int p = 0; p < nCoefficients; p++ )
204 for(
unsigned j = 0; j < nOverlapFaces; j++ )
206 dConstraint[p] += dIntArray[p][j];
208 dConstraint[p] /= dFirstArea;
212 DataArray2D< double > dFitArray;
213 DataArray1D< double > dFitWeights;
214 DataArray2D< double > dFitArrayPlus;
216 BuildFitArray( *m_meshInputCov, triquadrule, ixFirst, vecAdjFaces, nOrder, nFitWeightsExponent, dConstraint,
217 dFitArray, dFitWeights );
220 bool fSuccess = InvertFitArray_Corrected( dConstraint, dFitArray, dFitWeights, dFitArrayPlus );
223 DataArray2D< double > dComposedArray( nAdjFaces, nOverlapFaces );
227 for(
int i = 0; i < nAdjFaces; i++ )
229 for(
size_t j = 0; j < nOverlapFaces; j++ )
231 for(
int k = 0; k < nCoefficients; k++ )
233 dComposedArray( i, j ) += dIntArray( k, j ) * dFitArrayPlus( i, k );
243 dComposedArray.Zero();
244 for(
size_t j = 0; j < nOverlapFaces; j++ )
246 dComposedArray( 0, j ) += dIntArray( 0, j );
251 for(
unsigned i = 0; i < vecAdjFaces.size(); i++ )
253 for(
unsigned j = 0; j < nOverlapFaces; j++ )
255 int& ixFirstFaceLoc = vecAdjFaces[i].first;
256 int& ixSecondFaceLoc = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
262 if( ixSecondFaceLoc < 0 )
continue;
264 m_mapRemap( ixSecondFaceLoc, ixFirstFaceLoc ) +=
265 dComposedArray[i][j] / m_meshOutput->vecFaceArea[ixSecondFaceLoc];
270 ixOverlap += nOverlapFaces;
278 #ifdef MOAB_HAVE_EIGEN3
279 void moab::TempestOnlineMap::copy_tempest_sparsemat_to_eigen3()
282 #define VERBOSE_ACTIVATED
285 if( m_nTotDofs_Dest <= 0 || m_nTotDofs_SrcCov <= 0 )
293 m_weightMatrix.resize( m_nTotDofs_Dest, m_nTotDofs_SrcCov );
294 m_rowVector.resize( m_weightMatrix.rows() );
295 m_colVector.resize( m_weightMatrix.cols() );
298 int locrows = std::max( m_mapRemap.GetRows(), m_nTotDofs_Dest );
299 int loccols = std::max( m_mapRemap.GetColumns(), m_nTotDofs_SrcCov );
301 std::cout << m_weightMatrix.rows() <<
", " << locrows <<
", " << m_weightMatrix.cols() <<
", " << loccols <<
"\n";
305 DataArray1D< int > lrows;
306 DataArray1D< int > lcols;
307 DataArray1D< double > lvals;
308 m_mapRemap.GetEntries( lrows, lcols, lvals );
309 size_t locvals = lvals.GetRows();
312 typedef Eigen::Triplet< double > Triplet;
313 std::vector< Triplet > tripletList;
314 tripletList.reserve( locvals );
315 for(
size_t iv = 0; iv < locvals; iv++ )
317 tripletList.push_back( Triplet( lrows[iv], lcols[iv], lvals[iv] ) );
320 m_weightMatrix.setFromTriplets( tripletList.begin(), tripletList.end() );
321 m_weightMatrix.makeCompressed();
323 int nrows = m_weightMatrix.rows();
324 int ncols = m_weightMatrix.cols();
325 int NNZ = m_weightMatrix.nonZeros();
329 int arr3[6] = { NNZ, nrows, ncols, -NNZ, -nrows, -ncols };
331 MPI_Reduce( arr3, rarr3, 6, MPI_INT, MPI_MIN, 0, m_pcomm->comm() );
334 MPI_Reduce( arr3, total, 2, MPI_INT, MPI_SUM, 0, m_pcomm->comm() );
336 std::cout <<
" Rows:(" << rarr3[1] <<
", " << -rarr3[4] <<
"), Cols:(" << rarr3[2] <<
", " << -rarr3[5]
337 <<
"), NNZ:(" << rarr3[0] <<
", " << -rarr3[3] <<
"), total NNZ:" << total[0]
338 <<
" total rows:" << total[1] <<
"\n";
340 std::cout <<
"nr rows: " << nrows <<
" cols: " << ncols <<
" non-zeros: " << NNZ <<
"\n";
344 std::stringstream sstr;
345 sstr <<
"tempestmatrix.txt.0000" << rank;
346 std::ofstream output_file( sstr.str(), std::ios::out );
347 output_file <<
"0 " << locrows <<
" 0 " << loccols <<
"\n";
348 for(
unsigned iv = 0; iv < locvals; iv++ )
353 output_file << row_gdofmap[row_ldofmap[lrows[iv]]] <<
" " << col_gdofmap[col_ldofmap[lcols[iv]]] <<
" "
354 << lvals[iv] <<
"\n";
360 #ifdef VERBOSE_ACTIVATED
361 #undef VERBOSE_ACTIVATED
370 std::vector< double >& tgtVals,
374 m_rowVector.setZero();
375 m_colVector.setZero();
378 std::stringstream sstr;
379 static int callId = 0;
381 sstr <<
"projection_id_" << callId <<
"_s_" <<
size <<
"_rk_" << rank <<
".txt";
382 std::ofstream output_file( sstr.str() );
389 for(
unsigned i = 0; i < srcVals.size(); ++i )
391 if( row_dtoc_dofmap[i] >= 0 )
392 m_rowVector( row_dtoc_dofmap[i] ) = srcVals[i];
395 m_colVector = m_weightMatrix.adjoint() * m_rowVector;
398 for(
unsigned i = 0; i < tgtVals.size(); ++i )
400 if( col_dtoc_dofmap[i] >= 0 )
401 tgtVals[i] = m_colVector( col_dtoc_dofmap[i] );
408 output_file <<
"ColVector: " << m_colVector.size() <<
", SrcVals: " << srcVals.size()
409 <<
", Sizes: " << m_nTotDofs_SrcCov <<
", " << col_dtoc_dofmap.size() <<
"\n";
411 for(
unsigned i = 0; i < srcVals.size(); ++i )
413 if( col_dtoc_dofmap[i] >= 0 )
415 m_colVector( col_dtoc_dofmap[i] ) = srcVals[i];
417 output_file << i <<
" " << col_gdofmap[col_dtoc_dofmap[i]] + 1 <<
" " << srcVals[i] <<
"\n";
422 m_rowVector = m_weightMatrix * m_colVector;
426 output_file <<
"RowVector: " << m_rowVector.size() <<
", TgtVals:" << tgtVals.size()
427 <<
", Sizes: " << m_nTotDofs_Dest <<
", " << row_gdofmap.size() <<
"\n";
429 for(
unsigned i = 0; i < tgtVals.size(); ++i )
431 if( row_dtoc_dofmap[i] >= 0 )
433 tgtVals[i] = m_rowVector( row_dtoc_dofmap[i] );
435 output_file << i <<
" " << row_gdofmap[row_dtoc_dofmap[i]] + 1 <<
" " << tgtVals[i] <<
"\n";
455 const DataArray1D< double >& vecTargetArea,
456 DataArray2D< double >& dCoeff,
458 bool fSparseConstraints =
false );
463 const DataArray1D< double >& vecTargetArea,
464 DataArray2D< double >& dCoeff,
470 const DataArray3D< double >& dataGLLJacobian,
473 bool fNoConservation )
476 int nP = dataGLLNodes.GetRows();
479 const int TriQuadRuleOrder = 4;
482 TriangularQuadratureRule triquadrule( TriQuadRuleOrder );
484 int TriQuadraturePoints = triquadrule.GetPoints();
486 const DataArray2D< double >& TriQuadratureG = triquadrule.GetG();
488 const DataArray1D< double >& TriQuadratureW = triquadrule.GetW();
491 DataArray2D< double > dSampleCoeff( nP, nP );
494 DataArray1D< double > dG;
495 DataArray1D< double > dW;
496 GaussLobattoQuadrature::GetPoints( nP, 0.0, 1.0, dG, dW );
500 dbgprint.set_prefix(
"[LinearRemapSE4_Tempest_MOAB]: " );
503 dbgprint.printf( 0,
"Finite Element to Finite Volume Projection\n" );
504 dbgprint.printf( 0,
"Triangular quadrature rule order %i\n", TriQuadRuleOrder );
505 dbgprint.printf( 0,
"Order of the FE polynomial interpolant: %i\n", nP );
509 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
512 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
513 const NodeVector& nodesFirst = m_meshInputCov->nodes;
516 DataArray1D< double > vecSourceArea( nP * nP );
518 DataArray1D< double > vecTargetArea;
519 DataArray2D< double > dCoeff;
522 std::stringstream sstr;
523 sstr <<
"remapdata_" << rank <<
".txt";
524 std::ofstream output_file( sstr.str() );
530 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
538 NodeVector nodes( 3 );
539 faceTri.SetNode( 0, 0 );
540 faceTri.SetNode( 1, 1 );
541 faceTri.SetNode( 2, 2 );
544 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
546 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
548 if( faceFirst.edges.size() != 4 )
550 _EXCEPTIONT(
"Only quadrilateral elements allowed for SE remapping" );
554 if( ixFirst % outputFrequency == 0 && is_root )
556 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
564 int nOverlapFaces = 0;
565 size_t ixOverlapTemp = ixOverlap;
566 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
569 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
578 if( nOverlapFaces == 0 )
584 DataArray3D< double > dRemapCoeff( nP, nP, nOverlapFaces );
587 for(
int j = 0; j < nOverlapFaces; j++ )
589 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + j];
590 if( m_meshOverlap->vecFaceArea[ixOverlap + j] < 1.e-16 )
592 Announce(
"Very small overlap at index %i area polygon: (%1.10e )", ixOverlap + j,
593 m_meshOverlap->vecFaceArea[ixOverlap + j] );
594 int n = faceOverlap.edges.size();
595 Announce(
"Number nodes: %d", n );
596 for(
int k = 0; k < n; k++ )
598 Node nd = nodesOverlap[faceOverlap[k]];
599 Announce(
"Node %d %d : %1.10e %1.10e %1.10e ", k, faceOverlap[k], nd.x, nd.y, nd.z );
611 int nbEdges = faceOverlap.edges.size();
612 int nOverlapTriangles = 1;
616 nOverlapTriangles = nbEdges;
617 for(
int k = 0; k < nbEdges; k++ )
619 const Node& node = nodesOverlap[faceOverlap[k]];
626 Node node0, node1, node2;
627 double dTriangleArea;
630 for(
int k = 0; k < nOverlapTriangles; k++ )
634 node0 = nodesOverlap[faceOverlap[0]];
635 node1 = nodesOverlap[faceOverlap[1]];
636 node2 = nodesOverlap[faceOverlap[2]];
637 dTriangleArea = CalculateFaceArea( faceOverlap, nodesOverlap );
642 node1 = nodesOverlap[faceOverlap[k]];
643 int k1 = ( k + 1 ) % nbEdges;
644 node2 = nodesOverlap[faceOverlap[k1]];
648 dTriangleArea = CalculateFaceArea( faceTri, nodes );
651 for(
int l = 0; l < TriQuadraturePoints; l++ )
654 nodeQuadrature.x = TriQuadratureG[l][0] * node0.x + TriQuadratureG[l][1] * node1.x +
655 TriQuadratureG[l][2] * node2.x;
657 nodeQuadrature.y = TriQuadratureG[l][0] * node0.y + TriQuadratureG[l][1] * node1.y +
658 TriQuadratureG[l][2] * node2.y;
660 nodeQuadrature.z = TriQuadratureG[l][0] * node0.z + TriQuadratureG[l][1] * node1.z +
661 TriQuadratureG[l][2] * node2.z;
663 nodeQuadrature = nodeQuadrature.Normalized();
670 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlpha, dBeta );
673 if( ( dAlpha < -1.0e-13 ) || ( dAlpha > 1.0 + 1.0e-13 ) || ( dBeta < -1.0e-13 ) ||
674 ( dBeta > 1.0 + 1.0e-13 ) )
676 _EXCEPTION4(
"Inverse Map for element %d and subtriangle %d out of range "
678 j, l, dAlpha, dBeta );
682 SampleGLLFiniteElement( nMonotoneType, nP, dAlpha, dBeta, dSampleCoeff );
685 for(
int p = 0; p < nP; p++ )
687 for(
int q = 0; q < nP; q++ )
689 dRemapCoeff[p][q][j] += TriQuadratureW[l] * dTriangleArea * dSampleCoeff[p][q] /
690 m_meshOverlap->vecFaceArea[ixOverlap + j];
698 output_file <<
"[" << m_remapper->lid_to_gid_covsrc[ixFirst] <<
"] \t";
699 for(
int j = 0; j < nOverlapFaces; j++ )
701 for(
int p = 0; p < nP; p++ )
703 for(
int q = 0; q < nP; q++ )
705 output_file << dRemapCoeff[p][q][j] <<
" ";
709 output_file << std::endl;
713 if( !fNoConservation )
715 double dTargetArea = 0.0;
716 for(
int j = 0; j < nOverlapFaces; j++ )
718 dTargetArea += m_meshOverlap->vecFaceArea[ixOverlap + j];
721 for(
int p = 0; p < nP; p++ )
723 for(
int q = 0; q < nP; q++ )
725 vecSourceArea[p * nP + q] = dataGLLJacobian[p][q][ixFirst];
729 const double areaTolerance = 1e-10;
731 if( fabs( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea ) <= areaTolerance )
733 vecTargetArea.Allocate( nOverlapFaces );
734 for(
int j = 0; j < nOverlapFaces; j++ )
736 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
739 dCoeff.Allocate( nOverlapFaces, nP * nP );
741 for(
int j = 0; j < nOverlapFaces; j++ )
743 for(
int p = 0; p < nP; p++ )
745 for(
int q = 0; q < nP; q++ )
747 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
754 else if( m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea > areaTolerance )
756 double dExtraneousArea = m_meshInputCov->vecFaceArea[ixFirst] - dTargetArea;
758 vecTargetArea.Allocate( nOverlapFaces + 1 );
759 for(
int j = 0; j < nOverlapFaces; j++ )
761 vecTargetArea[j] = m_meshOverlap->vecFaceArea[ixOverlap + j];
763 vecTargetArea[nOverlapFaces] = dExtraneousArea;
766 Announce(
"Partial volume: %i (%1.10e / %1.10e)", ixFirst, dTargetArea,
767 m_meshInputCov->vecFaceArea[ixFirst] );
769 if( dTargetArea > m_meshInputCov->vecFaceArea[ixFirst] )
771 _EXCEPTIONT(
"Partial element area exceeds total element area" );
774 dCoeff.Allocate( nOverlapFaces + 1, nP * nP );
776 for(
int j = 0; j < nOverlapFaces; j++ )
778 for(
int p = 0; p < nP; p++ )
780 for(
int q = 0; q < nP; q++ )
782 dCoeff[j][p * nP + q] = dRemapCoeff[p][q][j];
786 for(
int p = 0; p < nP; p++ )
788 for(
int q = 0; q < nP; q++ )
790 dCoeff[nOverlapFaces][p * nP + q] = dataGLLJacobian[p][q][ixFirst];
793 for(
int j = 0; j < nOverlapFaces; j++ )
795 for(
int p = 0; p < nP; p++ )
797 for(
int q = 0; q < nP; q++ )
799 dCoeff[nOverlapFaces][p * nP + q] -=
800 dRemapCoeff[p][q][j] * m_meshOverlap->vecFaceArea[ixOverlap + j];
804 for(
int p = 0; p < nP; p++ )
806 for(
int q = 0; q < nP; q++ )
808 dCoeff[nOverlapFaces][p * nP + q] /= dExtraneousArea;
816 Announce(
"Coverage area: %1.10e, and target element area: %1.10e)", ixFirst,
817 m_meshInputCov->vecFaceArea[ixFirst], dTargetArea );
818 _EXCEPTIONT(
"Target grid must be a subset of source grid" );
824 for(
int j = 0; j < nOverlapFaces; j++ )
826 for(
int p = 0; p < nP; p++ )
828 for(
int q = 0; q < nP; q++ )
830 dRemapCoeff[p][q][j] = dCoeff[j][p * nP + q];
852 for(
int j = 0; j < nOverlapFaces; j++ )
854 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
857 if( ixSecondFace < 0 )
continue;
859 for(
int p = 0; p < nP; p++ )
861 for(
int q = 0; q < nP; q++ )
865 int ixFirstNode = dataGLLNodes[p][q][ixFirst] - 1;
867 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
868 m_meshOverlap->vecFaceArea[ixOverlap + j] /
869 m_meshOutput->vecFaceArea[ixSecondFace];
873 int ixFirstNode = ixFirst * nP * nP + p * nP + q;
875 smatMap( ixSecondFace, ixFirstNode ) += dRemapCoeff[p][q][j] *
876 m_meshOverlap->vecFaceArea[ixOverlap + j] /
877 m_meshOutput->vecFaceArea[ixSecondFace];
883 ixOverlap += nOverlapFaces;
896 const DataArray3D< double >& dataGLLJacobianIn,
897 const DataArray3D< int >& dataGLLNodesOut,
898 const DataArray3D< double >& dataGLLJacobianOut,
899 const DataArray1D< double >& dataNodalAreaOut,
905 bool fNoConservation )
908 TriangularQuadratureRule triquadrule( 8 );
910 const DataArray2D< double >& dG = triquadrule.GetG();
911 const DataArray1D< double >& dW = triquadrule.GetW();
914 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
917 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
918 DataArray2D< double > dSampleCoeffOut( nPout, nPout );
922 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_MOAB]: " );
925 dbgprint.printf( 0,
"Finite Element to Finite Element Projection\n" );
926 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
927 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
931 DataArray3D< double > dGlobalIntArray( nPin * nPin, m_meshOverlap->faces.size(), nPout * nPout );
934 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
937 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
940 int nOverlapFaces = 0;
941 size_t ixOverlapTemp = ixOverlap;
942 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
945 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
953 nAllOverlapFaces[ixFirst] = nOverlapFaces;
956 ixOverlap += nAllOverlapFaces[ixFirst];
960 DataArray2D< double > dGeometricOutputArea( m_meshOutput->faces.size(), nPout * nPout );
963 DataArray2D< double > dOverlapOutputArea( m_meshOverlap->faces.size(), nPout * nPout );
968 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
970 if( is_root )
dbgprint.printf( 0,
"Building conservative distribution maps\n" );
978 NodeVector nodes( 3 );
979 faceTri.SetNode( 0, 0 );
980 faceTri.SetNode( 1, 1 );
981 faceTri.SetNode( 2, 2 );
983 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
987 if( ixFirst % outputFrequency == 0 && is_root )
989 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
993 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
995 const NodeVector& nodesFirst = m_meshInputCov->nodes;
998 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1000 if( !nOverlapFaces )
continue;
1011 for(
int i = 0; i < nOverlapFaces; i++ )
1014 const Face& faceOverlap = m_meshOverlap->faces[ixOverlap + i];
1016 const NodeVector& nodesOverlap = m_meshOverlap->nodes;
1019 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
1022 if( ixSecond < 0 )
continue;
1024 const NodeVector& nodesSecond = m_meshOutput->nodes;
1026 const Face& faceSecond = m_meshOutput->faces[ixSecond];
1028 int nbEdges = faceOverlap.edges.size();
1029 int nOverlapTriangles = 1;
1033 nOverlapTriangles = nbEdges;
1034 for(
int k = 0; k < nbEdges; k++ )
1036 const Node& node = nodesOverlap[faceOverlap[k]];
1043 Node node0, node1, node2;
1047 for(
int j = 0; j < nOverlapTriangles; j++ )
1051 node0 = nodesOverlap[faceOverlap[0]];
1052 node1 = nodesOverlap[faceOverlap[1]];
1053 node2 = nodesOverlap[faceOverlap[2]];
1054 dTriArea = CalculateFaceArea( faceOverlap, nodesOverlap );
1059 node1 = nodesOverlap[faceOverlap[j]];
1060 int j1 = ( j + 1 ) % nbEdges;
1061 node2 = nodesOverlap[faceOverlap[j1]];
1065 dTriArea = CalculateFaceArea( faceTri, nodes );
1068 for(
int k = 0; k < triquadrule.GetPoints(); k++ )
1073 dX[0] = dG( k, 0 ) * node0.x + dG( k, 1 ) * node1.x + dG( k, 2 ) * node2.x;
1074 dX[1] = dG( k, 0 ) * node0.y + dG( k, 1 ) * node1.y + dG( k, 2 ) * node2.y;
1075 dX[2] = dG( k, 0 ) * node0.z + dG( k, 1 ) * node1.z + dG( k, 2 ) * node2.z;
1077 double dMag = sqrt( dX[0] * dX[0] + dX[1] * dX[1] + dX[2] * dX[2] );
1083 Node nodeQuadrature( dX[0], dX[1], dX[2] );
1090 ApplyInverseMap( faceFirst, nodesFirst, nodeQuadrature, dAlphaIn, dBetaIn );
1097 ApplyInverseMap( faceSecond, nodesSecond, nodeQuadrature, dAlphaOut, dBetaOut );
1117 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
1120 SampleGLLFiniteElement( nMonotoneType, nPout, dAlphaOut, dBetaOut, dSampleCoeffOut );
1123 for(
int s = 0; s < nPout; s++ )
1125 for(
int t = 0;
t < nPout;
t++ )
1127 double dNodeArea = dSampleCoeffOut[s][
t] * dW[k] * dTriArea;
1129 dOverlapOutputArea[ixOverlap + i][s * nPout +
t] += dNodeArea;
1131 dGeometricOutputArea[ixSecond][s * nPout +
t] += dNodeArea;
1137 for(
int p = 0; p < nPin; p++ )
1139 for(
int q = 0; q < nPin; q++ )
1142 for(
int s = 0; s < nPout; s++ )
1144 for(
int t = 0;
t < nPout;
t++ )
1147 dGlobalIntArray[ixp][ixOverlap + i][ixs] +=
1148 dSampleCoeffOut[s][
t] * dSampleCoeffIn[p][q] * dW[k] * dTriArea;
1162 DataArray2D< double > dCoeff( nOverlapFaces * nPout * nPout, nPin * nPin );
1164 for(
int i = 0; i < nOverlapFaces; i++ )
1169 for(
int p = 0; p < nPin; p++ )
1171 for(
int q = 0; q < nPin; q++ )
1174 for(
int s = 0; s < nPout; s++ )
1176 for(
int t = 0;
t < nPout;
t++ )
1178 dCoeff[i * nPout * nPout + ixs][ixp] = dGlobalIntArray[ixp][ixOverlap + i][ixs] /
1179 dOverlapOutputArea[ixOverlap + i][s * nPout +
t];
1191 DataArray1D< double > vecSourceArea( nPin * nPin );
1193 for(
int p = 0; p < nPin; p++ )
1195 for(
int q = 0; q < nPin; q++ )
1197 vecSourceArea[p * nPin + q] = dataGLLJacobianIn[p][q][ixFirst];
1202 DataArray1D< double > vecTargetArea( nOverlapFaces * nPout * nPout );
1204 for(
int i = 0; i < nOverlapFaces; i++ )
1208 for(
int s = 0; s < nPout; s++ )
1210 for(
int t = 0;
t < nPout;
t++ )
1212 vecTargetArea[i * nPout * nPout + ixs] = dOverlapOutputArea[ixOverlap + i][nPout * s +
t];
1220 if( !fNoConservation )
1226 for(
int i = 0; i < nOverlapFaces; i++ )
1229 for(
int p = 0; p < nPin; p++ )
1231 for(
int q = 0; q < nPin; q++ )
1234 for(
int s = 0; s < nPout; s++ )
1236 for(
int t = 0;
t < nPout;
t++ )
1238 dGlobalIntArray[ixp][ixOverlap + i][ixs] =
1239 dCoeff[i * nPout * nPout + ixs][ixp] * dOverlapOutputArea[ixOverlap + i][s * nPout +
t];
1252 for(
int i = 0; i < nPin * nPin; i++ )
1254 double dColSum = 0.0;
1255 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1257 dColSum += dCoeff[j][i] * vecTargetArea[j];
1259 printf(
"Col %i: %1.15e\n", i, dColSum / vecSourceArea[i] );
1263 for(
int j = 0; j < nOverlapFaces * nPout * nPout; j++ )
1265 double dRowSum = 0.0;
1266 for(
int i = 0; i < nPin * nPin; i++ )
1268 dRowSum += dCoeff[j][i];
1270 printf(
"Row %i: %1.15e\n", j, dRowSum );
1275 ixOverlap += nOverlapFaces;
1279 if( is_root )
dbgprint.printf( 0,
"Building redistribution maps on target mesh\n" );
1280 DataArray1D< double > dRedistSourceArea( nPout * nPout );
1281 DataArray1D< double > dRedistTargetArea( nPout * nPout );
1282 std::vector< DataArray2D< double > > dRedistributionMaps;
1283 dRedistributionMaps.resize( m_meshOutput->faces.size() );
1285 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
1287 dRedistributionMaps[ixSecond].Allocate( nPout * nPout, nPout * nPout );
1289 for(
int i = 0; i < nPout * nPout; i++ )
1291 dRedistributionMaps[ixSecond][i][i] = 1.0;
1294 for(
int s = 0; s < nPout * nPout; s++ )
1296 dRedistSourceArea[s] = dGeometricOutputArea[ixSecond][s];
1299 for(
int s = 0; s < nPout * nPout; s++ )
1301 dRedistTargetArea[s] = dataGLLJacobianOut[s / nPout][s % nPout][ixSecond];
1304 if( !fNoConservation )
1307 ( nMonotoneType != 0 ) );
1309 for(
int s = 0; s < nPout * nPout; s++ )
1311 for(
int t = 0;
t < nPout * nPout;
t++ )
1313 dRedistributionMaps[ixSecond][s][
t] *= dRedistTargetArea[s] / dRedistSourceArea[
t];
1320 DataArray1D< double > dTotalGeometricArea( dataNodalAreaOut.GetRows() );
1321 for(
size_t ixSecond = 0; ixSecond < m_meshOutput->faces.size(); ixSecond++ )
1323 for(
int s = 0; s < nPout; s++ )
1325 for(
int t = 0;
t < nPout;
t++ )
1327 dTotalGeometricArea[dataGLLNodesOut[s][
t][ixSecond] - 1] +=
1328 dGeometricOutputArea[ixSecond][s * nPout +
t];
1336 if( is_root )
dbgprint.printf( 0,
"Assembling map\n" );
1339 DataArray2D< double > dRedistributedOp( nPin * nPin, nPout * nPout );
1341 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1345 if( ixFirst % outputFrequency == 0 && is_root )
1347 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1351 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1353 if( !nOverlapFaces )
continue;
1356 for(
int j = 0; j < nOverlapFaces; j++ )
1358 int ixSecondFace = m_meshOverlap->vecTargetFaceIx[ixOverlap + j];
1361 if( ixSecondFace < 0 )
continue;
1363 dRedistributedOp.Zero();
1364 for(
int p = 0; p < nPin * nPin; p++ )
1366 for(
int s = 0; s < nPout * nPout; s++ )
1368 for(
int t = 0;
t < nPout * nPout;
t++ )
1370 dRedistributedOp[p][s] +=
1371 dRedistributionMaps[ixSecondFace][s][
t] * dGlobalIntArray[p][ixOverlap + j][
t];
1377 for(
int p = 0; p < nPin; p++ )
1379 for(
int q = 0; q < nPin; q++ )
1384 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
1388 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
1392 for(
int s = 0; s < nPout; s++ )
1394 for(
int t = 0;
t < nPout;
t++ )
1397 if( fContinuousOut )
1399 ixSecondNode = dataGLLNodesOut[s][
t][ixSecondFace] - 1;
1401 if( !fNoConservation )
1403 smatMap( ixSecondNode, ixFirstNode ) +=
1404 dRedistributedOp[ixp][ixs] / dataNodalAreaOut[ixSecondNode];
1408 smatMap( ixSecondNode, ixFirstNode ) +=
1409 dRedistributedOp[ixp][ixs] / dTotalGeometricArea[ixSecondNode];
1414 ixSecondNode = ixSecondFace * nPout * nPout + s * nPout +
t;
1416 if( !fNoConservation )
1418 smatMap( ixSecondNode, ixFirstNode ) +=
1419 dRedistributedOp[ixp][ixs] / dataGLLJacobianOut[s][
t][ixSecondFace];
1423 smatMap( ixSecondNode, ixFirstNode ) +=
1424 dRedistributedOp[ixp][ixs] / dGeometricOutputArea[ixSecondFace][s * nPout +
t];
1438 ixOverlap += nOverlapFaces;
1447 const DataArray3D< double >& ,
1448 const DataArray3D< int >& dataGLLNodesOut,
1449 const DataArray3D< double >& ,
1450 const DataArray1D< double >& dataNodalAreaOut,
1455 bool fContinuousOut )
1458 DataArray1D< double > dGL;
1459 DataArray1D< double > dWL;
1461 GaussLobattoQuadrature::GetPoints( nPout, 0.0, 1.0, dGL, dWL );
1464 SparseMatrix< double >& smatMap = this->GetSparseMatrix();
1467 DataArray2D< double > dSampleCoeffIn( nPin, nPin );
1471 dbgprint.set_prefix(
"[LinearRemapGLLtoGLL2_Pointwise_MOAB]: " );
1474 dbgprint.printf( 0,
"Finite Element to Finite Element (Pointwise) Projection\n" );
1475 dbgprint.printf( 0,
"Order of the input FE polynomial interpolant: %i\n", nPin );
1476 dbgprint.printf( 0,
"Order of the output FE polynomial interpolant: %i\n", nPout );
1480 DataArray1D< int > nAllOverlapFaces( m_meshInputCov->faces.size() );
1484 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1486 size_t ixOverlapTemp = ixOverlap;
1487 for( ; ixOverlapTemp < m_meshOverlap->faces.size(); ixOverlapTemp++ )
1491 if( ixFirst - m_meshOverlap->vecSourceFaceIx[ixOverlapTemp] != 0 )
break;
1493 nAllOverlapFaces[ixFirst]++;
1497 ixOverlap += nAllOverlapFaces[ixFirst];
1501 DataArray1D< bool > fSecondNodeFound( dataNodalAreaOut.GetRows() );
1505 const unsigned outputFrequency = ( m_meshInputCov->faces.size() / 10 ) + 1;
1508 for(
size_t ixFirst = 0; ixFirst < m_meshInputCov->faces.size(); ixFirst++ )
1512 if( ixFirst % outputFrequency == 0 && is_root )
1514 dbgprint.printf( 0,
"Element %zu/%lu\n", ixFirst, m_meshInputCov->faces.size() );
1518 const Face& faceFirst = m_meshInputCov->faces[ixFirst];
1520 const NodeVector& nodesFirst = m_meshInputCov->nodes;
1523 int nOverlapFaces = nAllOverlapFaces[ixFirst];
1526 for(
int i = 0; i < nOverlapFaces; i++ )
1529 int ixSecond = m_meshOverlap->vecTargetFaceIx[ixOverlap + i];
1532 if( ixSecond < 0 )
continue;
1534 const NodeVector& nodesSecond = m_meshOutput->nodes;
1535 const Face& faceSecond = m_meshOutput->faces[ixSecond];
1538 for(
int s = 0; s < nPout; s++ )
1540 for(
int t = 0;
t < nPout;
t++ )
1542 size_t ixSecondNode;
1543 if( fContinuousOut )
1545 ixSecondNode = dataGLLNodesOut[s][
t][ixSecond] - 1;
1549 ixSecondNode = ixSecond * nPout * nPout + s * nPout +
t;
1552 if( ixSecondNode >= fSecondNodeFound.GetRows() ) _EXCEPTIONT(
"Logic error" );
1555 if( fSecondNodeFound[ixSecondNode] )
continue;
1562 ApplyLocalMap( faceSecond, nodesSecond, dGL[
t], dGL[s], node, dDx1G, dDx2G );
1569 ApplyInverseMap( faceFirst, nodesFirst, node, dAlphaIn, dBetaIn );
1572 if( ( dAlphaIn < -1.0e-10 ) || ( dAlphaIn > 1.0 + 1.0e-10 ) || ( dBetaIn < -1.0e-10 ) ||
1573 ( dBetaIn > 1.0 + 1.0e-10 ) )
1577 fSecondNodeFound[ixSecondNode] =
true;
1580 SampleGLLFiniteElement( nMonotoneType, nPin, dAlphaIn, dBetaIn, dSampleCoeffIn );
1583 for(
int p = 0; p < nPin; p++ )
1585 for(
int q = 0; q < nPin; q++ )
1590 ixFirstNode = dataGLLNodesIn[p][q][ixFirst] - 1;
1594 ixFirstNode = ixFirst * nPin * nPin + p * nPin + q;
1597 smatMap( ixSecondNode, ixFirstNode ) += dSampleCoeffIn[p][q];
1605 ixOverlap += nOverlapFaces;
1609 for(
size_t i = 0; i < fSecondNodeFound.GetRows(); i++ )
1611 if( !fSecondNodeFound[i] )
1613 _EXCEPTION1(
"Can't sample point %i", i );