SundanceFunctionalEvaluator.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceFunctionalEvaluator.hpp"
00032 #include "SundanceEquationSet.hpp"
00033 #include "SundanceAssembler.hpp"
00034 #include "SundanceSymbPreprocessor.hpp"
00035 #include "SundanceDiscreteFunction.hpp"
00036 #include "SundanceEquationSet.hpp"
00037 #include "SundanceDiscreteSpace.hpp"
00038 #include "TSFSequentialIteratorImpl.hpp"
00039 #include "SundanceOut.hpp"
00040 #include "SundanceTabs.hpp"
00041 
00042 using namespace Sundance;
00043 using namespace Sundance;
00044 using namespace Sundance;
00045 using namespace Sundance;
00046 using namespace Sundance;
00047 using namespace Sundance;
00048 using namespace Sundance;
00049 using namespace Teuchos;
00050 
00051 
00052 using std::endl;
00053 using std::setw;
00054 
00055 
00056 namespace Sundance
00057 {
00058 double evaluateIntegral(const Mesh& mesh, const Expr& expr)
00059 {
00060   FunctionalEvaluator eval(mesh, expr);
00061   return eval.evaluate();
00062 }
00063 }
00064 
00065 FunctionalEvaluator::FunctionalEvaluator()
00066   : assembler_(),
00067     varValues_(),
00068     vecType_(),
00069     gradient_()
00070 {}
00071 
00072 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00073   const Expr& integral)
00074   : assembler_(),
00075     varValues_(),
00076     vecType_(),
00077     gradient_(1)
00078 {
00079   Array<Expr> fields;
00080   Expr bcs;
00081   Expr params;
00082 
00083   
00084   RCP<EquationSet> eqnSet 
00085     = rcp(new EquationSet(integral, bcs, params, params, fields, fields));
00086   
00087   
00088   assembler_ = rcp(new Assembler(mesh, eqnSet));
00089 }
00090 
00091 
00092 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00093   const Expr& integral,
00094   const Expr& bcs,
00095   const Expr& var,
00096   const Expr& varValues,
00097   const VectorType<double>& vectorType)
00098   : assembler_(),
00099     varValues_(varValues),
00100     vecType_(vectorType),
00101     gradient_(1)
00102 {
00103   Array<Expr> v = tuple(var.flatten());
00104   Array<Expr> v0 = tuple(varValues.flatten());
00105   Array<Expr> fixed;
00106   Expr params;
00107   
00108   RCP<EquationSet> eqnSet 
00109     = rcp(new EquationSet(integral, bcs, v, v0, params, params, fixed, fixed));
00110 
00111   assembler_ = rcp(new Assembler(mesh, eqnSet, tuple(vectorType), tuple(vectorType), false));
00112 }
00113 
00114 
00115 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00116   const Expr& integral,
00117   const Expr& bcs,
00118   const Expr& vars,
00119   const Expr& varEvalPts,
00120   const Expr& fields,
00121   const Expr& fieldValues,
00122   const VectorType<double>& vectorType)
00123   : assembler_(),
00124     varValues_(varEvalPts),
00125     vecType_(vectorType),
00126     gradient_(1)
00127 {
00128   Array<Expr> f = tuple(fields.flatten());
00129   Array<Expr> f0 = tuple(fieldValues.flatten());
00130   Array<Expr> v = tuple(vars.flatten());
00131   Array<Expr> v0 = tuple(varEvalPts.flatten());
00132 
00133   Expr params;
00134   
00135   RCP<EquationSet> eqnSet 
00136     = rcp(new EquationSet(integral, bcs, v, v0, params, params, f, f0));
00137 
00138   assembler_ = rcp(new Assembler(mesh, eqnSet, tuple(vectorType), tuple(vectorType), false));
00139 }
00140 
00141 double FunctionalEvaluator::evaluate() const
00142 {
00143   double value;
00144   assembler_->evaluate(value);
00145   return value;
00146 }
00147 
00148 
00149 Vector<double> FunctionalEvaluator::evalGradientVector(double& value) const 
00150 {
00151   assembler_->evaluate(value, gradient_);
00152 
00153   return gradient_[0];
00154 }
00155 
00156 Expr FunctionalEvaluator::evalGradient(double& value) const 
00157 {
00158   Vector<double> g = evalGradientVector(value);
00159 
00160   Array<Expr> rtn(assembler_->rowSpace().size());
00161   for (int i=0; i<rtn.size(); i++)
00162   {
00163     std::string name = "gradient";
00164     if (rtn.size() > 1) name += "[" + Teuchos::toString(i) + "]";
00165     rtn[i] = new DiscreteFunction(*(assembler_->rowSpace()[i]),
00166       g.getBlock(i), name);
00167   }
00168   if ((int)rtn.size()==1)
00169   {
00170     return rtn[0];
00171   }
00172   else
00173   {
00174     return new ListExpr(rtn);
00175   }
00176 }
00177 
00178 
00179 double FunctionalEvaluator::fdGradientCheck(double h) const
00180 {
00181   bool showAll = false;
00182   Tabs tabs;
00183   double f0, fPlus, fMinus;
00184   Expr gradF0 = evalGradient(f0);
00185 
00186   FancyOStream& os = Out::os();
00187 
00188 
00189   DiscreteFunction* df = DiscreteFunction::discFunc(varValues_);
00190   DiscreteFunction* dg = DiscreteFunction::discFunc(gradF0);
00191   Vector<double> x = df->getVector();
00192   Vector<double> x0 = x.copy();
00193   Vector<double> gf = dg->getVector();
00194 
00195   RCP<GhostView<double> > xView = df->ghostView();
00196   RCP<GhostView<double> > gradF0View = dg->ghostView();
00197 
00198 
00199   TEST_FOR_EXCEPTION(xView.get() == 0, RuntimeError, 
00200     "bad pointer in FunctionalEvaluator::fdGradientCheck");
00201   TEST_FOR_EXCEPTION(gradF0View.get() == 0, RuntimeError, 
00202     "bad pointer in FunctionalEvaluator::fdGradientCheck");
00203 
00204   int nTot = x.space().dim();
00205   int n = x.space().numLocalElements();
00206   int lowestIndex = x.space().lowestLocallyOwnedIndex();
00207 
00208   os << tabs << "doing fd check:  h=" << h << std::endl;
00209   Array<double> df_dx(n);
00210 
00211   int localIndex = 0;
00212   for (int globalIndex=0; globalIndex<nTot; globalIndex++)
00213   {
00214     double tmp=0.0;
00215     bool isLocal = globalIndex >= lowestIndex 
00216       && globalIndex < (lowestIndex+n);
00217     if (isLocal)
00218     {
00219       tmp = xView->getElement(globalIndex);
00220       x.setElement(globalIndex, tmp + h);
00221     }
00222 
00223     df->setVector(x);
00224     fPlus = evaluate();
00225     if (isLocal)
00226     {
00227       x.setElement(globalIndex, tmp - h);
00228     }
00229 
00230     df->setVector(x);
00231     fMinus = evaluate();
00232       
00233     if (isLocal)
00234     {
00235       df_dx[localIndex] = (fPlus - fMinus)/2.0/h;
00236       os << "g=" << setw(5) << globalIndex << ", l=" << setw(5) << localIndex << " f0="
00237          << setw(12) << f0 
00238          << " fPlus=" << setw(12) << fPlus << " fMinus=" << setw(12) << fMinus << " df_dx="
00239          << setw(12) << df_dx[localIndex] << std::endl;
00240       if (showAll)
00241       {
00242         os << "i " << globalIndex << " x_i=" << tmp 
00243            << " f(x)=" << f0 
00244            << " f(x+h)=" << fPlus 
00245            << " f(x-h)=" << fMinus << std::endl;
00246       }
00247       x.setElement(globalIndex, tmp);
00248       localIndex++;
00249     }
00250     df->setVector(x);
00251   }
00252   
00253   double localMaxErr = 0.0;
00254 
00255   showAll = true;
00256   int k=0;
00257   VectorSpace<double> space = x.space();
00258   for (SequentialIterator<double> i=space.begin(); i!=space.end(); i++, k++)
00259   {
00260     double num =  fabs(df_dx[k]-gf[i]);
00261     double den = fabs(df_dx[k]) + fabs(gf[i]);
00262     double r = 0.0;
00263     if (fabs(den) > 1.0e-10) r = num/den;
00264     else r = 1.0;
00265     if (showAll)
00266     {
00267       os << "i " << i;
00268       os << " FD=" << df_dx[k] 
00269          << " grad=" << gf[i]
00270          << " r=" << r << std::endl;
00271     }
00272     if (localMaxErr < r) localMaxErr = r;
00273   }
00274   os << "local max error = " << localMaxErr << std::endl;
00275   
00276   double maxErr = localMaxErr;
00277   df->mesh().comm().allReduce((void*) &localMaxErr, (void*) &maxErr, 1, 
00278     MPIComm::DOUBLE, MPIComm::MAX);
00279   os << tabs << "fd check: max error = " << maxErr << std::endl;
00280 
00281   return maxErr;
00282 }
00283 

Site Contact