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 "SundanceBernstein.hpp"
00043 #include "SundanceADReal.hpp"
00044 #include "PlayaExceptions.hpp"
00045 #include "SundanceSpatialDerivSpecifier.hpp"
00046 #include "SundancePoint.hpp"
00047 #include "SundanceObjectWithVerbosity.hpp"
00048 #include "SundanceOut.hpp"
00049
00050 using namespace Sundance;
00051 using namespace Teuchos;
00052
00053
00054 Bernstein::Bernstein(int order)
00055 : order_(order)
00056 {
00057 TEUCHOS_TEST_FOR_EXCEPTION(order < 0, std::runtime_error,
00058 "invalid polynomial order=" << order
00059 << " in Bernstein ctor");
00060 }
00061
00062 bool Bernstein::supportsCellTypePair(
00063 const CellType& maximalCellType,
00064 const CellType& cellType
00065 ) const
00066 {
00067 switch(maximalCellType)
00068 {
00069 case LineCell:
00070 switch(cellType)
00071 {
00072 case LineCell:
00073 case PointCell:
00074 return true;
00075 default:
00076 return false;
00077 }
00078 case TriangleCell:
00079 switch(cellType)
00080 {
00081 case TriangleCell:
00082 case LineCell:
00083 case PointCell:
00084 return true;
00085 default:
00086 return false;
00087 }
00088 case TetCell:
00089 switch(cellType)
00090 {
00091 case TetCell:
00092 case TriangleCell:
00093 case LineCell:
00094 case PointCell:
00095 return true;
00096 default:
00097 return false;
00098 }
00099 default:
00100 return false;
00101 }
00102 }
00103
00104 void Bernstein::print(std::ostream& os) const
00105 {
00106 os << "Bernstein(" << order_ << ")";
00107 }
00108
00109 int Bernstein::nReferenceDOFsWithoutFacets(
00110 const CellType& maximalCellType,
00111 const CellType& cellType
00112 ) const
00113 {
00114 if (order_==0)
00115 {
00116 if (maximalCellType != cellType) return 0;
00117 return 1;
00118 }
00119
00120 switch(cellType)
00121 {
00122 case PointCell:
00123 return 1;
00124 case LineCell:
00125 return order_-1;
00126 case TriangleCell:
00127 if (order_ < 3) return 0;
00128 if (order_ >= 3) return (order_-1)*(order_-2)/2;
00129 break;
00130 case QuadCell:
00131 if (order_==1) return 0;
00132 if (order_==2) return 1;
00133 TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error,
00134 "Bernstein order > 2 not implemented "
00135 "for quad cells");
00136 case TetCell:
00137 if (order_<=2) return 0;
00138 TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error,
00139 "Bernstein order > 2 not implemented "
00140 "for tet cells");
00141 case BrickCell:
00142 if (order_<=1) return 0;
00143 if (order_==2) return 1;
00144 TEUCHOS_TEST_FOR_EXCEPTION(order_>2, std::runtime_error,
00145 "Bernstein order > 2 not implemented "
00146 "for brick cells");
00147 default:
00148 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00149 << cellType << " not implemented in Bernstein basis");
00150 return -1;
00151 }
00152 return -1;
00153 }
00154
00155 void Bernstein::getReferenceDOFs(
00156 const CellType& maximalCellType,
00157 const CellType& cellType,
00158 Array<Array<Array<int> > >& dofs) const
00159 {
00160 const int N=(order()+1)*(order()+2)/2;
00161 typedef Array<int> Aint;
00162 switch(cellType)
00163 {
00164 case PointCell:
00165 dofs.resize(1);
00166 dofs[0] = tuple<Aint>(tuple(0));
00167 return;
00168 case LineCell:
00169 dofs.resize(2);
00170 dofs[0] = tuple<Aint>(tuple(0), tuple(order()));
00171 dofs[1] = tuple<Aint>(makeRange(1, order()-1));
00172 return;
00173 case TriangleCell:
00174 {
00175 dofs.resize(3);
00176 dofs[0] = tuple<Aint>(tuple(0),tuple(N-order()-1),tuple(N-1));
00177 if (order()>1)
00178 {
00179
00180 Aint dof0(order()-1);
00181 Aint dof1;
00182 Aint dof2(order()-1);
00183
00184
00185 int inc = 2;
00186 dof0[0] = 1;
00187 for (int i=1;i<order()-1;i++)
00188 {
00189 dof0[i] = dof0[i-1]+inc;
00190 inc++;
00191 }
00192
00193
00194 dof1 = makeRange(N-order(),N-2);
00195
00196
00197 inc = 3;
00198 dof2[order()-2] = 2;
00199 for (int i=order()-3;i>=0;i--)
00200 {
00201 dof2[i] = dof2[i+1]+inc;
00202 inc++;
00203 }
00204
00205 dofs[1] = tuple<Aint>(dof1,dof2,dof0);
00206 }
00207 else
00208 {
00209 dofs[1] = tuple(Array<int>());
00210 }
00211 if (order()>2)
00212 {
00213 Array<int> internaldofs;
00214 int bfcur = 0;
00215
00216 for (int alpha1=order();alpha1>=0;alpha1--)
00217 {
00218 for (int alpha2=order()-alpha1;alpha2>=0;alpha2--)
00219 {
00220 int alpha3 = order()-alpha1-alpha2;
00221 if (alpha1*alpha2*alpha3>0) {
00222 internaldofs.append(bfcur);
00223 }
00224 bfcur++;
00225 }
00226 }
00227 dofs[2] = tuple(internaldofs);
00228 }
00229 else
00230 {
00231 dofs[2] = tuple(Array<int>());
00232 }
00233 return;
00234 }
00235 case TetCell:
00236 {
00237 }
00238 default:
00239 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, "Cell type "
00240 << cellType << " not implemented in Bernstein basis");
00241 }
00242 }
00243
00244
00245
00246 Array<int> Bernstein::makeRange(int low, int high)
00247 {
00248 if (high < low) return Array<int>();
00249
00250 Array<int> rtn(high-low+1);
00251 for (int i=0; i<rtn.length(); i++) rtn[i] = low+i;
00252 return rtn;
00253 }
00254
00255 void Bernstein::refEval(
00256 const CellType& cellType,
00257 const Array<Point>& pts,
00258 const SpatialDerivSpecifier& sds,
00259 Array<Array<Array<double> > >& result,
00260 int verbosity) const
00261 {
00262 TEUCHOS_TEST_FOR_EXCEPTION(!(sds.isPartial() || sds.isIdentity()),
00263 std::runtime_error,
00264 "cannot evaluate spatial derivative " << sds << " on Bernstein basis");
00265 const MultiIndex& deriv = sds.mi();
00266 typedef Array<double> Adouble;
00267 result.resize(1);
00268 result[0].resize(pts.length());
00269
00270 switch(cellType)
00271 {
00272 case PointCell:
00273 result[0] = tuple<Adouble>(tuple(1.0));
00274 return;
00275 case LineCell:
00276 for (int i=0; i<pts.length(); i++)
00277 {
00278 evalOnLine(pts[i], deriv, result[0][i]);
00279 }
00280 return;
00281 case TriangleCell:
00282 for (int i=0; i<pts.length(); i++)
00283 {
00284 evalOnTriangle(pts[i], deriv, result[0][i]);
00285 }
00286 return;
00287 case TetCell:
00288 for (int i=0; i<pts.length(); i++)
00289 {
00290 evalOnTet(pts[i], deriv, result[0][i]);
00291 }
00292 return;
00293 default:
00294 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00295 "Bernstein::refEval() unimplemented for cell type "
00296 << cellType);
00297
00298 }
00299 }
00300
00301
00302
00303 void Bernstein::evalOnLine(const Point& pt,
00304 const MultiIndex& deriv,
00305 Array<double>& result) const
00306 {
00307 ADReal x = ADReal(pt[0], 0, 1);
00308 ADReal one(1.0, 1);
00309
00310 result.resize(order()+1);
00311 Array<ADReal> tmp(result.length());
00312 Array<double> x0(order()+1);
00313
00314 if (order_ == 0)
00315 {
00316 tmp[0] = one;
00317 }
00318 else
00319 {
00320 double binom_cur = 1.0;
00321 for (int i=0; i<=order_; i++)
00322 {
00323 tmp[i] = one;
00324
00325 for (int j=0;j<order_-i;j++)
00326 {
00327 tmp[i] *= (1-x);
00328 }
00329 for (int j=0;j<i;j++)
00330 {
00331 tmp[i] *= x;
00332 }
00333 tmp[i] *= binom_cur;
00334 binom_cur *= double(order()-i) / double(i+1);
00335 }
00336 }
00337
00338 for (int i=0; i<tmp.length(); i++)
00339 {
00340 if (deriv.order()==0) result[i] = tmp[i].value();
00341 else result[i] = tmp[i].gradient()[0];
00342 }
00343 }
00344
00345 void Bernstein::evalOnTriangle(const Point& pt,
00346 const MultiIndex& deriv,
00347 Array<double>& result) const
00348
00349 {
00350 ADReal x = ADReal(pt[0], 0, 2);
00351 ADReal y = ADReal(pt[1], 1, 2);
00352 ADReal one(1.0, 2);
00353
00354 Array<ADReal> tmp;
00355
00356 SUNDANCE_OUT(this->verb() > 3, "x=" << x.value() << " y="
00357 << y.value());
00358
00359 if(order_==0) {
00360 result.resize(1);
00361 tmp.resize(1);
00362 tmp[0] = one;
00363 }
00364 else {
00365 int N = (order()+1)*(order()+2)/2;
00366 result.resize(N);
00367 tmp.resize(N);
00368
00369 ADReal b1 = 1.0 - x - y;
00370 ADReal b2 = x;
00371 ADReal b3 = y;
00372
00373
00374 int bfcur = 0;
00375
00376 for (int alpha1=order();alpha1>=0;alpha1--)
00377 {
00378 for (int alpha2 = order()-alpha1;alpha2>=0;alpha2--)
00379 {
00380 int alpha3 = order() - alpha1 - alpha2;
00381 tmp[bfcur] = one;
00382 for (int i=0;i<alpha1;i++)
00383 {
00384 tmp[bfcur] *= b1;
00385 }
00386 for (int i=0;i<alpha2;i++)
00387 {
00388 tmp[bfcur] *= b2;
00389 }
00390 for (int i=0;i<alpha3;i++)
00391 {
00392 tmp[bfcur] *= b3;
00393 }
00394 for (int i=2;i<=order();i++)
00395 {
00396 tmp[bfcur] *= (double) i;
00397 }
00398 for (int i=2;i<=alpha1;i++)
00399 {
00400 tmp[bfcur] /= (double) i;
00401 }
00402 for (int i=2;i<=alpha2;i++)
00403 {
00404 tmp[bfcur] /= (double) i;
00405 }
00406 for (int i=2;i<=alpha3;i++)
00407 {
00408 tmp[bfcur] /= (double) i;
00409 }
00410 bfcur++;
00411 }
00412 }
00413 }
00414
00415 for (int i=0; i<tmp.length(); i++)
00416 {
00417 if (deriv.order()==0) result[i] = tmp[i].value();
00418 else
00419 result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00420 }
00421 }
00422
00423 void Bernstein::evalOnTet(const Point& pt,
00424 const MultiIndex& deriv,
00425 Array<double>& result) const
00426 {
00427 ADReal x = ADReal(pt[0], 0, 3);
00428 ADReal y = ADReal(pt[1], 1, 3);
00429 ADReal z = ADReal(pt[2], 2, 3);
00430 ADReal one(1.0, 3);
00431
00432 Array<ADReal> tmp(result.length());
00433
00434 if(order_==0)
00435 {
00436 tmp.resize(1);
00437 result.resize(1);
00438 tmp[0] = one;
00439 }
00440 else
00441 {
00442 }
00443
00444 for (int i=0; i<tmp.length(); i++)
00445 {
00446 if (deriv.order()==0) result[i] = tmp[i].value();
00447 else
00448 result[i] = tmp[i].gradient()[deriv.firstOrderDirection()];
00449 }
00450 }
00451
00452
00453
00454