PCDStokesCouette2D.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "Sundance.hpp"
00044 
00045 #if defined(HAVE_SUNDANCE_EXODUS) && defined(Trilinos_DATA_DIR)
00046 
00047 
00048 Array<double> runit(const string& meshName)
00049 {
00050   VectorType<double> vecType = new EpetraVectorType();
00051   MeshType meshType = new BasicSimplicialMeshType();
00052   MeshSource mesher = new ExodusMeshReader(meshName, meshType);
00053   Mesh mesh = mesher.getMesh();
00054 
00055   BasisFamily P2 = new Lagrange(2);
00056   BasisFamily P1 = new Lagrange(1);
00057   QuadratureFamily quad = new GaussianQuadrature(4);
00058 
00059   Expr ux = new UnknownFunction(P2);
00060   Expr uy = new UnknownFunction(P2);
00061   Expr vx = new TestFunction(P2);
00062   Expr vy = new TestFunction(P2);
00063   Expr u = List(ux, uy);
00064   Expr v = List(vx, vy);
00065 
00066   Expr p = new UnknownFunction(P1);
00067   Expr q = new TestFunction(P1);
00068 
00069   CellFilter interior = new MaximalCellFilter();
00070   CellFilter sides = new DimensionalCellFilter(1);
00071   CellFilter pts = new DimensionalCellFilter(0);
00072   CellFilter peg = pts.labeledSubset(1);
00073   CellFilter inner = sides.labeledSubset(2);
00074   CellFilter outer = sides.labeledSubset(1);
00075 
00076   Expr grad = gradient(2);
00077   Expr x = new CoordExpr(0);
00078   Expr y = new CoordExpr(1);
00079   Expr r = sqrt(x*x+y*y);
00080   double uIn = 0.25;
00081   double uOut = 1.0;
00082   Expr uInnerX = -uIn*y/r;
00083   Expr uInnerY = uIn*x/r;
00084   Expr uOuterX = -uOut*y/r;
00085   Expr uOuterY = uOut*x/r;
00086   Expr uInner = List(uInnerX, uInnerY);
00087   Expr uOuter = List(uOuterX, uOuterY);
00088 
00089   Expr nu = 1.0;
00090   double C1 = 20.0;
00091   double C2 = 20.0;
00092 
00093   /* Stokes equations */
00094   Expr eqn = Integral(interior, 
00095     nu * colonProduct( outerProduct(grad, u), outerProduct(grad, v) ) 
00096     - p*div(v) - q*div(u), quad)
00097     + NitscheStokesNoSlipBC(inner, quad, nu, v, q, u, p, uInner, C1, C2)
00098     + NitscheStokesNoSlipBC(outer, quad, nu, v, q, u, p, uOuter, C1, C2);
00099 
00100   Expr dummyBC;
00101 
00102   /* Equations for the PCD preconditioner */
00103   Expr MpEqn = Integral(interior, p*q, quad);
00104   Expr ApEqn = Integral(interior, (grad*p)*(grad*q), quad) 
00105     + Integral(peg, p*q, quad);
00106   Expr FpEqn = Integral(interior, (grad*p)*(grad*q), quad) 
00107     + Integral(peg, p*q, quad);
00108 
00109   /* Arrange the variables into blocks: [velocity, pressure] */
00110   Array<Block> unkBlocks = tuple(Block(u, vecType), Block(p, vecType));
00111   Array<Block> varBlocks = tuple(Block(v, vecType), Block(q, vecType));
00112 
00113   /* Form the Stokes problem */
00114   LinearProblem prob( mesh , eqn , dummyBC , varBlocks, unkBlocks );
00115 
00116   /* Form the PCD problems */
00117   LinearProblem MpProb(mesh, MpEqn, dummyBC, q, p, vecType);
00118   LinearProblem ApProb(mesh, ApEqn, dummyBC, q, p, vecType);
00119   LinearProblem FpProb(mesh, FpEqn, dummyBC, q, p, vecType);
00120 
00121   /* Read the parameters. This is a little complicated because the
00122    * PCD precond parameters contain solver parameter lists */
00123   ParameterXMLFileReader outerSolverReader("pcd-outer-belos.xml");
00124   ParameterList outerSolverParams = outerSolverReader.getParameters();
00125   ParameterList precParams = outerSolverParams.sublist("PCD Preconditioner");
00126   LinearSolver<double> outerSolver = LinearSolverBuilder::createSolver(outerSolverParams);
00127 
00128   /* Form the preconditioner, and set it as a user preconditioner */
00129   PreconditionerFactory<double> outerPrec 
00130     = new PCDPreconditionerFactory(precParams, MpProb, ApProb, FpProb);
00131   outerSolver.setUserPrec(outerPrec);
00132 
00133   /* Solve the problem */
00134   Expr soln = prob.solve(outerSolver);
00135 
00136   /* Compare to the exact solution */
00137 
00138   double c1 = -2.0/3.0*(uIn-2.0*uOut);
00139   double c2 = 1.0/3.0*(2.0*uIn - uOut);
00140   Expr uMagExact = c1*r + c2/r;
00141   Expr uxExact = -uMagExact*y/r;
00142   Expr uyExact = uMagExact*x/r;
00143   Expr uExact = List(uxExact, uyExact);
00144 
00145   double area = L2Norm(mesh, interior, 1.0, quad);
00146   double uErrorNorm = L2Norm(mesh, interior, soln[0]-uExact, quad)/area;
00147   double pErrorNorm = L2Norm(mesh, interior, soln[1], quad)/area;
00148 
00149 
00150   Expr h = new CellDiameterExpr();
00151   double hAvg = L2Norm(mesh, interior, h, quad)/area;
00152 
00153   
00154   Out::root() << "average h = " << hAvg << std::endl;
00155   Out::root() << "velocity error norm = " << uErrorNorm << std::endl;
00156   Out::root() << "pressure error norm = " << pErrorNorm << std::endl;
00157 
00158     
00159 
00160 
00161   // project velocity onto P1
00162   DiscreteSpace P1Space( mesh , P1 , vecType );
00163   L2Projector proj_ux( P1Space , soln[0][0] );
00164   L2Projector proj_uy( P1Space , soln[0][1] );
00165   L2Projector proj_uxEx( P1Space , uxExact );
00166   L2Projector proj_uyEx( P1Space , uyExact );
00167 
00168   Expr ux_P1 = proj_ux.project( );
00169   Expr uy_P1 = proj_uy.project( );
00170 
00171   Expr uxEx_P1 = proj_uxEx.project( );
00172   Expr uyEx_P1 = proj_uyEx.project( );
00173     
00174   FieldWriter w = new VTKWriter("PCDStokes-" + meshName);
00175   w.addMesh(mesh);
00176   w.addField( "ux" , new ExprFieldWrapper( ux_P1 ) );
00177   w.addField( "uy" , new ExprFieldWrapper( uy_P1 ) );
00178   w.addField( "p" , new ExprFieldWrapper( soln[1] ) );
00179   w.addField( "uxEx" , new ExprFieldWrapper( uxEx_P1 ) );
00180   w.addField( "uyEx" , new ExprFieldWrapper( uyEx_P1 ) );
00181   w.write();
00182 
00183   return tuple<double>(hAvg, uErrorNorm, pErrorNorm);
00184 }
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 int main( int argc , char **argv )
00194 {
00195   try 
00196   {
00197     Sundance::init( &argc , &argv );
00198 
00199     Array<Array<double> > results;
00200     for (int n=0; n<=1; n++)
00201     {
00202       string meshName = "diskWithHole2D-" + Teuchos::toString(n);
00203       Array<double> x = runit(meshName);
00204       results.append(x);
00205     }
00206 
00207     for (int n=0; n<results.size(); n++)
00208     {
00209       Out::root() << setw(12) << results[n][0] << setw(20) << results[n][1]
00210                   << setw(20) << results[n][2] << endl;
00211     }
00212 
00213     Sundance::passFailTest(results[0][1], 0.001);
00214   }
00215   catch (std::exception &e) {
00216     Out::os() << e.what() << std::endl;
00217   }
00218 
00219   Sundance::finalize();
00220   return Sundance::testStatus(); 
00221 }
00222 
00223     
00224 
00225 
00226 #else
00227 
00228 
00229 int main(int argc, char** argv)
00230 {
00231   Sundance::init(&argc, &argv);
00232   std::cout << "dummy PCDStokes PASSED. Enable exodus to run the actual test" << std::endl;
00233   Sundance::finalize();
00234   return 0;
00235 }
00236 
00237 
00238 #endif    

Site Contact