1DfemInterface.C

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 // NOX include (for iostream, cmath, etc...)
00030 #include "NOX_Common.H"
00031 
00032 #include "Teuchos_ParameterList.hpp"
00033 
00034 // Class Definition
00035 #include "1DfemInterface.H"
00036 
00037 // Epetra includes
00038 #include "Epetra_Comm.h"
00039 #include "Epetra_Map.h"
00040 #include "Epetra_Vector.h"
00041 #include "Epetra_Import.h"
00042 #include "Epetra_CrsGraph.h"
00043 #include "Epetra_CrsMatrix.h"
00044 
00045 // Constructor - creates the Epetra objects (maps and vectors) 
00046 Interface::Interface(int numGlobalElements, Epetra_Comm& comm, double xmin_,
00047                      double xmax_) :
00048   NumGlobalElements(numGlobalElements),
00049   NumMyElements(0),  // gets set after map creation
00050   MyPID(comm.MyPID()),
00051   NumProc(comm.NumProc()),
00052   xmin(xmin_),
00053   xmax(xmax_),
00054   factor(1.0),
00055   Comm(&comm),
00056   StandardMap(0),
00057   OverlapMap(0),
00058   Importer(0),
00059   initialSolution(0),
00060   rhs(0),
00061   Graph(0),
00062   jacobian(0),
00063   xptr(0)
00064 {
00065 
00066   // Construct a Source Map that puts approximately the same 
00067   // Number of equations on each processor in uniform global ordering
00068   StandardMap = new Epetra_Map(NumGlobalElements, 0, *Comm);
00069 //  std::cout << "StandardMap = new Epetra_Map(NumGlobalElements, 0, *Comm);" << std::endl;
00070 //  std::cout << "typeid(*StandardMap).name() = " << typeid(*StandardMap).name() << std::endl;
00071 
00072   // Get the number of elements owned by this processor
00073   NumMyElements = StandardMap->NumMyElements();
00074 
00075   // Construct an overlaped map for the finite element fill *************
00076   // For single processor jobs, the overlap and standard map are the same
00077   if (NumProc == 1) {
00078     OverlapMap = new Epetra_Map(*StandardMap);
00079   } else {
00080 
00081     int OverlapNumMyElements;
00082     int OverlapMinMyGID;
00083     OverlapNumMyElements = NumMyElements + 2;
00084     if ((MyPID == 0) || (MyPID == NumProc - 1)) 
00085       OverlapNumMyElements --;
00086     
00087     if (MyPID==0) 
00088       OverlapMinMyGID = StandardMap->MinMyGID();
00089     else 
00090       OverlapMinMyGID = StandardMap->MinMyGID() - 1;
00091     
00092     int* OverlapMyGlobalElements = new int[OverlapNumMyElements];
00093     
00094     for (int i = 0; i < OverlapNumMyElements; i ++) 
00095       OverlapMyGlobalElements[i] = OverlapMinMyGID + i;
00096     
00097     OverlapMap = new Epetra_Map(-1, OverlapNumMyElements, 
00098           OverlapMyGlobalElements, 0, *Comm);
00099 
00100     delete [] OverlapMyGlobalElements;
00101 
00102   } // End Overlap map construction *************************************
00103 
00104   // Construct Linear Objects  
00105   Importer = new Epetra_Import(*OverlapMap, *StandardMap);
00106   initialSolution = new Epetra_Vector(*StandardMap);
00107 //  std::cout << "initialSolution = new Epetra_Vector(*StandardMap);" << std::endl;
00108 //  std::cout << "typeid(initialSolution->Map()).name() = " << typeid(initialSolution->Map()).name() << std::endl;
00109 
00110   // Assign non-zero entries in the graph
00111   createGraph();
00112 
00113   // Construct a matrix
00114   jacobian = new Epetra_CrsMatrix (Copy, *Graph);
00115 
00116   // Clean-up 
00117   jacobian->FillComplete();
00118 
00119   // Create the nodal coordinates
00120   xptr = new Epetra_Vector(*StandardMap);
00121   double Length = xmax - xmin;
00122   double dx = Length/((double) NumGlobalElements-1);
00123   for (int i=0; i < NumMyElements; i++) {
00124     (*xptr)[i] = xmin + dx*((double) StandardMap->MinMyGID()+i);
00125   }
00126   
00127   initializeSoln();
00128   
00129 }
00130 
00131 // Destructor
00132 Interface::~Interface()
00133 {
00134   delete jacobian;
00135   delete Graph;
00136   delete Importer;
00137   delete initialSolution;
00138   delete xptr;
00139   delete OverlapMap;
00140   delete StandardMap;
00141 }
00142 
00143 bool Interface::computeF(const Epetra_Vector& x, 
00144           Epetra_Vector& FVec, 
00145           NOX::Epetra::Interface::Required::FillType fillType)
00146 {
00147   return evaluate(fillType, &x, &FVec, 0);
00148 }
00149 
00150 bool Interface::computeJacobian(const Epetra_Vector& x,
00151         Epetra_Operator& Jac)
00152 {
00153   return evaluate(NOX::Epetra::Interface::Required::Jac, &x, 0, 0);
00154 }
00155 
00156 bool Interface::computePrecMatrix(const Epetra_Vector& x)
00157 {
00158   return evaluate(NOX::Epetra::Interface::Required::Prec, &x, 0, 0);
00159 }
00160 bool Interface::computePreconditioner(const Epetra_Vector& x,
00161               Epetra_Operator& Prec,
00162               Teuchos::ParameterList* precParams)
00163 {
00164   cout << "ERROR: Interface::preconditionVector() - "
00165        << "Use Explicit Jaciban only for this test problem!" << endl;
00166   throw "Interface Error";
00167 }
00168 
00169 // Matrix and Residual Fills
00170 bool Interface::evaluate(NOX::Epetra::Interface::Required::FillType flag, 
00171        const Epetra_Vector* soln, 
00172        Epetra_Vector* tmp_rhs, 
00173        Epetra_RowMatrix* tmp_matrix)
00174 {
00175   //Determine what to fill (F or Jacobian)
00176   bool fillF = false;
00177   bool fillMatrix = false;
00178   if (tmp_rhs != 0) {
00179     fillF = true;
00180     rhs = tmp_rhs;
00181   }
00182   else {
00183     fillMatrix = true;
00184   }
00185 
00186   // "flag" can be used to determine how accurate your fill of F should be
00187   // depending on why we are calling evaluate (Could be using computeF to 
00188   // populate a Jacobian or Preconditioner).
00189   if (flag == NOX::Epetra::Interface::Required::Residual) {
00190     // Do nothing for now
00191   }
00192   else if (flag == NOX::Epetra::Interface::Required::Jac) {
00193     // Do nothing for now
00194   }
00195   else if (flag == NOX::Epetra::Interface::Required::Prec) {
00196     // Do nothing for now
00197   }
00198   else if (flag == NOX::Epetra::Interface::Required::User) {
00199     // Do nothing for now
00200   }
00201 
00202 
00203   // Create the overlapped solution and position vectors
00204   Epetra_Vector u(*OverlapMap);
00205   Epetra_Vector x(*OverlapMap);
00206 
00207   // Export Solution to Overlap vector
00208   u.Import(*soln, *Importer, Insert);
00209   x.Import(*xptr, *Importer, Insert);
00210 
00211   // Declare required variables
00212   int ierr;
00213   int OverlapNumMyElements = OverlapMap->NumMyElements();
00214 
00215   int OverlapMinMyGID;
00216   if (MyPID == 0) OverlapMinMyGID = StandardMap->MinMyGID();
00217   else OverlapMinMyGID = StandardMap->MinMyGID()-1;
00218 
00219   int row, column;
00220   double jac;
00221   double xx[2];
00222   double uu[2];
00223   Basis basis;
00224 
00225   // Zero out the objects that will be filled
00226   if (fillF) 
00227     rhs->PutScalar(0.0);
00228   if (fillMatrix) 
00229     jacobian->PutScalar(0.0);
00230 
00231   // Loop Over # of Finite Elements on Processor
00232   for (int ne=0; ne < OverlapNumMyElements-1; ne++) {
00233     
00234     // Loop Over Gauss Points
00235     for(int gp=0; gp < 2; gp++) {
00236       // Get the solution and coordinates at the nodes 
00237       xx[0]=x[ne];
00238       xx[1]=x[ne+1];
00239       uu[0]=u[ne];
00240       uu[1]=u[ne+1];
00241       // Calculate the basis function at the gauss point
00242       basis.computeBasis(gp, xx, uu);
00243               
00244       // Loop over Nodes in Element
00245       for (int i=0; i< 2; i++) {
00246   row=OverlapMap->GID(ne+i);
00247   //printf("Proc=%d GlobalRow=%d LocalRow=%d Owned=%d\n",
00248   //     MyPID, row, ne+i,StandardMap.MyGID(row));
00249   if (StandardMap->MyGID(row)) {
00250     if (fillF) {
00251       (*rhs)[StandardMap->LID(OverlapMap->GID(ne+i))]+=
00252         +basis.wt*basis.dx
00253         *((1.0/(basis.dx*basis.dx))*basis.duu*
00254     basis.dphide[i]+factor*basis.uu*basis.uu*basis.phi[i]);
00255     }
00256   }
00257   // Loop over Trial Functions
00258   if (fillMatrix) {
00259     for(int j=0;j < 2; j++) {
00260       if (StandardMap->MyGID(row)) {
00261         column=OverlapMap->GID(ne+j);
00262         jac=basis.wt*basis.dx*((1.0/(basis.dx*basis.dx))*
00263              basis.dphide[j]*basis.dphide[i]
00264              +2.0*factor*basis.uu*basis.phi[j]*
00265              basis.phi[i]);  
00266         ierr=jacobian->SumIntoGlobalValues(row, 1, &jac, &column);
00267       }
00268     }
00269   }
00270       }
00271     }
00272   } 
00273 
00274   // Insert Boundary Conditions and modify Jacobian and function (F)
00275   // U(0)=1
00276   if (MyPID==0) {
00277     if (fillF) 
00278       (*rhs)[0]= (*soln)[0] - 1.0;
00279     if (fillMatrix) {
00280       column=0;
00281       jac=1.0;
00282       jacobian->ReplaceGlobalValues(0, 1, &jac, &column);
00283       column=1;
00284       jac=0.0;
00285       jacobian->ReplaceGlobalValues(0, 1, &jac, &column);
00286     }
00287   }
00288 
00289   // Sync up processors to be safe
00290   Comm->Barrier();
00291  
00292   jacobian->FillComplete();
00293 
00294   return true;
00295 }
00296 
00297 Epetra_Vector& Interface::getSolution()
00298 {
00299   return *initialSolution;
00300 }
00301 
00302 Epetra_Map& Interface::getMap()
00303 {
00304   return *StandardMap;
00305 }
00306 
00307 Epetra_CrsGraph& Interface::getGraph()
00308 {
00309   return *Graph;
00310 }
00311   
00312 Epetra_Vector& Interface::getMesh()
00313 {
00314   return *xptr;
00315 }
00316   
00317 Epetra_CrsMatrix& Interface::getJacobian()
00318 {
00319   return *jacobian;
00320 }
00321 
00322 bool Interface::createGraph()
00323 {
00324   if (Graph != 0) {
00325     delete Graph;
00326     Graph = 0;
00327   }
00328 
00329   // Create the shell for the 
00330   Graph = new Epetra_CrsGraph(Copy, *StandardMap, 5);
00331 
00332   // Declare required variables
00333   int row, column;
00334   int OverlapNumMyElements = OverlapMap->NumMyElements();
00335   int OverlapMinMyGID;
00336   if (MyPID==0) OverlapMinMyGID = StandardMap->MinMyGID();
00337   else OverlapMinMyGID = StandardMap->MinMyGID()-1;
00338   
00339   // Loop Over # of Finite Elements on Processor
00340   for (int ne=0; ne < OverlapNumMyElements-1; ne++) {
00341           
00342     // Loop over Nodes in Element
00343     for (int i=0; i< 2; i++) {
00344       row=OverlapMap->GID(ne+i);
00345       
00346       // Loop over Trial Functions
00347       for(int j=0;j < 2; j++) {
00348   
00349   // If this row is owned by current processor, add the index
00350   if (StandardMap->MyGID(row)) {
00351     column=OverlapMap->GID(ne+j);
00352     Graph->InsertGlobalIndices(row, 1, &column);
00353   }
00354       }   
00355     }
00356   }
00357   Graph->FillComplete();
00358   return true;
00359 }
00360 
00361 // Set initialSolution to desired initial condition
00362 bool Interface::initializeSoln()
00363 {
00364   initialSolution->PutScalar(1.0); // Default initialization
00365   return true;
00366 }
00367 
00368 //====================================================================
00369 // Basis vector
00370 
00371 // Constructor
00372 Basis::Basis() {
00373   phi = new double[2];
00374   dphide = new double[2];
00375 }
00376 
00377 // Destructor
00378 Basis::~Basis() {
00379   delete [] phi;
00380   delete [] dphide;
00381 }
00382 
00383 // Calculates a linear 1D basis
00384 void Basis::computeBasis(int gp, double *x, double *u, double *uold) {
00385   int N = 2;
00386   if (gp==0) {eta=-1.0/sqrt(3.0); wt=1.0;}
00387   if (gp==1) {eta=1.0/sqrt(3.0); wt=1.0;}
00388 
00389   // Calculate basis function and derivatives at nodel pts
00390   phi[0]=(1.0-eta)/2.0;
00391   phi[1]=(1.0+eta)/2.0;
00392   dphide[0]=-0.5;
00393   dphide[1]=0.5;
00394   
00395   // Caculate basis function and derivative at GP.
00396   dx=0.5*(x[1]-x[0]);
00397   xx=0.0;
00398   uu=0.0;
00399   duu=0.0;
00400   uuold=0.0;
00401   duuold=0.0;
00402   for (int i=0; i < N; i++) {
00403     xx += x[i] * phi[i];
00404     uu += u[i] * phi[i];
00405     duu += u[i] * dphide[i];
00406     if (uold) {
00407       uuold += uold[i] * phi[i];
00408       duuold += uold[i] * dphide[i];
00409     }
00410   }
00411 
00412   return;
00413 }

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