SundanceFunctionalEvaluator.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 #include "SundanceFunctionalEvaluator.hpp"
00043 #include "SundanceEquationSet.hpp"
00044 #include "SundanceAssembler.hpp"
00045 #include "SundanceSymbPreprocessor.hpp"
00046 #include "SundanceDiscreteFunction.hpp"
00047 #include "SundanceEquationSet.hpp"
00048 #include "SundanceDiscreteSpace.hpp"
00049 #include "SundanceOut.hpp"
00050 #include "PlayaTabs.hpp"
00051 
00052 using namespace Sundance;
00053 using namespace Teuchos;
00054 using namespace Playa;
00055 
00056 
00057 using std::endl;
00058 using std::setw;
00059 
00060 
00061 namespace Sundance
00062 {
00063 double evaluateIntegral(const Mesh& mesh, const Expr& expr)
00064 {
00065   FunctionalEvaluator eval(mesh, expr);
00066   return eval.evaluate();
00067 }
00068 }
00069 
00070 FunctionalEvaluator::FunctionalEvaluator()
00071   : assembler_(),
00072     varValues_(),
00073     vecType_(),
00074     gradient_()
00075 {}
00076 
00077 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00078   const Expr& integral)
00079   : assembler_(),
00080     varValues_(),
00081     vecType_(),
00082     gradient_(1)
00083 {
00084   Array<Expr> fields;
00085   Expr bcs;
00086   Expr params;
00087 
00088   
00089   RCP<EquationSet> eqnSet 
00090     = rcp(new EquationSet(integral, bcs, params, params, fields, fields));
00091   
00092   
00093   assembler_ = rcp(new Assembler(mesh, eqnSet));
00094 }
00095 
00096 
00097 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00098   const Expr& integral,
00099   const Expr& bcs,
00100   const Expr& var,
00101   const Expr& varValues,
00102   const VectorType<double>& vectorType)
00103   : assembler_(),
00104     varValues_(varValues),
00105     vecType_(vectorType),
00106     gradient_(1)
00107 {
00108   Array<Expr> v = tuple(var.flatten());
00109   Array<Expr> v0 = tuple(varValues.flatten());
00110   Array<Expr> fixed;
00111   Expr params;
00112   
00113   RCP<EquationSet> eqnSet 
00114     = rcp(new EquationSet(integral, bcs, v, v0, params, params, fixed, fixed));
00115 
00116   assembler_ = rcp(new Assembler(mesh, eqnSet, tuple(vectorType), tuple(vectorType), false));
00117 }
00118 
00119 
00120 FunctionalEvaluator::FunctionalEvaluator(const Mesh& mesh,
00121   const Expr& integral,
00122   const Expr& bcs,
00123   const Expr& vars,
00124   const Expr& varEvalPts,
00125   const Expr& fields,
00126   const Expr& fieldValues,
00127   const VectorType<double>& vectorType)
00128   : assembler_(),
00129     varValues_(varEvalPts),
00130     vecType_(vectorType),
00131     gradient_(1)
00132 {
00133   Array<Expr> f = tuple(fields.flatten());
00134   Array<Expr> f0 = tuple(fieldValues.flatten());
00135   Array<Expr> v = tuple(vars.flatten());
00136   Array<Expr> v0 = tuple(varEvalPts.flatten());
00137 
00138   Expr params;
00139   
00140   RCP<EquationSet> eqnSet 
00141     = rcp(new EquationSet(integral, bcs, v, v0, params, params, f, f0));
00142 
00143   assembler_ = rcp(new Assembler(mesh, eqnSet, tuple(vectorType), tuple(vectorType), false));
00144 }
00145 
00146 double FunctionalEvaluator::evaluate() const
00147 {
00148   double value;
00149   assembler_->evaluate(value);
00150   return value;
00151 }
00152 
00153 
00154 Vector<double> FunctionalEvaluator::evalGradientVector(double& value) const 
00155 {
00156   assembler_->evaluate(value, gradient_);
00157 
00158   return gradient_[0];
00159 }
00160 
00161 Expr FunctionalEvaluator::evalGradient(double& value) const 
00162 {
00163   Vector<double> g = evalGradientVector(value);
00164 
00165   Array<Expr> rtn(assembler_->rowSpace().size());
00166   for (int i=0; i<rtn.size(); i++)
00167   {
00168     std::string name = "gradient";
00169     if (rtn.size() > 1) name += "[" + Teuchos::toString(i) + "]";
00170     rtn[i] = new DiscreteFunction(*(assembler_->rowSpace()[i]),
00171       g.getBlock(i), name);
00172   }
00173   if ((int)rtn.size()==1)
00174   {
00175     return rtn[0];
00176   }
00177   else
00178   {
00179     return new ListExpr(rtn);
00180   }
00181 }
00182 
00183 
00184 double FunctionalEvaluator::fdGradientCheck(double h) const
00185 {
00186   bool showAll = false;
00187   Tabs tabs;
00188   double f0, fPlus, fMinus;
00189   Expr gradF0 = evalGradient(f0);
00190 
00191   FancyOStream& os = Out::os();
00192 
00193 
00194   DiscreteFunction* df = DiscreteFunction::discFunc(varValues_);
00195   DiscreteFunction* dg = DiscreteFunction::discFunc(gradF0);
00196   Vector<double> x = df->getVector();
00197   Vector<double> x0 = x.copy();
00198   Vector<double> gf = dg->getVector();
00199 
00200   RCP<GhostView<double> > xView = df->ghostView();
00201   RCP<GhostView<double> > gradF0View = dg->ghostView();
00202 
00203 
00204   TEUCHOS_TEST_FOR_EXCEPTION(xView.get() == 0, std::runtime_error, 
00205     "bad pointer in FunctionalEvaluator::fdGradientCheck");
00206   TEUCHOS_TEST_FOR_EXCEPTION(gradF0View.get() == 0, std::runtime_error, 
00207     "bad pointer in FunctionalEvaluator::fdGradientCheck");
00208 
00209   int nTot = x.space().dim();
00210   int n = x.space().numLocalElements();
00211   int lowestIndex = x.space().baseGlobalNaturalIndex();
00212 
00213   os << tabs << "doing fd check:  h=" << h << std::endl;
00214   Array<double> df_dx(n);
00215 
00216   int localIndex = 0;
00217   for (int globalIndex=0; globalIndex<nTot; globalIndex++)
00218   {
00219     double tmp=0.0;
00220     bool isLocal = globalIndex >= lowestIndex 
00221       && globalIndex < (lowestIndex+n);
00222     if (isLocal)
00223     {
00224       tmp = xView->getElement(globalIndex);
00225       loadable(x)->setElement(globalIndex, tmp + h);
00226     }
00227 
00228     df->setVector(x);
00229     fPlus = evaluate();
00230     if (isLocal)
00231     {
00232       loadable(x)->setElement(globalIndex, tmp - h);
00233     }
00234 
00235     df->setVector(x);
00236     fMinus = evaluate();
00237       
00238     if (isLocal)
00239     {
00240       df_dx[localIndex] = (fPlus - fMinus)/2.0/h;
00241       os << "g=" << setw(5) << globalIndex << ", l=" << setw(5) << localIndex << " f0="
00242          << setw(12) << f0 
00243          << " fPlus=" << setw(12) << fPlus << " fMinus=" << setw(12) << fMinus << " df_dx="
00244          << setw(12) << df_dx[localIndex] << std::endl;
00245       if (showAll)
00246       {
00247         os << "i " << globalIndex << " x_i=" << tmp 
00248            << " f(x)=" << f0 
00249            << " f(x+h)=" << fPlus 
00250            << " f(x-h)=" << fMinus << std::endl;
00251       }
00252       loadable(x)->setElement(globalIndex, tmp);
00253       localIndex++;
00254     }
00255     df->setVector(x);
00256   }
00257   
00258   double localMaxErr = 0.0;
00259 
00260   showAll = true;
00261   VectorSpace<double> space = x.space();
00262   for (int i=0; i<space.numLocalElements(); i++)
00263   {
00264     double num =  fabs(df_dx[i]-gf[i]);
00265     double den = fabs(df_dx[i]) + fabs(gf[i]) + 1.0e-14;
00266     double r = 0.0;
00267     if (fabs(den) > 1.0e-16) r = num/den;
00268     else r = 1.0;
00269     if (showAll)
00270     {
00271       os << "i " << i;
00272       os << " FD=" << df_dx[i] 
00273          << " grad=" << gf[i]
00274          << " r=" << r << std::endl;
00275     }
00276     if (localMaxErr < r) localMaxErr = r;
00277   }
00278   os << "local max error = " << localMaxErr << std::endl;
00279   
00280   double maxErr = localMaxErr;
00281   df->mesh().comm().allReduce((void*) &localMaxErr, (void*) &maxErr, 1, 
00282     MPIDataType::doubleType(), MPIOp::maxOp());
00283   os << tabs << "fd check: max error = " << maxErr << std::endl;
00284 
00285   return maxErr;
00286 }
00287 

Site Contact