FEApp_InitPostOps.cpp

Go to the documentation of this file.
00001 // $Id: FEApp_InitPostOps.cpp,v 1.8 2008/08/01 22:57:12 etphipp Exp $ 
00002 // $Source: /space/CVS/Trilinos/packages/sacado/example/FEApp/FEApp_InitPostOps.cpp,v $ 
00003 // @HEADER
00004 // ***********************************************************************
00005 // 
00006 //                           Sacado Package
00007 //                 Copyright (2006) Sandia Corporation
00008 // 
00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00010 // the U.S. Government retains certain rights in this software.
00011 // 
00012 // This library is free software; you can redistribute it and/or modify
00013 // it under the terms of the GNU Lesser General Public License as
00014 // published by the Free Software Foundation; either version 2.1 of the
00015 // License, or (at your option) any later version.
00016 //  
00017 // This library is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //  
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
00027 // (etphipp@sandia.gov).
00028 // 
00029 // ***********************************************************************
00030 // @HEADER
00031 
00032 #include "FEApp_InitPostOps.hpp"
00033 #include "Teuchos_TestForException.hpp"
00034 //#include "Teuchos_Exceptions.hpp"
00035 #include "Epetra_Map.h"
00036 
00037 #if SGFAD_ACTIVE
00038 #include "EpetraExt_MatrixMatrix.h"
00039 #endif
00040 
00041 FEApp::ResidualOp::ResidualOp(
00042         const Teuchos::RCP<const Epetra_Vector>& overlapped_xdot,
00043         const Teuchos::RCP<const Epetra_Vector>& overlapped_x,
00044         const Teuchos::RCP<Epetra_Vector>& overlapped_f) :
00045   xdot(overlapped_xdot),
00046   x(overlapped_x),
00047   f(overlapped_f)
00048 {
00049 }
00050 
00051 FEApp::ResidualOp::~ResidualOp()
00052 {
00053 }
00054 
00055 void
00056 FEApp::ResidualOp::elementInit(const FEApp::AbstractElement& e,
00057              unsigned int neqn,
00058              std::vector<double>* elem_xdot,
00059              std::vector<double>& elem_x)
00060 {
00061   // Global node ID
00062   unsigned int node_GID;
00063 
00064   // Local ID of first DOF
00065   unsigned int firstDOF;
00066 
00067   // Number of nodes
00068   unsigned int nnode = e.numNodes();
00069 
00070   // Copy element solution
00071   for (unsigned int i=0; i<nnode; i++) {
00072     node_GID = e.nodeGID(i);
00073     firstDOF = x->Map().LID(node_GID*neqn);
00074     for (unsigned int j=0; j<neqn; j++) {
00075       elem_x[neqn*i+j] = (*x)[firstDOF+j];
00076       if (elem_xdot != NULL)
00077   (*elem_xdot)[neqn*i+j] = (*xdot)[firstDOF+j];
00078     }
00079   }
00080 }
00081 
00082 void
00083 FEApp::ResidualOp::elementPost(const FEApp::AbstractElement& e,
00084              unsigned int neqn,
00085              std::vector<double>& elem_f)
00086 {
00087   // Number of nodes
00088   unsigned int nnode = e.numNodes();
00089 
00090   // Sum element residual into global residual
00091   int row;
00092   unsigned int lrow;
00093   for (unsigned int node_row=0; node_row<nnode; node_row++) {
00094     for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
00095       lrow = neqn*node_row+eq_row;
00096       row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
00097       f->SumIntoGlobalValue(row, 0, elem_f[lrow]);
00098     }
00099   }
00100 }
00101 
00102 void
00103 FEApp::ResidualOp::nodeInit(const FEApp::NodeBC& bc,
00104           unsigned int neqn,
00105           std::vector<double>* node_xdot,
00106           std::vector<double>& node_x)
00107 {
00108   // Global node ID
00109   unsigned int node_GID = bc.getNodeGID();
00110 
00111   // Local ID of first DOF
00112   unsigned int firstDOF = x->Map().LID(node_GID*neqn);
00113 
00114   // Copy node solution
00115   for (unsigned int j=0; j<neqn; j++) {
00116     node_x[j] = (*x)[firstDOF+j];
00117     if (node_xdot != NULL)
00118       (*node_xdot)[j] = (*xdot)[firstDOF+j];
00119   }
00120 }
00121 
00122 void
00123 FEApp::ResidualOp::nodePost(const FEApp::NodeBC& bc,
00124           unsigned int neqn,
00125           std::vector<double>& node_f)
00126 {
00127   // Global node ID
00128   unsigned int node_GID = bc.getNodeGID();
00129 
00130   // Global ID of first DOF
00131   unsigned int firstDOF = node_GID*neqn;
00132 
00133   // Residual offsets
00134   const std::vector<unsigned int>& offsets = bc.getOffsets();
00135 
00136   // Replace global residual
00137   for (unsigned int j=0; j<offsets.size(); j++) {
00138     int row = static_cast<int>(firstDOF + offsets[j]);
00139     if (bc.isOwned())
00140       f->ReplaceGlobalValue(row, 0, node_f[offsets[j]]);
00141     else if (bc.isShared())
00142       f->ReplaceGlobalValue(row, 0, 0.0);
00143   }
00144 }
00145 
00146 FEApp::JacobianOp::JacobianOp(
00147              double alpha, double beta,
00148        const Teuchos::RCP<const Epetra_Vector>& overlapped_xdot,
00149        const Teuchos::RCP<const Epetra_Vector>& overlapped_x,
00150        const Teuchos::RCP<Epetra_Vector>& overlapped_f,
00151        const Teuchos::RCP<Epetra_CrsMatrix>& overlapped_jac) :
00152   m_coeff(alpha),
00153   j_coeff(beta),
00154   xdot(overlapped_xdot),
00155   x(overlapped_x),
00156   f(overlapped_f),
00157   jac(overlapped_jac)
00158 {
00159 }
00160 
00161 FEApp::JacobianOp::~JacobianOp()
00162 {
00163 }
00164 
00165 void
00166 FEApp::JacobianOp::elementInit(
00167        const FEApp::AbstractElement& e,
00168        unsigned int neqn,
00169        std::vector< FadType >* elem_xdot,
00170        std::vector< FadType >& elem_x)
00171 {
00172   // Global node ID
00173   unsigned int node_GID;
00174 
00175   // Local ID of first DOF
00176   unsigned int firstDOF;
00177 
00178   // Number of nodes
00179   unsigned int nnode = e.numNodes();
00180 
00181   // Number of dof
00182   unsigned int ndof = nnode*neqn;
00183 
00184   // Copy element solution
00185   for (unsigned int i=0; i<nnode; i++) {
00186     node_GID = e.nodeGID(i);
00187     firstDOF = x->Map().LID(node_GID*neqn);
00188     for (unsigned int j=0; j<neqn; j++) {
00189       elem_x[neqn*i+j] = 
00190   FadType(ndof, (*x)[firstDOF+j]);
00191       elem_x[neqn*i+j].fastAccessDx(neqn*i+j) = j_coeff;
00192       if (elem_xdot != NULL) {
00193   (*elem_xdot)[neqn*i+j] = 
00194     FadType(ndof, (*xdot)[firstDOF+j]);
00195   (*elem_xdot)[neqn*i+j].fastAccessDx(neqn*i+j) = m_coeff;
00196       }
00197   
00198     }
00199   }
00200 }
00201 
00202 void
00203 FEApp::JacobianOp::elementPost(
00204           const FEApp::AbstractElement& e,
00205           unsigned int neqn,
00206           std::vector< FadType >& elem_f)
00207 {
00208   // Number of nodes
00209   unsigned int nnode = e.numNodes();
00210 
00211   // Sum element residual and Jacobian into global residual, Jacobian
00212   // Loop over nodes in element
00213   int row, col;
00214   unsigned int lrow, lcol;
00215   for (unsigned int node_row=0; node_row<nnode; node_row++) {
00216 
00217     // Loop over equations per node
00218     for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
00219       lrow = neqn*node_row+eq_row;
00220 
00221       // Global row
00222       row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
00223 
00224       // Sum residual
00225       if (f != Teuchos::null)
00226   f->SumIntoGlobalValue(row, 0, elem_f[lrow].val());
00227   
00228       // Check derivative array is nonzero
00229       if (elem_f[lrow].hasFastAccess()) {
00230 
00231   // Loop over nodes in element
00232   for (unsigned int node_col=0; node_col<nnode; node_col++){
00233       
00234     // Loop over equations per node
00235     for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
00236       lcol = neqn*node_col+eq_col;
00237         
00238       // Global column
00239       col = static_cast<int>(e.nodeGID(node_col)*neqn + eq_col);
00240 
00241       // Sum Jacobian
00242       jac->SumIntoGlobalValues(row, 1, 
00243              &(elem_f[lrow].fastAccessDx(lcol)),
00244              &col);
00245 
00246     } // column equations
00247     
00248   } // column nodes
00249   
00250       } // has fast access
00251       
00252     } // row equations
00253 
00254   } // row node
00255 
00256 }
00257 
00258 void
00259 FEApp::JacobianOp::nodeInit(
00260        const FEApp::NodeBC& bc,
00261        unsigned int neqn,
00262        std::vector< FadType >* node_xdot,
00263        std::vector< FadType >& node_x)
00264 {
00265   // Global node ID
00266   unsigned int node_GID = bc.getNodeGID();
00267 
00268   // Local ID of first DOF
00269   unsigned int firstDOF = x->Map().LID(node_GID*neqn);
00270 
00271   // Copy element solution
00272   for (unsigned int j=0; j<neqn; j++) {
00273     node_x[j] = FadType(neqn, (*x)[firstDOF+j]);
00274     node_x[j].fastAccessDx(j) = j_coeff;
00275     if (node_xdot != NULL) {
00276       (*node_xdot)[j] = FadType(neqn, (*xdot)[firstDOF+j]);
00277       (*node_xdot)[j].fastAccessDx(j) = m_coeff;
00278     }
00279   }
00280 }
00281 
00282 void
00283 FEApp::JacobianOp::nodePost(const FEApp::NodeBC& bc,
00284           unsigned int neqn,
00285           std::vector< FadType >& node_f)
00286 {
00287   // Global node ID
00288   unsigned int node_GID = bc.getNodeGID();
00289 
00290   // Global ID of first DOF
00291   unsigned int firstDOF = node_GID*neqn;
00292 
00293   // Residual offsets
00294   const std::vector<unsigned int>& offsets = bc.getOffsets();
00295 
00296   int num_entries;
00297   double* row_view = 0;
00298   int row, col;
00299 
00300   // Loop over equations per node
00301   for (unsigned int eq_row=0; eq_row<offsets.size(); eq_row++) {
00302 
00303     // Global row
00304     row = static_cast<int>(firstDOF + offsets[eq_row]);
00305     
00306     // Replace residual
00307     if (f != Teuchos::null) {
00308       if (bc.isOwned())
00309   f->ReplaceGlobalValue(row, 0, node_f[offsets[eq_row]].val());
00310       else if (bc.isShared())
00311   f->ReplaceGlobalValue(row, 0, 0.0);
00312     }
00313 
00314     // Always zero out row (This takes care of the not-owned case)
00315     if (bc.isOwned() || bc.isShared()) {
00316       jac->ExtractGlobalRowView(row, num_entries, row_view);
00317       for (int k=0; k<num_entries; k++)
00318   row_view[k] = 0.0;
00319     }
00320   
00321     // Check derivative array is nonzero
00322     if (node_f[offsets[eq_row]].hasFastAccess()) {
00323       
00324       // Loop over equations per node
00325       for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
00326         
00327   // Global column
00328   col = static_cast<int>(firstDOF + eq_col);
00329 
00330   // Replace Jacobian
00331   if (bc.isOwned())
00332     jac->ReplaceGlobalValues(row, 1, 
00333            &(node_f[eq_row].fastAccessDx(eq_col)),
00334            &col);
00335 
00336       } // column equations
00337   
00338     } // has fast access
00339       
00340   } // row equations
00341 
00342 }
00343 
00344 FEApp::TangentOp::TangentOp(
00345         double alpha, double beta, bool sum_derivs_,
00346   const Teuchos::RCP<const Epetra_Vector>& overlapped_xdot,
00347   const Teuchos::RCP<const Epetra_Vector>& overlapped_x,
00348   const Teuchos::RCP<Sacado::ScalarParameterVector>& p,
00349   const Teuchos::RCP<const Epetra_MultiVector>& overlapped_Vx,
00350   const Teuchos::RCP<const Epetra_MultiVector>& overlapped_Vxdot,
00351   const Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,double> >& Vp_,
00352   const Teuchos::RCP<Epetra_Vector>& overlapped_f,
00353   const Teuchos::RCP<Epetra_MultiVector>& overlapped_JV,
00354   const Teuchos::RCP<Epetra_MultiVector>& overlapped_fp) :
00355   m_coeff(alpha),
00356   j_coeff(beta),
00357   sum_derivs(sum_derivs_),
00358   xdot(overlapped_xdot),
00359   x(overlapped_x),
00360   params(p),
00361   Vx(overlapped_Vx),
00362   Vxdot(overlapped_Vxdot),
00363   Vp(Vp_),
00364   f(overlapped_f),
00365   JV(overlapped_JV),
00366   fp(overlapped_fp),
00367   num_cols_x(0),
00368   num_cols_p(0),
00369   num_cols_tot(0),
00370   param_offset(0)
00371 {
00372   if (Vx != Teuchos::null)
00373     num_cols_x = Vx->NumVectors();
00374   else if (Vxdot != Teuchos::null)
00375     num_cols_x = Vxdot->NumVectors();
00376   if (params != Teuchos::null) {
00377     if (Vp != Teuchos::null)
00378       num_cols_p = Vp->numCols();
00379     else
00380       num_cols_p = params->size();
00381   }
00382   if (sum_derivs) {
00383     num_cols_tot = num_cols_x;
00384     param_offset = 0;
00385   }
00386   else {
00387     num_cols_tot = num_cols_x + num_cols_p;
00388     param_offset = num_cols_x;
00389   }
00390 
00391   TEST_FOR_EXCEPTION(sum_derivs && (num_cols_x != 0) && (num_cols_p != 0) && 
00392          (num_cols_x != num_cols_p),
00393          std::logic_error,
00394          "Seed matrices Vx and Vp must have the same number " << 
00395          " of columns when sum_derivs is true and both are "
00396          << "non-null!" << std::endl);
00397 }
00398 
00399 FEApp::TangentOp::~TangentOp()
00400 {
00401 }
00402 
00403 void
00404 FEApp::TangentOp::elementInit(
00405        const FEApp::AbstractElement& e,
00406        unsigned int neqn,
00407        std::vector< FadType >* elem_xdot,
00408        std::vector< FadType >& elem_x)
00409 {
00410   // Global node ID
00411   unsigned int node_GID;
00412 
00413   // Local ID of first DOF
00414   unsigned int firstDOF;
00415 
00416   // Number of nodes
00417   unsigned int nnode = e.numNodes();
00418 
00419   // Copy element solution
00420   for (unsigned int i=0; i<nnode; i++) {
00421     node_GID = e.nodeGID(i);
00422     firstDOF = x->Map().LID(node_GID*neqn);
00423 
00424     for (unsigned int j=0; j<neqn; j++) {
00425       if (Vx != Teuchos::null && j_coeff != 0.0) {
00426   elem_x[neqn*i+j] = 
00427     FadType(num_cols_tot, (*x)[firstDOF+j]);
00428   for (int k=0; k<num_cols_x; k++)
00429     elem_x[neqn*i+j].fastAccessDx(k) = j_coeff*(*Vx)[k][firstDOF+j];
00430       }
00431       else
00432   elem_x[neqn*i+j] = 
00433     FadType((*x)[firstDOF+j]);
00434 
00435       if (elem_xdot != NULL) {
00436   if (Vxdot != Teuchos::null && m_coeff != 0.0) {
00437     (*elem_xdot)[neqn*i+j] = 
00438       FadType(num_cols_tot, (*xdot)[firstDOF+j]);
00439     for (int k=0; k<num_cols_x; k++)
00440       (*elem_xdot)[neqn*i+j].fastAccessDx(k) = 
00441         m_coeff*(*Vxdot)[k][firstDOF+j];
00442   }
00443   else
00444     (*elem_xdot)[neqn*i+j] = 
00445       FadType((*xdot)[firstDOF+j]);
00446       }
00447   
00448     }
00449   }
00450 
00451   if (params != Teuchos::null) {
00452     FadType p;
00453     for (unsigned int i=0; i<params->size(); i++) {
00454       p = FadType(num_cols_tot, (*params)[i].baseValue);
00455       if (Vp != Teuchos::null) 
00456   for (int k=0; k<num_cols_p; k++)
00457     p.fastAccessDx(param_offset+k) = (*Vp)(i,k);
00458       else
00459   p.fastAccessDx(param_offset+i) = 1.0;
00460       (*params)[i].family->setValueAsIndependent(p);
00461     }
00462   }
00463 }
00464 
00465 void
00466 FEApp::TangentOp::elementPost(
00467           const FEApp::AbstractElement& e,
00468           unsigned int neqn,
00469           std::vector< FadType >& elem_f)
00470 {
00471   // Number of nodes
00472   unsigned int nnode = e.numNodes();
00473 
00474   int row;
00475   unsigned int lrow;
00476   for (unsigned int node_row=0; node_row<nnode; node_row++) {
00477 
00478     // Loop over equations per node
00479     for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
00480       lrow = neqn*node_row+eq_row;
00481 
00482       // Global row
00483       row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
00484 
00485       // Sum residual
00486       if (f != Teuchos::null)
00487   f->SumIntoGlobalValue(row, 0, elem_f[lrow].val());
00488   
00489       // Extract derivative components for each column
00490       if (JV != Teuchos::null)
00491   for (int col=0; col<num_cols_x; col++)
00492     JV->SumIntoGlobalValue(row, col, elem_f[lrow].dx(col));
00493       if (fp != Teuchos::null)
00494   for (int col=0; col<num_cols_p; col++)
00495     fp->SumIntoGlobalValue(row, col, elem_f[lrow].dx(col+param_offset));
00496       
00497     } // row equations
00498 
00499   } // row node
00500 
00501 }
00502 
00503 void
00504 FEApp::TangentOp::nodeInit(
00505        const FEApp::NodeBC& bc,
00506        unsigned int neqn,
00507        std::vector< FadType >* node_xdot,
00508        std::vector< FadType >& node_x)
00509 {
00510   // Global node ID
00511   unsigned int node_GID = bc.getNodeGID();
00512 
00513   // Local ID of first DOF
00514   unsigned int firstDOF = x->Map().LID(node_GID*neqn);
00515 
00516   // Copy element solution
00517   for (unsigned int j=0; j<neqn; j++) {
00518     if (Vx != Teuchos::null && j_coeff != 0.0) {
00519       node_x[j] = FadType(num_cols_tot, (*x)[firstDOF+j]);
00520       for (int k=0; k < num_cols_x; k++)
00521   node_x[j].fastAccessDx(k) = j_coeff*(*Vx)[k][firstDOF+j];
00522     }
00523     else
00524       node_x[j] = FadType((*x)[firstDOF+j]);
00525 
00526     if (node_xdot != NULL) {
00527       if (Vxdot != Teuchos::null && m_coeff != 0.0) {
00528   (*node_xdot)[j] = 
00529     FadType(num_cols_tot, (*xdot)[firstDOF+j]);
00530   for (int k=0; k < num_cols_x; k++)
00531     (*node_xdot)[j].fastAccessDx(k) = m_coeff*(*Vxdot)[k][firstDOF+j];
00532       }
00533       else
00534   (*node_xdot)[j] = 
00535     FadType((*xdot)[firstDOF+j]);
00536     }
00537   }
00538 
00539   if (params != Teuchos::null) {
00540     FadType p;
00541     for (unsigned int i=0; i<params->size(); i++) {
00542       p = FadType(num_cols_tot, (*params)[i].baseValue);
00543       if (Vp != Teuchos::null) 
00544   for (int k=0; k<num_cols_p; k++)
00545     p.fastAccessDx(param_offset+k) = (*Vp)(i,k);
00546       else
00547   p.fastAccessDx(param_offset+i) = 1.0;
00548       (*params)[i].family->setValueAsIndependent(p);
00549     }
00550   }
00551 }
00552 
00553 void
00554 FEApp::TangentOp::nodePost(const FEApp::NodeBC& bc,
00555           unsigned int neqn,
00556           std::vector< FadType >& node_f)
00557 {
00558   // Global node ID
00559   unsigned int node_GID = bc.getNodeGID();
00560 
00561   // Global ID of first DOF
00562   unsigned int firstDOF = node_GID*neqn;
00563 
00564   // Residual offsets
00565   const std::vector<unsigned int>& offsets = bc.getOffsets();
00566 
00567   int row;
00568 
00569   // Loop over equations per node
00570   for (unsigned int eq_row=0; eq_row<offsets.size(); eq_row++) {
00571 
00572     // Global row
00573     row = static_cast<int>(firstDOF + offsets[eq_row]);
00574     
00575     // Replace residual
00576     if (f != Teuchos::null) {
00577       if (bc.isOwned())
00578   f->ReplaceGlobalValue(row, 0, node_f[offsets[eq_row]].val());
00579       else if (bc.isShared())
00580   f->ReplaceGlobalValue(row, 0, 0.0);
00581     }
00582 
00583     if (bc.isOwned()) {
00584 
00585       // Extract derivative components for each column
00586       if (JV != Teuchos::null && Vx != Teuchos::null)
00587   for (int col=0; col<num_cols_x; col++)
00588     JV->ReplaceGlobalValue(row, col, node_f[offsets[eq_row]].dx(col));
00589 
00590       if (fp != Teuchos::null)
00591   for (int col=0; col<num_cols_p; col++)
00592     fp->ReplaceGlobalValue(row, col, 
00593          node_f[offsets[eq_row]].dx(col+param_offset));
00594     }
00595     else if (bc.isShared()) {
00596       if (JV != Teuchos::null && Vx != Teuchos::null)
00597   for (int col=0; col<num_cols_x; col++)
00598     JV->ReplaceGlobalValue(row, col, 0.0);
00599 
00600       if (fp != Teuchos::null)
00601   for (int col=0; col<num_cols_p; col++)
00602     fp->ReplaceGlobalValue(row, col, 0.0);
00603     }
00604     
00605   } // row equations
00606 
00607 }
00608 
00609 #if SG_ACTIVE
00610 
00611 FEApp::SGResidualOp::SGResidualOp(
00612   const Teuchos::RCP<const Epetra_Map>& base_map,
00613         const Teuchos::RCP<const Stokhos::OrthogPolyBasis<double> >& sg_basis_,
00614   const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
00615   const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x,
00616   const Teuchos::RCP<EpetraExt::BlockVector>& sg_overlapped_f) :
00617   nblock(sg_basis_->size()),
00618   map(base_map),
00619   sg_basis(sg_basis_),
00620   sg_xdot(sg_overlapped_xdot),
00621   sg_x(sg_overlapped_x),
00622   sg_f(sg_overlapped_f),
00623   xdot(sg_xdot != Teuchos::null ? nblock : 0),
00624   x(nblock)
00625 {
00626   for (unsigned int block=0; block<nblock; block++) {
00627     // Allocate vectors for blocks
00628     if (sg_xdot != Teuchos::null)
00629       xdot[block] = Teuchos::rcp(new Epetra_Vector(*map));
00630     x[block] = Teuchos::rcp(new Epetra_Vector(*map));
00631 
00632     // Extract blocks
00633     sg_x->ExtractBlockValues(*x[block], block);
00634     if (sg_xdot != Teuchos::null)
00635       sg_xdot->ExtractBlockValues(*xdot[block], block);
00636   }
00637 }
00638 
00639 FEApp::SGResidualOp::~SGResidualOp()
00640 {
00641 }
00642 
00643 void
00644 FEApp::SGResidualOp::reset(
00645     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
00646     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x)
00647 {
00648   sg_xdot = sg_overlapped_xdot;
00649   sg_x = sg_overlapped_x;
00650 
00651   // Extract blocks
00652   for (unsigned int block=0; block<nblock; block++) {
00653     sg_x->ExtractBlockValues(*x[block], block);
00654     if (sg_xdot != Teuchos::null)
00655       sg_xdot->ExtractBlockValues(*xdot[block], block);
00656   }
00657 }
00658 
00659 void
00660 FEApp::SGResidualOp::elementInit(const FEApp::AbstractElement& e,
00661              unsigned int neqn,
00662              std::vector<SGType>* elem_xdot,
00663              std::vector<SGType>& elem_x)
00664 {
00665   // Global node ID
00666   unsigned int node_GID;
00667 
00668   // Local ID of first DOF
00669   unsigned int firstDOF;
00670 
00671   // Number of nodes
00672   unsigned int nnode = e.numNodes();
00673 
00674   // Allocate appropriate sizes for coefficients
00675   for (unsigned int i=0; i<nnode; i++) {
00676     for (unsigned int j=0; j<neqn; j++) {
00677       if (elem_x[neqn*i+j].size() != nblock)
00678   elem_x[neqn*i+j].resize(nblock);
00679       if (elem_xdot != NULL && (*elem_xdot)[neqn*i+j].size() != nblock)
00680   (*elem_xdot)[neqn*i+j].resize(nblock);
00681       elem_x[neqn*i+j].copyForWrite();
00682       if (elem_xdot != NULL)
00683   (*elem_xdot)[neqn*i+j].copyForWrite();
00684     }
00685   }
00686 
00687   for (unsigned int block=0; block<nblock; block++) {
00688 
00689     // Copy element solution
00690     for (unsigned int i=0; i<nnode; i++) {
00691       node_GID = e.nodeGID(i);
00692       firstDOF = map->LID(node_GID*neqn);
00693       for (unsigned int j=0; j<neqn; j++) {
00694   elem_x[neqn*i+j].fastAccessCoeff(block) = (*x[block])[firstDOF+j];
00695   if (elem_xdot != NULL)
00696     (*elem_xdot)[neqn*i+j].fastAccessCoeff(block) = 
00697       (*xdot[block])[firstDOF+j];
00698       }
00699     }
00700 
00701   }
00702 }
00703 
00704 void
00705 FEApp::SGResidualOp::elementPost(const FEApp::AbstractElement& e,
00706          unsigned int neqn,
00707          std::vector<SGType>& elem_f)
00708 {
00709   // Number of nodes
00710   unsigned int nnode = e.numNodes();
00711 
00712   // Number of SG blocks
00713   unsigned int nblock = sg_basis->size();
00714 
00715   int row;
00716   unsigned int lrow;
00717   double c;
00718 
00719   for (unsigned int block=0; block<nblock; block++) {
00720 
00721     // Sum element residual into global residual
00722     for (unsigned int node_row=0; node_row<nnode; node_row++) {
00723       for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
00724   lrow = neqn*node_row+eq_row;
00725   row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
00726   c =  elem_f[lrow].coeff(block);
00727   sg_f->BlockSumIntoGlobalValues(1, &c, &row, block);
00728       }
00729     }
00730 
00731   }
00732 }
00733 
00734 void
00735 FEApp::SGResidualOp::nodeInit(const FEApp::NodeBC& bc,
00736           unsigned int neqn,
00737           std::vector<SGType>* node_xdot,
00738           std::vector<SGType>& node_x)
00739 {
00740   // Global node ID
00741   unsigned int node_GID = bc.getNodeGID();
00742 
00743   // Local ID of first DOF
00744   unsigned int firstDOF = map->LID(node_GID*neqn);
00745 
00746   // Allocate appropriate sizes for coefficients
00747   for (unsigned int j=0; j<neqn; j++) {
00748     if (node_x[j].size() != nblock)
00749       node_x[j].resize(nblock);
00750     if (node_xdot != NULL && node_x[j].size() != nblock)
00751       (*node_xdot)[j].resize(nblock);
00752     node_x[j].copyForWrite();
00753     if (node_xdot != NULL)
00754       (*node_xdot)[j].copyForWrite();
00755   }
00756 
00757   for (unsigned int block=0; block<nblock; block++) {
00758 
00759     // Copy node solution
00760     for (unsigned int j=0; j<neqn; j++) {
00761       node_x[j].fastAccessCoeff(block) = (*x[block])[firstDOF+j];
00762       if (node_xdot != NULL)
00763   (*node_xdot)[j].fastAccessCoeff(block) = (*xdot[block])[firstDOF+j];
00764     }
00765 
00766   }
00767 }
00768 
00769 void
00770 FEApp::SGResidualOp::nodePost(const FEApp::NodeBC& bc,
00771             unsigned int neqn,
00772             std::vector<SGType>& node_f)
00773 {
00774   // Global node ID
00775   unsigned int node_GID = bc.getNodeGID();
00776 
00777   // Global ID of first DOF
00778   unsigned int firstDOF = node_GID*neqn;
00779 
00780   double c;
00781   double zero = 0.0;
00782 
00783   // Residual offsets
00784   const std::vector<unsigned int>& offsets = bc.getOffsets();
00785 
00786   for (unsigned int block=0; block<nblock; block++) {
00787 
00788     // Replace global residual
00789     for (unsigned int j=0; j<offsets.size(); j++) {
00790       int row = static_cast<int>(firstDOF + offsets[j]);
00791       if (bc.isOwned()) {
00792   c =  node_f[offsets[j]].coeff(block);
00793   sg_f->BlockReplaceGlobalValues(1, &c, &row, block);
00794       }
00795       else if (bc.isShared())
00796   sg_f->BlockReplaceGlobalValues(1, &zero, &row, block);
00797     }
00798 
00799   }
00800 }
00801 
00802 void
00803 FEApp::SGResidualOp::finalizeFill()
00804 {
00805 //   // Load Epetra vectors into block vector
00806 //   for (unsigned int block=0; block<nblock; block++) 
00807 //     sg_f->LoadBlockValues(*f[block], block);
00808 }
00809   
00810 #endif // SG_ACTIVE
00811 
00812 #if SGFAD_ACTIVE
00813 
00814 FEApp::SGJacobianOp::SGJacobianOp(
00815        const Teuchos::RCP<const Epetra_Map>& base_map,
00816        const Teuchos::RCP<const Epetra_CrsGraph>& base_graph,
00817        const Teuchos::RCP<const Stokhos::OrthogPolyBasis<double> >& sg_basis_,
00818        const Teuchos::RCP<const FEApp::SGJacobianOp::tp_type>& Cijk_,
00819        double alpha, double beta,
00820        const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
00821        const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x,
00822        const Teuchos::RCP<EpetraExt::BlockVector>& sg_overlapped_f,
00823        const Teuchos::RCP<EpetraExt::BlockCrsMatrix>& sg_overlapped_jac) :
00824   nblock(sg_basis_->size()),
00825   map(base_map),
00826   graph(base_graph),
00827   sg_basis(sg_basis_),
00828   Cijk(Cijk_),
00829   m_coeff(alpha),
00830   j_coeff(beta),
00831   sg_xdot(sg_overlapped_xdot),
00832   sg_x(sg_overlapped_x),
00833   sg_f(sg_overlapped_f),
00834   sg_jac(sg_overlapped_jac),
00835   xdot(sg_xdot != Teuchos::null ? nblock : 0),
00836   x(nblock)
00837 {
00838   for (unsigned int block=0; block<nblock; block++) {
00839     // Allocate vectors for blocks
00840     if (sg_xdot != Teuchos::null)
00841       xdot[block] = Teuchos::rcp(new Epetra_Vector(*map));
00842     x[block] = Teuchos::rcp(new Epetra_Vector(*map));
00843 
00844     // Extract blocks
00845     sg_x->ExtractBlockValues(*x[block], block);
00846     if (sg_xdot != Teuchos::null)
00847       sg_xdot->ExtractBlockValues(*xdot[block], block);
00848   }
00849 }
00850 
00851 FEApp::SGJacobianOp::~SGJacobianOp()
00852 {
00853 }
00854 
00855 void
00856 FEApp::SGJacobianOp::reset(
00857     double alpha, double beta,
00858     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
00859     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x)
00860 {
00861   m_coeff = alpha;
00862   j_coeff = beta;
00863   sg_xdot = sg_overlapped_xdot;
00864   sg_x = sg_overlapped_x;
00865 
00866   // Extract blocks
00867   for (unsigned int block=0; block<nblock; block++) {
00868     sg_x->ExtractBlockValues(*x[block], block);
00869     if (sg_xdot != Teuchos::null)
00870       sg_xdot->ExtractBlockValues(*xdot[block], block);
00871   }
00872 }
00873 
00874 void
00875 FEApp::SGJacobianOp::elementInit(const FEApp::AbstractElement& e,
00876          unsigned int neqn,
00877          std::vector< SGFadType >* elem_xdot,
00878          std::vector< SGFadType >& elem_x)
00879 {
00880   // Global node ID
00881   unsigned int node_GID;
00882 
00883   // Local ID of first DOF
00884   unsigned int firstDOF;
00885 
00886   // Number of nodes
00887   unsigned int nnode = e.numNodes();
00888 
00889   // Number of dof
00890   unsigned int ndof = nnode*neqn;
00891 
00892   // Copy element solution
00893   for (unsigned int i=0; i<nnode; i++) {
00894     node_GID = e.nodeGID(i);
00895     firstDOF = map->LID(node_GID*neqn);
00896     for (unsigned int j=0; j<neqn; j++) {
00897       elem_x[neqn*i+j] = SGFadType(ndof, 0.0);
00898       elem_x[neqn*i+j].fastAccessDx(neqn*i+j) = j_coeff;
00899       elem_x[neqn*i+j].val().resize(nblock);
00900       elem_x[neqn*i+j].val().copyForWrite();
00901       for (unsigned int block=0; block<nblock; block++)
00902   elem_x[neqn*i+j].val().fastAccessCoeff(block) = 
00903     (*x[block])[firstDOF+j];
00904       if (elem_xdot != NULL) {
00905   (*elem_xdot)[neqn*i+j] = SGFadType(ndof, 0.0);
00906   (*elem_xdot)[neqn*i+j].fastAccessDx(neqn*i+j) = m_coeff;
00907   (*elem_xdot)[neqn*i+j].val().resize(nblock);
00908   (*elem_xdot)[neqn*i+j].val().copyForWrite();
00909   for (unsigned int block=0; block<nblock; block++)
00910     (*elem_xdot)[neqn*i+j].val().fastAccessCoeff(block) = 
00911       (*xdot[block])[firstDOF+j];
00912       }
00913   
00914     }
00915   }
00916 
00917 }
00918 
00919 void
00920 FEApp::SGJacobianOp::elementPost(const FEApp::AbstractElement& e,
00921          unsigned int neqn,
00922          std::vector< SGFadType >& elem_f)
00923 {
00924   // Number of nodes
00925   unsigned int nnode = e.numNodes();
00926 
00927   // Sum element residual and Jacobian into global residual, Jacobian
00928   // Loop over nodes in element
00929   int row, col;
00930   unsigned int lrow, lcol, nl, i, j;
00931   double v1, v2, cijk;
00932   
00933   for (unsigned int node_row=0; node_row<nnode; node_row++) {
00934 
00935     // Loop over equations per node
00936     for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
00937       lrow = neqn*node_row+eq_row;
00938 
00939       // Global row
00940       row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
00941 
00942       // Sum residual
00943       if (sg_f != Teuchos::null)
00944   for (unsigned int k=0; k<nblock; k++) {
00945     v1 = elem_f[lrow].val().coeff(k);
00946     sg_f->BlockSumIntoGlobalValues(1, &v1, &row, k);
00947   }
00948       
00949       // Check derivative array is nonzero
00950       if (elem_f[lrow].hasFastAccess()) {
00951 
00952   // Loop over nodes in element
00953   for (unsigned int node_col=0; node_col<nnode; node_col++){
00954       
00955     // Loop over equations per node
00956     for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
00957       lcol = neqn*node_col+eq_col;
00958         
00959       // Global column
00960       col = static_cast<int>(e.nodeGID(node_col)*neqn + eq_col);
00961 
00962       // Sum Jacobian
00963       for (unsigned int k=0; k<nblock; k++) {
00964         v1 = elem_f[lrow].fastAccessDx(lcol).coeff(k);
00965         nl = Cijk->num_values(k);
00966         for (unsigned int l=0; l<nl; l++) {
00967     Cijk->triple_value(k,l,i,j,cijk); 
00968     v2 = v1 * cijk / Cijk->norm_squared(i);
00969     sg_jac->BlockSumIntoGlobalValues(row, 1, &v2, &col, i, j);
00970         }
00971       } // SG blocks
00972 
00973     } // column equations
00974     
00975   } // column nodes
00976   
00977       } // has fast access
00978       
00979     } // row equations
00980       
00981   } // row node
00982 
00983 }
00984 
00985 void
00986 FEApp::SGJacobianOp::nodeInit(const FEApp::NodeBC& bc,
00987             unsigned int neqn,
00988             std::vector< SGFadType >* node_xdot,
00989             std::vector< SGFadType >& node_x)
00990 {
00991   // Global node ID
00992   unsigned int node_GID = bc.getNodeGID();
00993 
00994   // Local ID of first DOF
00995   unsigned int firstDOF = map->LID(node_GID*neqn);
00996 
00997   // Copy element solution
00998   for (unsigned int j=0; j<neqn; j++) {
00999     node_x[j] = SGFadType(neqn, 0.0);
01000     node_x[j].fastAccessDx(j) = j_coeff;
01001     node_x[j].val().resize(nblock);
01002     node_x[j].val().copyForWrite();
01003     for (unsigned int block=0; block<nblock; block++)
01004       node_x[j].val().fastAccessCoeff(block) = (*x[block])[firstDOF+j];
01005     if (node_xdot != NULL) {
01006       (*node_xdot)[j] = SGFadType(neqn, 0.0);
01007       (*node_xdot)[j].fastAccessDx(j) = m_coeff;
01008       (*node_xdot)[j].val().resize(nblock);
01009       (*node_xdot)[j].val().copyForWrite();
01010       for (unsigned int block=0; block<nblock; block++)
01011   (*node_xdot)[j].val().fastAccessCoeff(block) = 
01012     (*xdot[block])[firstDOF+j];
01013     }
01014   }
01015 }
01016 
01017 void
01018 FEApp::SGJacobianOp::nodePost(const FEApp::NodeBC& bc,
01019             unsigned int neqn,
01020             std::vector< SGFadType >& node_f)
01021 {
01022   // Global node ID
01023   unsigned int node_GID = bc.getNodeGID();
01024 
01025   // Global ID of first DOF
01026   unsigned int firstDOF = node_GID*neqn;
01027 
01028   // Residual offsets
01029   const std::vector<unsigned int>& offsets = bc.getOffsets();
01030 
01031   int num_entries;
01032   double* row_view = 0;
01033   int row, col;
01034   unsigned int nl, i, j;
01035   double v1, v2, cijk, zero;
01036   zero = 0.0;
01037 
01038   // Loop over equations per node
01039   for (unsigned int eq_row=0; eq_row<offsets.size(); eq_row++) {
01040 
01041     // Global row
01042     row = static_cast<int>(firstDOF + offsets[eq_row]);
01043     
01044     // Replace residual
01045     if (sg_f != Teuchos::null) {
01046       if (bc.isOwned()) {
01047   for (unsigned int k=0; k<nblock; k++) {
01048     v1 = node_f[offsets[eq_row]].val().coeff(k);
01049     sg_f->BlockReplaceGlobalValues(1, &v1, &row, k);
01050   }
01051       }
01052       else if (bc.isShared()) {
01053   for (unsigned int k=0; k<nblock; k++)
01054     sg_f->BlockReplaceGlobalValues(1, &zero, &row, k);
01055       }
01056     }
01057 
01058     // Always zero out row (This takes care of the not-owned case)
01059     // Do this for each SG block
01060     if (bc.isOwned() || bc.isShared()) {
01061       for (unsigned int i=0; i<nblock; i++)
01062   for (unsigned int j=0; j<nblock; j++) {
01063     sg_jac->BlockExtractGlobalRowView(row, num_entries, row_view, i, j);
01064     for (int k=0; k<num_entries; k++)
01065       row_view[k] = 0.0;
01066   }
01067     }
01068   
01069     // Check derivative array is nonzero
01070     if (node_f[offsets[eq_row]].hasFastAccess()) {
01071       
01072       // Loop over equations per node
01073       for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
01074         
01075   // Global column
01076   col = static_cast<int>(firstDOF + eq_col);
01077 
01078   // Replace Jacobian
01079   if (bc.isOwned()) {
01080     for (unsigned int k=0; k<nblock; k++) {
01081       v1 = node_f[eq_row].fastAccessDx(eq_col).coeff(k);
01082       nl = Cijk->num_values(k);
01083       for (unsigned int l=0; l<nl; l++) {
01084         Cijk->triple_value(k,l,i,j,cijk); 
01085         v2 = v1 * cijk / Cijk->norm_squared(i);
01086         sg_jac->BlockSumIntoGlobalValues(row, 1, &v2, &col, i, j);
01087       }
01088     }
01089   } // SG blocks
01090 
01091       } // column equations
01092       
01093     } // has fast access
01094     
01095   } // row equations
01096 
01097 }
01098 
01099 void
01100 FEApp::SGJacobianOp::finalizeFill()
01101 {
01102 }
01103 
01104 FEApp::SGMatrixFreeJacobianOp::SGMatrixFreeJacobianOp(
01105        const Teuchos::RCP<const Epetra_Map>& base_map,
01106        const Teuchos::RCP<const Epetra_CrsGraph>& base_graph,
01107        const Teuchos::RCP<const Stokhos::OrthogPolyBasis<double> >& sg_basis_,
01108        double alpha, double beta,
01109        const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
01110        const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x,
01111        const Teuchos::RCP<EpetraExt::BlockVector>& sg_overlapped_f) :
01112   nblock(sg_basis_->size()),
01113   map(base_map),
01114   graph(base_graph),
01115   sg_basis(sg_basis_),
01116   m_coeff(alpha),
01117   j_coeff(beta),
01118   sg_xdot(sg_overlapped_xdot),
01119   sg_x(sg_overlapped_x),
01120   sg_f(sg_overlapped_f),
01121   xdot(sg_xdot != Teuchos::null ? nblock : 0),
01122   x(nblock),
01123   jac(nblock)
01124 {
01125   for (unsigned int block=0; block<nblock; block++) {
01126     // Allocate vectors for blocks
01127     if (sg_xdot != Teuchos::null)
01128       xdot[block] = Teuchos::rcp(new Epetra_Vector(*map));
01129     x[block] = Teuchos::rcp(new Epetra_Vector(*map));
01130     jac[block] = Teuchos::rcp(new Epetra_CrsMatrix(Copy, *graph));
01131 
01132     // Extract blocks
01133     sg_x->ExtractBlockValues(*x[block], block);
01134     if (sg_xdot != Teuchos::null)
01135       sg_xdot->ExtractBlockValues(*xdot[block], block);
01136   }
01137 }
01138 
01139 FEApp::SGMatrixFreeJacobianOp::~SGMatrixFreeJacobianOp()
01140 {
01141 }
01142 
01143 void
01144 FEApp::SGMatrixFreeJacobianOp::reset(
01145     double alpha, double beta,
01146     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_xdot,
01147     const Teuchos::RCP<const EpetraExt::BlockVector>& sg_overlapped_x)
01148 {
01149   m_coeff = alpha;
01150   j_coeff = beta;
01151   sg_xdot = sg_overlapped_xdot;
01152   sg_x = sg_overlapped_x;
01153 
01154   // Extract blocks
01155   for (unsigned int block=0; block<nblock; block++) {
01156     sg_x->ExtractBlockValues(*x[block], block);
01157     if (sg_xdot != Teuchos::null)
01158       sg_xdot->ExtractBlockValues(*xdot[block], block);
01159     jac[block]->PutScalar(0.0);
01160   }
01161 }
01162 
01163 std::vector< Teuchos::RCP<Epetra_CrsMatrix> >&
01164 FEApp::SGMatrixFreeJacobianOp::getJacobianBlocks()
01165 {
01166   return jac;
01167 }
01168 
01169 
01170 void
01171 FEApp::SGMatrixFreeJacobianOp::elementInit(const FEApp::AbstractElement& e,
01172          unsigned int neqn,
01173          std::vector< SGFadType >* elem_xdot,
01174          std::vector< SGFadType >& elem_x)
01175 {
01176   // Global node ID
01177   unsigned int node_GID;
01178 
01179   // Local ID of first DOF
01180   unsigned int firstDOF;
01181 
01182   // Number of nodes
01183   unsigned int nnode = e.numNodes();
01184 
01185   // Number of dof
01186   unsigned int ndof = nnode*neqn;
01187 
01188   // Copy element solution
01189   for (unsigned int i=0; i<nnode; i++) {
01190     node_GID = e.nodeGID(i);
01191     firstDOF = map->LID(node_GID*neqn);
01192     for (unsigned int j=0; j<neqn; j++) {
01193       elem_x[neqn*i+j] = SGFadType(ndof, 0.0);
01194       elem_x[neqn*i+j].fastAccessDx(neqn*i+j) = j_coeff;
01195       elem_x[neqn*i+j].val().resize(nblock);
01196       elem_x[neqn*i+j].val().copyForWrite();
01197       for (unsigned int block=0; block<nblock; block++)
01198   elem_x[neqn*i+j].val().fastAccessCoeff(block) = 
01199     (*x[block])[firstDOF+j];
01200       if (elem_xdot != NULL) {
01201   (*elem_xdot)[neqn*i+j] = SGFadType(ndof, 0.0);
01202   (*elem_xdot)[neqn*i+j].fastAccessDx(neqn*i+j) = m_coeff;
01203   (*elem_xdot)[neqn*i+j].val().resize(nblock);
01204   (*elem_xdot)[neqn*i+j].val().copyForWrite();
01205   for (unsigned int block=0; block<nblock; block++)
01206     (*elem_xdot)[neqn*i+j].val().fastAccessCoeff(block) = 
01207       (*xdot[block])[firstDOF+j];
01208       }
01209   
01210     }
01211   }
01212 
01213 }
01214 
01215 void
01216 FEApp::SGMatrixFreeJacobianOp::elementPost(const FEApp::AbstractElement& e,
01217          unsigned int neqn,
01218          std::vector< SGFadType >& elem_f)
01219 {
01220   // Number of nodes
01221   unsigned int nnode = e.numNodes();
01222 
01223   // Sum element residual and Jacobian into global residual, Jacobian
01224   // Loop over nodes in element
01225   int row, col;
01226   unsigned int lrow, lcol;
01227   double c;
01228   
01229   for (unsigned int node_row=0; node_row<nnode; node_row++) {
01230     
01231     // Loop over equations per node
01232     for (unsigned int eq_row=0; eq_row<neqn; eq_row++) {
01233       lrow = neqn*node_row+eq_row;
01234       
01235       // Global row
01236       row = static_cast<int>(e.nodeGID(node_row)*neqn + eq_row);
01237 
01238       // Sum residual
01239       if (sg_f != Teuchos::null) 
01240   for (unsigned int block=0; block<nblock; block++) {
01241     c = elem_f[lrow].val().coeff(block);
01242     sg_f->BlockSumIntoGlobalValues(1, &c, &row, block);
01243   }
01244       
01245       // Check derivative array is nonzero
01246       if (elem_f[lrow].hasFastAccess()) {
01247 
01248   // Loop over nodes in element
01249   for (unsigned int node_col=0; node_col<nnode; node_col++){
01250       
01251     // Loop over equations per node
01252     for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
01253       lcol = neqn*node_col+eq_col;
01254         
01255       // Global column
01256       col = static_cast<int>(e.nodeGID(node_col)*neqn + eq_col);
01257 
01258       // Sum Jacobian
01259        for (unsigned int block=0; block<nblock; block++) {
01260          c = elem_f[lrow].fastAccessDx(lcol).coeff(block);
01261          jac[block]->SumIntoGlobalValues(row, 1, &c, &col);
01262        }
01263 
01264     } // column equations
01265       
01266   } // column nodes
01267   
01268       } // has fast access
01269       
01270     } // row equations
01271       
01272   } // row node
01273 
01274 }
01275 
01276 void
01277 FEApp::SGMatrixFreeJacobianOp::nodeInit(const FEApp::NodeBC& bc,
01278             unsigned int neqn,
01279             std::vector< SGFadType >* node_xdot,
01280             std::vector< SGFadType >& node_x)
01281 {
01282   // Global node ID
01283   unsigned int node_GID = bc.getNodeGID();
01284 
01285   // Local ID of first DOF
01286   unsigned int firstDOF = map->LID(node_GID*neqn);
01287 
01288   // Copy element solution
01289   for (unsigned int j=0; j<neqn; j++) {
01290     node_x[j] = SGFadType(neqn, 0.0);
01291     node_x[j].fastAccessDx(j) = j_coeff;
01292     node_x[j].val().resize(nblock);
01293     node_x[j].val().copyForWrite();
01294     for (unsigned int block=0; block<nblock; block++)
01295       node_x[j].val().fastAccessCoeff(block) = (*x[block])[firstDOF+j];
01296     if (node_xdot != NULL) {
01297       (*node_xdot)[j] = SGFadType(neqn, 0.0);
01298       (*node_xdot)[j].fastAccessDx(j) = m_coeff;
01299       (*node_xdot)[j].val().resize(nblock);
01300       (*node_xdot)[j].val().copyForWrite();
01301       for (unsigned int block=0; block<nblock; block++)
01302   (*node_xdot)[j].val().fastAccessCoeff(block) = 
01303     (*xdot[block])[firstDOF+j];
01304     }
01305   }
01306 }
01307 
01308 void
01309 FEApp::SGMatrixFreeJacobianOp::nodePost(const FEApp::NodeBC& bc,
01310             unsigned int neqn,
01311             std::vector< SGFadType >& node_f)
01312 {
01313   // Global node ID
01314   unsigned int node_GID = bc.getNodeGID();
01315 
01316   // Global ID of first DOF
01317   unsigned int firstDOF = node_GID*neqn;
01318 
01319   // Residual offsets
01320   const std::vector<unsigned int>& offsets = bc.getOffsets();
01321 
01322   int num_entries;
01323   double* row_view = 0;
01324   int row, col;
01325   double c;
01326   double zero = 0.0;
01327 
01328   for (unsigned int block=0; block<nblock; block++) {
01329 
01330     // Loop over equations per node
01331     for (unsigned int eq_row=0; eq_row<offsets.size(); eq_row++) {
01332 
01333       // Global row
01334       row = static_cast<int>(firstDOF + offsets[eq_row]);
01335     
01336       // Replace residual
01337       if (sg_f != Teuchos::null) {
01338   if (bc.isOwned()) {
01339     c = node_f[offsets[eq_row]].val().coeff(block);
01340     sg_f->BlockReplaceGlobalValues(1, &c, &row, block);
01341   }
01342   else if (bc.isShared())
01343     sg_f->BlockReplaceGlobalValues(1, &zero, &row, block);
01344       }
01345 
01346       // Always zero out row (This takes care of the not-owned case)
01347       if (bc.isOwned() || bc.isShared()) {
01348   jac[block]->ExtractGlobalRowView(row, num_entries, row_view);
01349   for (int k=0; k<num_entries; k++)
01350     row_view[k] = 0.0;
01351       }
01352   
01353       // Check derivative array is nonzero
01354       if (node_f[offsets[eq_row]].hasFastAccess()) {
01355       
01356   // Loop over equations per node
01357   for (unsigned int eq_col=0; eq_col<neqn; eq_col++) {
01358         
01359     // Global column
01360     col = static_cast<int>(firstDOF + eq_col);
01361 
01362     // Replace Jacobian
01363     if (bc.isOwned()) {
01364       c = node_f[eq_row].fastAccessDx(eq_col).coeff(block);
01365       jac[block]->ReplaceGlobalValues(row, 1, &c, &col);
01366     }
01367 
01368   } // column equations
01369     
01370       } // has fast access
01371   
01372     } // row equations
01373 
01374   } // SG blocks
01375 
01376 }
01377 
01378 void
01379 FEApp::SGMatrixFreeJacobianOp::finalizeFill()
01380 {
01381 }
01382 
01383 #endif // SGFAD_ACTIVE

Generated on Wed May 12 21:59:03 2010 for Sacado Package Browser (Single Doxygen Collection) by  doxygen 1.4.7