Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Cn_FEM( const int n , const EPointType &pointType ): latticePts_( n+1 , 1 ), Phis_( n ), V_(n+1,n+1), Vinv_(n+1,n+1) { const int N = n+1; this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; switch(pointType) { case POINTTYPE_EQUISPACED: PointTools::getLattice<Scalar,ArrayScalar >( latticePts_ , this->basisCellTopology_ , n , 0 , POINTTYPE_EQUISPACED ); break; case POINTTYPE_SPECTRAL: case POINTTYPE_WARPBLEND: PointTools::getLattice<Scalar,ArrayScalar >( latticePts_ , this->basisCellTopology_ , n , 0 , POINTTYPE_WARPBLEND ); break; case POINTTYPE_SPECTRAL_OPEN: PointTools::getGaussPoints<Scalar,ArrayScalar >( latticePts_ , n ); break; default: TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument , "Basis_HGRAD_LINE_Cn_FEM:: invalid point type" ); break; } // form Vandermonde matrix. Actually, this is the transpose of the VDM, // so we transpose on copy below. Phis_.getValues( V_ , latticePts_ , OPERATOR_VALUE ); // now I need to copy V into a Teuchos array to do the inversion Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N); for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vsdm(i,j) = V_(i,j); } } // invert the matrix Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); // now I need to copy the inverse into Vinv for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vinv_(i,j) = Vsdm(j,i); } } initializeTags(); this->basisTagsAreSet_ = true; }
Basis_HGRAD_TRI_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_TRI_Cn_FEM( const int n , const EPointType pointType ): Phis( n ), V((n+1)*(n+2)/2,(n+1)*(n+2)/2), Vinv((n+1)*(n+2)/2,(n+1)*(n+2)/2), latticePts( (n+1)*(n+2)/2 , 2 ) { TEUCHOS_TEST_FOR_EXCEPTION( n <= 0, std::invalid_argument, "polynomial order must be >= 1"); const int N = (n+1)*(n+2)/2; this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; // construct lattice shards::CellTopology myTri_3( shards::getCellTopologyData< shards::Triangle<3> >() ); PointTools::getLattice<Scalar,FieldContainer<Scalar> >( latticePts , myTri_3 , n , 0 , pointType ); // form Vandermonde matrix. Actually, this is the transpose of the VDM, // so we transpose on copy below. Phis.getValues( V , latticePts , OPERATOR_VALUE ); // now I need to copy V into a Teuchos array to do the inversion Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N); for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vsdm(i,j) = V(i,j); } } // invert the matrix Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); // now I need to copy the inverse into Vinv for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vinv(i,j) = Vsdm(j,i); } } }
Basis_HGRAD_TET_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_TET_Cn_FEM( const int n , const EPointType pointType ): Phis( n ), V((n+1)*(n+2)*(n+3)/6,(n+1)*(n+2)*(n+3)/6), Vinv((n+1)*(n+2)*(n+3)/6,(n+1)*(n+2)*(n+3)/6), latticePts( (n+1)*(n+2)*(n+3)/6 , 3 ) { const int N = (n+1)*(n+2)*(n+3)/6; this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Tetrahedron<4> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; // construct lattice PointTools::getLattice<Scalar,ArrayScalar >( latticePts , this->getBaseCellTopology() , n , 0 , pointType ); // form Vandermonde matrix. Actually, this is the transpose of the VDM, // so we transpose on copy below. Phis.getValues( V , latticePts , OPERATOR_VALUE ); // now I need to copy V into a Teuchos array to do the inversion Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N); for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vsdm(i,j) = V(i,j); } } // invert the matrix Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); // now I need to copy the inverse into Vinv for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vinv(i,j) = Vsdm(j,i); } } initializeTags(); this->basisTagsAreSet_ = true; }
Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Cn_FEM( const int n , const ArrayScalar &pts ): latticePts_( n+1 , 1 ), Phis_( n ), V_(n+1,n+1), Vinv_(n+1,n+1) { const int N = n+1; this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; // check validity of points for (int i=0;i<n;i++) { TEUCHOS_TEST_FOR_EXCEPTION( pts(i,0) >= pts(i+1,0) , std::runtime_error , "Intrepid2::Basis_HGRAD_LINE_Cn_FEM Illegal points given to constructor" ); } // copy points int latticePts, correcting endpoints if needed if (std::abs(pts(0,0)+1.0) < INTREPID_TOL) { latticePts_(0,0) = -1.0; } else { latticePts_(0,0) = pts(0,0); } for (int i=1;i<n;i++) { latticePts_(i,0) = pts(i,0); } if (std::abs(pts(n,0)-1.0) < INTREPID_TOL) { latticePts_(n,0) = 1.0; } else { latticePts_(n,0) = pts(n,0); } // form Vandermonde matrix. Actually, this is the transpose of the VDM, // so we transpose on copy below. Phis_.getValues( V_ , latticePts_ , OPERATOR_VALUE ); // now I need to copy V into a Teuchos array to do the inversion Teuchos::SerialDenseMatrix<int,Scalar> Vsdm(N,N); for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vsdm(i,j) = V_(i,j); } } // invert the matrix Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); // now I need to copy the inverse into Vinv for (int i=0;i<N;i++) { for (int j=0;j<N;j++) { Vinv_(i,j) = Vsdm(j,i); } } }
Basis_HDIV_TRI_In_FEM<Scalar,ArrayScalar>::Basis_HDIV_TRI_In_FEM( const int n , const EPointType pointType ): Phis( n ), coeffs( (n+1)*(n+2) , n*(n+2) ) { const int N = n*(n+2); this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; const int littleN = n*(n+1); // dim of (P_{n-1})^2 -- smaller space const int bigN = (n+1)*(n+2); // dim of (P_{n})^2 -- larger space const int scalarSmallestN = (n-1)*n / 2; const int scalarLittleN = littleN/2; const int scalarBigN = bigN/2; // first, need to project the basis for RT space onto the // orthogonal basis of degree n // get coefficients of PkHx Teuchos::SerialDenseMatrix<int,Scalar> V1(bigN, N); // basis for the space is // { (phi_i,0) }_{i=0}^{scalarLittleN-1} , // { (0,phi_i) }_{i=0}^{scalarLittleN-1} , // { (x,y) . phi_i}_{i=scalarLittleN}^{scalarBigN-1} // columns of V1 are expansion of this basis in terms of the basis // for P_{n}^2 // these two loops get the first two sets of basis functions for (int i=0;i<scalarLittleN;i++) { V1(i,i) = 1.0; V1(scalarBigN+i,scalarLittleN+i) = 1.0; } // now I need to integrate { (x,y) phi } against the big basis // first, get a cubature rule. CubatureDirectTriDefault<Scalar,ArrayScalar > myCub( 2 * n ); ArrayScalar cubPoints( myCub.getNumPoints() , 2 ); ArrayScalar cubWeights( myCub.getNumPoints() ); myCub.getCubature( cubPoints , cubWeights ); // tabulate the scalar orthonormal basis at cubature points ArrayScalar phisAtCubPoints( scalarBigN , myCub.getNumPoints() ); Phis.getValues( phisAtCubPoints , cubPoints , OPERATOR_VALUE ); // now do the integration for (int i=0;i<n;i++) { for (int j=0;j<scalarBigN;j++) { // int (x,y) phi_i \cdot (phi_j,0) V1(j,littleN+i) = 0.0; for (int k=0;k<myCub.getNumPoints();k++) { V1(j,littleN+i) += cubWeights(k) * cubPoints(k,0) * phisAtCubPoints(scalarSmallestN+i,k) * phisAtCubPoints(j,k); } } for (int j=0;j<scalarBigN;j++) { // int (x,y) phi_i \cdot (0,phi_j) V1(j+scalarBigN,littleN+i) = 0.0; for (int k=0;k<myCub.getNumPoints();k++) { V1(j+scalarBigN,littleN+i) += cubWeights(k) * cubPoints(k,1) * phisAtCubPoints(scalarSmallestN+i,k) * phisAtCubPoints(j,k); } } } //std::cout << V1 << "\n"; // next, apply the RT nodes (rows) to the basis for (P_n)^2 (columns) Teuchos::SerialDenseMatrix<int,Scalar> V2(N , bigN); // first 3 * degree nodes are normals at each edge // get the points on the line ArrayScalar linePts( n , 1 ); if (pointType == POINTTYPE_WARPBLEND) { CubatureDirectLineGauss<Scalar> edgeRule( n ); ArrayScalar edgeCubWts( n ); edgeRule.getCubature( linePts , edgeCubWts ); } else if (pointType == POINTTYPE_EQUISPACED ) { shards::CellTopology linetop(shards::getCellTopologyData<shards::Line<2> >() ); PointTools::getLattice<Scalar,ArrayScalar >( linePts , linetop , n+1 , 1 , POINTTYPE_EQUISPACED ); } // holds the image of the line points ArrayScalar edgePts( n , 2 ); ArrayScalar phisAtEdgePoints( scalarBigN , n ); // these are scaled by the appropriate edge lengths. const Scalar nx[] = {0.0,1.0,-1.0}; const Scalar ny[] = {-1.0,1.0,0.0}; for (int i=0;i<3;i++) { // loop over edges CellTools<Scalar>::mapToReferenceSubcell( edgePts , linePts , 1 , i , this->basisCellTopology_ ); Phis.getValues( phisAtEdgePoints , edgePts , OPERATOR_VALUE ); // loop over points (rows of V2) for (int j=0;j<n;j++) { // loop over orthonormal basis functions (columns of V2) for (int k=0;k<scalarBigN;k++) { V2(n*i+j,k) = nx[i] * phisAtEdgePoints(k,j); V2(n*i+j,k+scalarBigN) = ny[i] * phisAtEdgePoints(k,j); } } } // next map the points to each edge // remaining nodes are divided into two pieces: point value of x // components and point values of y components. These are // evaluated at the interior of a lattice of degree + 1, For then // the degree == 1 space corresponds classicaly to RT0 and so gets // no internal nodes, and degree == 2 corresponds to RT1 and needs // one internal node per vector component. const int numInternalPoints = PointTools::getLatticeSize( this->getBaseCellTopology() , n + 1 , 1 ); if (numInternalPoints > 0) { ArrayScalar internalPoints( numInternalPoints , 2 ); PointTools::getLattice<Scalar,ArrayScalar >( internalPoints , this->getBaseCellTopology() , n + 1 , 1 , pointType ); ArrayScalar phisAtInternalPoints( scalarBigN , numInternalPoints ); Phis.getValues( phisAtInternalPoints , internalPoints , OPERATOR_VALUE ); // copy values into right positions of V2 for (int i=0;i<numInternalPoints;i++) { for (int j=0;j<scalarBigN;j++) { // x component V2(3*n+i,j) = phisAtInternalPoints(j,i); // y component V2(3*n+numInternalPoints+i,scalarBigN+j) = phisAtInternalPoints(j,i); } } } // std::cout << "Nodes on big basis\n"; // std::cout << V2 << "\n"; // std::cout << "End nodes\n"; Teuchos::SerialDenseMatrix<int,Scalar> Vsdm( N , N ); // multiply V2 * V1 --> V Vsdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V2 , V1 , 0.0 ); // std::cout << "Vandermonde:\n"; // std::cout << Vsdm << "\n"; // std::cout << "End Vandermonde\n"; Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); Teuchos::SerialDenseMatrix<int,Scalar> Csdm( bigN , N ); Csdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V1 , Vsdm , 0.0 ); // std::cout << Csdm << "\n"; for (int i=0;i<bigN;i++) { for (int j=0;j<N;j++) { coeffs(i,j) = Csdm(i,j); } } }
void DislocationDensity<EvalT, Traits>:: evaluateFields(typename Traits::EvalData workset) { Teuchos::SerialDenseMatrix<int, double> A; Teuchos::SerialDenseMatrix<int, double> X; Teuchos::SerialDenseMatrix<int, double> B; Teuchos::SerialDenseSolver<int, double> solver; A.shape(numNodes,numNodes); X.shape(numNodes,numNodes); B.shape(numNodes,numNodes); // construct Identity for RHS for (int i = 0; i < numNodes; ++i) B(i,i) = 1.0; for (int i=0; i < G.size() ; i++) G[i] = 0.0; // construct the node --> point operator for (std::size_t cell=0; cell < workset.numCells; ++cell) { for (std::size_t node=0; node < numNodes; ++node) for (std::size_t qp=0; qp < numQPs; ++qp) A(qp,node) = BF(cell,node,qp); X = 0.0; solver.setMatrix( Teuchos::rcp( &A, false) ); solver.setVectors( Teuchos::rcp( &X, false ), Teuchos::rcp( &B, false ) ); // Solve the system A X = B to find A_inverse int status = 0; status = solver.factor(); status = solver.solve(); // compute nodal Fp nodalFp.initialize(0.0); for (std::size_t node=0; node < numNodes; ++node) for (std::size_t qp=0; qp < numQPs; ++qp) for (std::size_t i=0; i < numDims; ++i) for (std::size_t j=0; j < numDims; ++j) nodalFp(node,i,j) += X(node,qp) * Fp(cell,qp,i,j); // compute the curl using nodalFp curlFp.initialize(0.0); for (std::size_t node=0; node < numNodes; ++node) { for (std::size_t qp=0; qp < numQPs; ++qp) { curlFp(qp,0,0) += nodalFp(node,0,2) * GradBF(cell,node,qp,1) - nodalFp(node,0,1) * GradBF(cell,node,qp,2); curlFp(qp,0,1) += nodalFp(node,1,2) * GradBF(cell,node,qp,1) - nodalFp(node,1,1) * GradBF(cell,node,qp,2); curlFp(qp,0,2) += nodalFp(node,2,2) * GradBF(cell,node,qp,1) - nodalFp(node,2,1) * GradBF(cell,node,qp,2); curlFp(qp,1,0) += nodalFp(node,0,0) * GradBF(cell,node,qp,2) - nodalFp(node,0,2) * GradBF(cell,node,qp,0); curlFp(qp,1,1) += nodalFp(node,1,0) * GradBF(cell,node,qp,2) - nodalFp(node,1,2) * GradBF(cell,node,qp,0); curlFp(qp,1,2) += nodalFp(node,2,0) * GradBF(cell,node,qp,2) - nodalFp(node,2,2) * GradBF(cell,node,qp,0); curlFp(qp,2,0) += nodalFp(node,0,1) * GradBF(cell,node,qp,0) - nodalFp(node,0,0) * GradBF(cell,node,qp,1); curlFp(qp,2,1) += nodalFp(node,1,1) * GradBF(cell,node,qp,0) - nodalFp(node,1,0) * GradBF(cell,node,qp,1); curlFp(qp,2,2) += nodalFp(node,2,1) * GradBF(cell,node,qp,0) - nodalFp(node,2,0) * GradBF(cell,node,qp,1); } } for (std::size_t qp=0; qp < numQPs; ++qp) for (std::size_t i=0; i < numDims; ++i) for (std::size_t j=0; j < numDims; ++j) for (std::size_t k=0; k < numDims; ++k) G(cell,qp,i,j) += Fp(cell,qp,i,k) * curlFp(qp,k,j); } }
Basis_HCURL_TRI_In_FEM<Scalar,ArrayScalar>::Basis_HCURL_TRI_In_FEM( const int n , const EPointType pointType ): Phis_( n ), coeffs_( (n+1)*(n+2) , n*(n+2) ) { const int N = n*(n+2); this -> basisCardinality_ = N; this -> basisDegree_ = n; this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Triangle<3> >() ); this -> basisType_ = BASIS_FEM_FIAT; this -> basisCoordinates_ = COORDINATES_CARTESIAN; this -> basisTagsAreSet_ = false; const int littleN = n*(n+1); // dim of (P_{n-1})^2 -- smaller space const int bigN = (n+1)*(n+2); // dim of (P_{n})^2 -- larger space const int scalarSmallestN = (n-1)*n / 2; const int scalarLittleN = littleN/2; const int scalarBigN = bigN/2; // first, need to project the basis for Nedelec space onto the // orthogonal basis of degree n // get coefficients of PkHx Teuchos::SerialDenseMatrix<int,Scalar> V1(bigN, N); // basis for the space is // { (phi_i,0) }_{i=0}^{scalarLittleN-1} , // { (0,phi_i) }_{i=0}^{scalarLittleN-1} , // { (x,y) \times phi_i}_{i=scalarLittleN}^{scalarBigN-1} // { (x,y) \times phi = (y phi , -x \phi) // columns of V1 are expansion of this basis in terms of the basis // for P_{n}^2 // these two loops get the first two sets of basis functions for (int i=0;i<scalarLittleN;i++) { V1(i,i) = 1.0; V1(scalarBigN+i,scalarLittleN+i) = 1.0; } // now I need to integrate { (x,y) \times phi } against the big basis // first, get a cubature rule. CubatureDirectTriDefault<Scalar,ArrayScalar > myCub( 2 * n ); ArrayScalar cubPoints( myCub.getNumPoints() , 2 ); ArrayScalar cubWeights( myCub.getNumPoints() ); myCub.getCubature( cubPoints , cubWeights ); // tabulate the scalar orthonormal basis at cubature points ArrayScalar phisAtCubPoints( scalarBigN , myCub.getNumPoints() ); Phis_.getValues( phisAtCubPoints , cubPoints , OPERATOR_VALUE ); // now do the integration for (int i=0;i<n;i++) { for (int j=0;j<scalarBigN;j++) { // int (x,y) phi_i \cdot (phi_j,0) V1(j,littleN+i) = 0.0; for (int k=0;k<myCub.getNumPoints();k++) { V1(j,littleN+i) -= cubWeights(k) * cubPoints(k,1) * phisAtCubPoints(scalarSmallestN+i,k) * phisAtCubPoints(j,k); } } for (int j=0;j<scalarBigN;j++) { // int (x,y) phi_i \cdot (0,phi_j) V1(j+scalarBigN,littleN+i) = 0.0; for (int k=0;k<myCub.getNumPoints();k++) { V1(j+scalarBigN,littleN+i) += cubWeights(k) * cubPoints(k,0) * phisAtCubPoints(scalarSmallestN+i,k) * phisAtCubPoints(j,k); } } } //std::cout << V1 << "\n"; // next, apply the RT nodes (rows) to the basis for (P_n)^2 (columns) Teuchos::SerialDenseMatrix<int,Scalar> V2(N , bigN); // first 3 * degree nodes are normals at each edge // get the points on the line ArrayScalar linePts( n , 1 ); if (pointType == POINTTYPE_WARPBLEND) { CubatureDirectLineGauss<Scalar> edgeRule( 2*n - 1 ); ArrayScalar edgeCubWts( n ); edgeRule.getCubature( linePts , edgeCubWts ); } else if (pointType == POINTTYPE_EQUISPACED ) { shards::CellTopology linetop(shards::getCellTopologyData<shards::Line<2> >() ); PointTools::getLattice<Scalar,ArrayScalar >( linePts , linetop , n+1 , 1 , POINTTYPE_EQUISPACED ); } ArrayScalar edgePts( n , 2 ); ArrayScalar phisAtEdgePoints( scalarBigN , n ); ArrayScalar edgeTan(2); for (int i=0;i<3;i++) { // loop over edges CellTools<Scalar>::getReferenceEdgeTangent( edgeTan , i , this->basisCellTopology_ ); /* multiply by 2.0 to account for a Jacobian in Pavel's definition */ for (int j=0;j<2;j++) { edgeTan(j) *= 2.0; } CellTools<Scalar>::mapToReferenceSubcell( edgePts , linePts , 1 , i , this->basisCellTopology_ ); Phis_.getValues( phisAtEdgePoints , edgePts , OPERATOR_VALUE ); // loop over points (rows of V2) for (int j=0;j<n;j++) { // loop over orthonormal basis functions (columns of V2) for (int k=0;k<scalarBigN;k++) { V2(n*i+j,k) = edgeTan(0) * phisAtEdgePoints(k,j); V2(n*i+j,k+scalarBigN) = edgeTan(1) * phisAtEdgePoints(k,j); } } } // remaining nodes are x- and y- components at internal points, if n > 1 // this code is exactly the same as it is for HDIV const int numInternalPoints = PointTools::getLatticeSize( this->getBaseCellTopology() , n + 1 , 1 ); if (numInternalPoints > 0) { ArrayScalar internalPoints( numInternalPoints , 2 ); PointTools::getLattice<Scalar,ArrayScalar >( internalPoints , this->getBaseCellTopology() , n + 1 , 1 , pointType ); ArrayScalar phisAtInternalPoints( scalarBigN , numInternalPoints ); Phis_.getValues( phisAtInternalPoints , internalPoints , OPERATOR_VALUE ); // copy values into right positions of V2 for (int i=0;i<numInternalPoints;i++) { for (int j=0;j<scalarBigN;j++) { // x component V2(3*n+i,j) = phisAtInternalPoints(j,i); // y component V2(3*n+numInternalPoints+i,scalarBigN+j) = phisAtInternalPoints(j,i); } } } // std::cout << "Nodes on big basis\n"; // std::cout << V2 << "\n"; // std::cout << "End nodes\n"; Teuchos::SerialDenseMatrix<int,Scalar> Vsdm( N , N ); // multiply V2 * V1 --> V Vsdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V2 , V1 , 0.0 ); // std::cout << "Vandermonde:\n"; // std::cout << Vsdm << "\n"; // std::cout << "End Vandermonde\n"; Teuchos::SerialDenseSolver<int,Scalar> solver; solver.setMatrix( rcp( &Vsdm , false ) ); solver.invert( ); Teuchos::SerialDenseMatrix<int,Scalar> Csdm( bigN , N ); Csdm.multiply( Teuchos::NO_TRANS , Teuchos::NO_TRANS , 1.0 , V1 , Vsdm , 0.0 ); // std::cout << Csdm << "\n"; for (int i=0;i<bigN;i++) { for (int j=0;j<N;j++) { coeffs_(i,j) = Csdm(i,j); } } initializeTags(); this->basisTagsAreSet_ = true; }
void SaddleOperator<ScalarType, MV, OP>::Apply(const SaddleContainer<ScalarType,MV>& X, SaddleContainer<ScalarType,MV>& Y) const { RCP<SerialDenseMatrix> Xlower = X.getLower(); RCP<SerialDenseMatrix> Ylower = Y.getLower(); if(pt_ == NO_PREC) { // trans does literally nothing, because the operator is symmetric // Y.bottom = B'X.top MVT::MvTransMv(1., *B_, *(X.upper_), *Ylower); // Y.top = A*X.top+B*X.bottom A_->Apply(*(X.upper_), *(Y.upper_)); MVT::MvTimesMatAddMv(1., *B_, *Xlower, 1., *(Y.upper_)); } else if(pt_ == NONSYM) { // Y.bottom = -B'X.top MVT::MvTransMv(-1., *B_, *(X.upper_), *Ylower); // Y.top = A*X.top+B*X.bottom A_->Apply(*(X.upper_), *(Y.upper_)); MVT::MvTimesMatAddMv(1., *B_, *Xlower, 1., *(Y.upper_)); } else if(pt_ == BD_PREC) { Teuchos::SerialDenseSolver<int,ScalarType> MySolver; // Solve A Y.X = X.X A_->Apply(*(X.upper_),*(Y.upper_)); // So, let me tell you a funny story about how the SerialDenseSolver destroys the original matrix... Teuchos::RCP<SerialDenseMatrix> localSchur = Teuchos::rcp(new SerialDenseMatrix(*Schur_)); // Solve the small system MySolver.setMatrix(localSchur); MySolver.setVectors(Ylower, Xlower); MySolver.solve(); } // Hermitian-Skew Hermitian splitting has some extra requirements // We need B'B = I, which is true for standard eigenvalue problems, but not generalized // We also need to use gmres, because our operator is no longer symmetric else if(pt_ == HSS_PREC) { // std::cout << "applying preconditioner to"; // X.MvPrint(std::cout); // Solve (H + alpha I) Y1 = X // 1. Apply preconditioner A_->Apply(*(X.upper_),*(Y.upper_)); // 2. Scale by 1/alpha *Ylower = *Xlower; Ylower->scale(1./alpha_); // std::cout << "H preconditioning produced"; // Y.setLower(Ylower); // Y.MvPrint(std::cout); // Solve (S + alpha I) Y = Y1 // 1. Y_lower = (B' Y1_upper + alpha Y1_lower) / (1 + alpha^2) Teuchos::RCP<SerialDenseMatrix> Y1_lower = Teuchos::rcp(new SerialDenseMatrix(*Ylower)); MVT::MvTransMv(1,*B_,*(Y.upper_),*Ylower); // std::cout << "Y'b1 " << *Ylower; Y1_lower->scale(alpha_); // std::cout << "alpha b2 " << *Y1_lower; *Ylower += *Y1_lower; // std::cout << "alpha b2 + Y'b1 " << *Ylower; Ylower->scale(1/(1+alpha_*alpha_)); // 2. Y_upper = (Y1_upper - B Y_lower) / alpha MVT::MvTimesMatAddMv(-1/alpha_,*B_,*Ylower,1/alpha_,*(Y.upper_)); // std::cout << "preconditioning produced"; // Y.setLower(Ylower); // Y.MvPrint(std::cout); } else { std::cout << "Not a valid preconditioner type\n"; } Y.setLower(Ylower); // std::cout << "result of applying operator"; // Y.MvPrint(std::cout); }