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
00032
00033
00034
00035
00036
00037
00038
00039
00040
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