1DfemTransient.H

Go to the documentation of this file.
00001 //@HEADER
00002 // ***********************************************************************
00003 //
00004 //                     Rythmos Package
00005 //                 Copyright (2006) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Todd S. Coffey (tscoffe@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 //@HEADER
00028 
00029 // 1D Transient Finite Element Test Problem
00030 /* Solves the nonlinear PDE for u(x,t):
00031 *
00032 * du     d2u    8
00033 * --- =  --- + --- u**2( 1 - u )
00034 * dt     dx2   k*k
00035 *
00036 * subject to u(-infinity,t) = 1
00037 *            u(-infinity,t) = 0
00038 * and
00039 *            u(x,0) = 0.5 * ( 1 - tanh(x/k) )
00040 *
00041 * with d representing partial differentiation.
00042 *
00043 * An exact closed solution is the following:
00044 *
00045 *                             x - 2t/k
00046 *  u(x,t) = 0.5 * ( 1 - tanh(--------- ) )
00047 *                                k
00048 *
00049 * This problem is examined with a variety of time integration schemes in:
00050 * "Studies on the Convergence of Various Time-Integration Schemes for the
00051 * Radiation-Diffusion Problem," Curtis C. Ober & John N. Shadid, in prep.
00052 *
00053 * In this example, only a 1st-order fully implicit (backward Euler)
00054 * time integration scheme is considered currently.
00055 *
00056 * Values for k, time step size, and finite spatial extent are specified in
00057 * the constructor initialization list in FiniteElementProblem.C using
00058 * variables factor, dt and xmin,xmax, respectively.
00059 * The number of time steps to be taken is specified by variable
00060 * maxTimeSteps below.
00061 */
00062 
00063 #undef PRINT_RESULTS_TO_FILES
00064 
00065 // NOX Objects
00066 #include "NOX.H"
00067 #include "NOX_Epetra.H"
00068 
00069 // Trilinos Objects
00070 #ifdef HAVE_MPI
00071 #include "Epetra_MpiComm.h"
00072 #else
00073 #include "Epetra_SerialComm.h"
00074 #endif
00075 #include "Epetra_Map.h"
00076 #include "Epetra_Vector.h"
00077 #include "Epetra_RowMatrix.h"
00078 #include "Epetra_CrsMatrix.h"
00079 #include "Epetra_Map.h"
00080 #include "Epetra_LinearProblem.h"
00081 //#include "AztecOO.h"
00082 
00083 // User's application specific files 
00084 #include "1DfemInterface.H" 
00085 
00086 #include "Teuchos_dyn_cast.hpp"
00087 
00088 using namespace std;
00089 
00090 // ------------------------------------------------------------------------
00091 // ------------------  Declaration with definition ------------------------
00092 // ------------------------------------------------------------------------
00093 class TransientInterface : public Interface 
00094 {
00095 
00096 public:
00097 
00098   // ---------------------------
00099   // --------------- Constructor ------
00100   // ---------------------------
00101   TransientInterface(int NumGlobalElements, Epetra_Comm& Comm, 
00102                      double xmin = 0.0, double xmax = 1.0) :
00103     Interface(NumGlobalElements, Comm, xmin, xmax),
00104     oldSolution(0),
00105     exactSolution(0)
00106     {
00107       // Must reinitialize the solution now that the inherited class exists
00108       initializeSoln();
00109 
00110       oldSolution = new Epetra_Vector(*initialSolution);
00111     };
00112 
00113   // ---------------------------
00114   // --------------- Destructor ------
00115   // ---------------------------
00116   virtual ~TransientInterface()
00117     { 
00118       delete oldSolution;
00119       if (exactSolution) delete exactSolution;
00120     };
00121 
00122   // ---------------------------
00123   // --------------- Matrix and Residual Fills
00124   // ---------------------------
00125   bool evaluate(NOX::Epetra::Interface::Required::FillType flag, 
00126                 const Epetra_Vector* soln, 
00127                 const Epetra_Vector* solndot, // 09/21/05 tscoffe
00128                 double alpha, // 09/21/05 tscoffe
00129                 double beta, // 09/21/05 tscoffe
00130       Epetra_Vector* tmp_rhs, 
00131       Epetra_RowMatrix* tmp_matrix)
00132   {
00133 
00134     Epetra_CrsMatrix* jacout;
00135     
00136     //Determine what to fill (F or Jacobian)
00137     bool fillF = false;
00138     bool fillMatrix = false;
00139     if (tmp_rhs != 0) {
00140       fillF = true;
00141       rhs = tmp_rhs;
00142     }
00143     else {
00144       fillMatrix = true;
00145       jacout = &Teuchos::dyn_cast<Epetra_CrsMatrix>(*tmp_matrix);
00146     }
00147   
00148     // "flag" can be used to determine how accurate your fill of F should be
00149     // depending on why we are calling evaluate (Could be using computeF to 
00150     // populate a Jacobian or Preconditioner).
00151     if (flag == NOX::Epetra::Interface::Required::Residual) {
00152       // Do nothing for now
00153     }
00154     else if (flag == NOX::Epetra::Interface::Required::Jac) {
00155       // Do nothing for now
00156     }
00157     else if (flag == NOX::Epetra::Interface::Required::Prec) {
00158       // Do nothing for now
00159     }
00160     else if (flag == NOX::Epetra::Interface::Required::User) {
00161       // Do nothing for now
00162     }
00163   
00164   
00165     // Create the overlapped solution and position vectors
00166     Epetra_Vector u(*OverlapMap);
00167     Epetra_Vector uold(*OverlapMap);
00168     Epetra_Vector xvec(*OverlapMap);
00169     Epetra_Vector udot(*OverlapMap); // 09/21/05 tscoffe
00170   
00171     // Export Solution to Overlap vector
00172     u.Import(*soln, *Importer, Insert);
00173     uold.Import(*oldSolution, *Importer, Insert);
00174     xvec.Import(*xptr, *Importer, Insert);
00175     udot.Import(*solndot, *Importer, Insert); // 09/21/05 tscoffe
00176   
00177     // Declare required variables
00178     int ierr;
00179     int OverlapNumMyElements = OverlapMap->NumMyElements();
00180   
00181     int OverlapMinMyGID;
00182     if (MyPID == 0) OverlapMinMyGID = StandardMap->MinMyGID();
00183     else OverlapMinMyGID = StandardMap->MinMyGID()-1;
00184   
00185     int row, column;
00186     double jac;
00187     double xx[2];
00188     double uu[2];
00189     double uuold[2];
00190     double uudot[2]; // 09/21/05 tscoffe
00191     Basis basis;
00192   
00193     // Zero out the objects that will be filled
00194     if (fillF) 
00195       rhs->PutScalar(0.0);
00196     if (fillMatrix) 
00197       jacout->PutScalar(0.0);
00198   
00199     // Loop Over # of Finite Elements on Processor
00200     for (int ne=0; ne < OverlapNumMyElements-1; ne++) {
00201       
00202       // Loop Over Gauss Points
00203       for(int gp=0; gp < 2; gp++) {
00204         // Get the solution and coordinates at the nodes 
00205         xx[0]=xvec[ne];
00206         xx[1]=xvec[ne+1];
00207         uu[0]=u[ne];
00208         uu[1]=u[ne+1];
00209         uuold[0]=uold[ne];
00210         uuold[1]=uold[ne+1];
00211         uudot[0] = udot[ne]; // 09/21/05 tscoffe
00212         uudot[1] = udot[ne+1]; // 09/21/05 tscoffe
00213         // Calculate the basis function at the gauss point
00214         // basis.computeBasis(gp, xx, uu, uuold);
00215         basis.computeBasis(gp, xx, uu, uudot); // 09/21/05 tscoffe
00216                 
00217         // Loop over Nodes in Element
00218         for (int i=0; i< 2; i++) {
00219     row=OverlapMap->GID(ne+i);
00220     //printf("Proc=%d GlobalRow=%d LocalRow=%d Owned=%d\n",
00221     //     MyPID, row, ne+i,StandardMap.MyGID(row));
00222     if (StandardMap->MyGID(row)) {
00223       if (fillF) {
00224             (*rhs)[StandardMap->LID(OverlapMap->GID(ne+i))]+=
00225               +basis.wt*basis.dx*(
00226              // (basis.uu-basis.uuold)/dt*basis.phi[i] +   // 09/21/05 tscoffe
00227                 basis.uuold*basis.phi[i] +                 // 09/21/05 tscoffe
00228                 (1.0/(basis.dx*basis.dx))*basis.duu*basis.dphide[i] -
00229                 8.0/factor/factor*basis.uu*basis.uu*
00230                 (1.0-basis.uu)*basis.phi[i]);
00231       }
00232     }
00233     // Loop over Trial Functions
00234     if (fillMatrix) {
00235       for(int j=0;j < 2; j++) {
00236         if (StandardMap->MyGID(row)) {
00237           column=OverlapMap->GID(ne+j);
00238               jac=basis.wt*basis.dx*(
00239              // basis.phi[j]/dt*basis.phi[i] +    // 09/21/05 tscoffe
00240                 basis.phi[j]*alpha*basis.phi[i] + // 09/21/05 tscoffe
00241           beta*(                                  // 09/21/05 tscoffe
00242           (1.0/(basis.dx*basis.dx))*
00243                 basis.dphide[j]*basis.dphide[i] -
00244                 8.0/factor/factor*
00245                 (2.0*basis.uu-3.0*basis.uu*basis.uu)*
00246                 basis.phi[j]*basis.phi[i])); // 09/21/05 tscoffe
00247           ierr=jacout->SumIntoGlobalValues(row, 1, &jac, &column);
00248         }
00249       }
00250     }
00251         }
00252       }
00253     } 
00254   
00255     // Insert Boundary Conditions and modify Jacobian and function (F)
00256     // U(0)=1
00257     if (MyPID==0) {
00258       if (fillF) 
00259         (*rhs)[0]= (*soln)[0] - 1.0;
00260       if (fillMatrix) {
00261         column=0;
00262         jac=1.0;
00263         jacout->ReplaceGlobalValues(0, 1, &jac, &column);
00264         column=1;
00265         jac=0.0;
00266         jacout->ReplaceGlobalValues(0, 1, &jac, &column);
00267       }
00268     }
00269 
00270   // Insert Boundary Conditions and modify Jacobian and function (F)
00271   // U(xmax)=0
00272   if (MyPID==NumProc-1) {
00273     if (fillF)
00274       (*rhs)[NumMyElements-1]= (*soln)[OverlapNumMyElements-1] - 0.0;
00275     if (fillMatrix) {
00276       row=NumGlobalElements-1;
00277       column=row;
00278       jac=1.0;
00279       jacout->ReplaceGlobalValues(row, 1, &jac, &column);
00280       column--;
00281       jac=0.0;
00282       jacout->ReplaceGlobalValues(row, 1, &jac, &column);
00283     }
00284   }
00285 
00286     // Sync up processors to be safe
00287     Comm->Barrier();
00288    
00289     if (fillMatrix)
00290       jacout->FillComplete();
00291   
00292     return true;
00293   }
00294 
00295   // ---------------------------
00296   // --------------- Set desired initial condition / initial guess
00297   // ---------------------------
00298   bool initializeSoln()
00299   {
00300     Epetra_Vector& x = *xptr;
00301   
00302     double arg;
00303     for(int i=0; i<NumMyElements; i++) {
00304       arg = x[i]/factor;
00305         (*initialSolution)[i] = (1.0 - ( exp(arg) - exp(-arg) ) /
00306         ( exp(arg) + exp(-arg) )) / 2.0;
00307     }
00308     return true;
00309   }
00310 
00311   // Reset problem for next parameter (time) step.
00312   // For now, this simply updates oldsoln with the given Epetra_Vector
00313   bool reset(const Epetra_Vector& x) 
00314     { *oldSolution = x;  return true; };
00315 
00316   // Return a reference to the Epetra_Vector with the old solution
00317   Epetra_Vector& getOldSoln()
00318     { return *oldSolution; };
00319 
00320   // ---------------------------
00321   // --------------- Return a reference to the Epetra_Vector 
00322   // --------------- with the exact analytic solution
00323   // ---------------------------
00324   Epetra_Vector& getExactSoln(double time)
00325     {  
00326       // Create the exact solution vector only if needed and if not already
00327       // created.
00328       if( !exactSolution )
00329         exactSolution = new Epetra_Vector(*xptr);
00330 
00331       Epetra_Vector& x = *xptr;
00332 
00333       for(int i=0; i<NumMyElements; i++)
00334         (*exactSolution)[i] = 
00335           (1.0 - tanh( (x[i]-2.0*time/factor)/factor )) / 2.0;
00336 
00337       return *exactSolution;
00338     }
00339 
00340   // Accesor function for setting time step
00341   void setdt( double dt_ ) { dt = dt_; }
00342   
00343   // Accesor function for time obtaining step
00344   double getdt() { return dt; }
00345   
00346 private:
00347 
00348   double dt;  // Time step size
00349 
00350   Epetra_Vector *oldSolution;
00351   Epetra_Vector *exactSolution;
00352 
00353 };
00354 

Generated on Thu Sep 18 12:30:04 2008 for Rythmos - Transient Integration for Differential Equations by doxygen 1.3.9.1