00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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