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 "SundanceElementIntegral.hpp"
00043 #include "SundanceOut.hpp"
00044 #include "PlayaTabs.hpp"
00045 #include "Teuchos_TimeMonitor.hpp"
00046
00047 using namespace Sundance;
00048 using namespace Teuchos;
00049
00050 using std::endl;
00051
00052 static Time& transCreationTimer()
00053 {
00054 static RCP<Time> rtn
00055 = TimeMonitor::getNewTimer("building integral transformation matrices");
00056 return *rtn;
00057 }
00058
00059
00060 bool& ElementIntegral::alwaysUseCofacets()
00061 {
00062 static bool rtn = true;
00063 return rtn;
00064 }
00065
00066 ElementIntegral::ElementIntegral(int spatialDim,
00067 const CellType& maxCellType,
00068 int dim,
00069 const CellType& cellType,
00070 bool isInternalBdry,
00071 const ParametrizedCurve& globalCurve,
00072 const Mesh& mesh,
00073 int verb)
00074 : setupVerb_(verb),
00075 integrationVerb_(0),
00076 transformVerb_(0),
00077 spatialDim_(spatialDim),
00078 dim_(dim),
00079 isInternalBdry_(isInternalBdry),
00080 nFacetCases_(1),
00081 testDerivOrder_(-1),
00082 nRefDerivTest_(-1),
00083 nNodesTest_(-1),
00084 unkDerivOrder_(-1),
00085 nRefDerivUnk_(-1),
00086 nNodesUnk_(-1),
00087 nNodes_(-1),
00088 order_(0),
00089 alpha_(),
00090 beta_(),
00091 cellType_(cellType),
00092 maxCellType_(maxCellType),
00093 evalCellType_(cellType),
00094 testBasis_(),
00095 unkBasis_(),
00096 globalCurve_(globalCurve),
00097 mesh_(mesh)
00098 {
00099 Tabs tab0;
00100 SUNDANCE_MSG2(setupVerb(), tab0 << "constructing 0-form ElementIntegral");
00101
00102
00103 if (alwaysUseCofacets() || (dim != spatialDim && !isInternalBdry))
00104 {
00105 evalCellType_ = maxCellType_;
00106 nFacetCases_ = numFacets(maxCellType, dim);
00107 }
00108 }
00109
00110 ElementIntegral::ElementIntegral(int spatialDim,
00111 const CellType& maxCellType,
00112 int dim,
00113 const CellType& cellType,
00114 const BasisFamily& testBasis,
00115 int alpha,
00116 int testDerivOrder,
00117 bool isInternalBdry,
00118 const ParametrizedCurve& globalCurve,
00119 const Mesh& mesh,
00120 int verb)
00121 : setupVerb_(verb),
00122 integrationVerb_(0),
00123 transformVerb_(0),
00124 spatialDim_(spatialDim),
00125 dim_(dim),
00126 isInternalBdry_(isInternalBdry),
00127 nFacetCases_(1),
00128 testDerivOrder_(testDerivOrder),
00129 nRefDerivTest_(ipow(spatialDim, testDerivOrder)),
00130 nNodesTest_(testBasis.nReferenceDOFsWithFacets(maxCellType, cellType)),
00131 unkDerivOrder_(-1),
00132 nRefDerivUnk_(-1),
00133 nNodesUnk_(-1),
00134 nNodes_(nNodesTest_),
00135 order_(1),
00136 alpha_(alpha),
00137 beta_(-1),
00138 cellType_(cellType),
00139 maxCellType_(maxCellType),
00140 evalCellType_(cellType),
00141 testBasis_(testBasis),
00142 unkBasis_(),
00143 globalCurve_(globalCurve),
00144 mesh_(mesh)
00145 {
00146 Tabs tab0(0);
00147 SUNDANCE_MSG2(setupVerb(), tab0 << "constructing 1-form ElementIntegral");
00148
00149
00150 bool okToRestrictTestToBdry = basisRestrictableToBoundary(testBasis);
00151
00152 Tabs tab1;
00153 SUNDANCE_MSG2(setupVerb(), tab1 << "dim=" << dim << " spatialDim=" << spatialDim);
00154 if (dim != spatialDim)
00155 {
00156 if (isInternalBdry)
00157 {
00158 TEUCHOS_TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
00159 }
00160 if (alwaysUseCofacets() || testDerivOrder>0)
00161 {
00162 Tabs tab2;
00163 evalCellType_ = maxCellType_;
00164 nFacetCases_ = numFacets(maxCellType, dim);
00165 nNodesTest_ = testBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00166 SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesTest=" << nNodesTest_);
00167 nNodes_ = nNodesTest_;
00168 TEUCHOS_TEST_FOR_EXCEPT(nNodes_ == 0);
00169 }
00170 else
00171 {
00172 TEUCHOS_TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
00173 }
00174 }
00175
00176 SUNDANCE_MSG2(setupVerb(), tab1 << "nNodes=" << nNodes_);
00177 }
00178
00179
00180
00181 ElementIntegral::ElementIntegral(int spatialDim,
00182 const CellType& maxCellType,
00183 int dim,
00184 const CellType& cellType,
00185 const BasisFamily& testBasis,
00186 int alpha,
00187 int testDerivOrder,
00188 const BasisFamily& unkBasis,
00189 int beta,
00190 int unkDerivOrder,
00191 bool isInternalBdry,
00192 const ParametrizedCurve& globalCurve,
00193 const Mesh& mesh,
00194 int verb)
00195 : setupVerb_(verb),
00196 integrationVerb_(0),
00197 transformVerb_(0),
00198 spatialDim_(spatialDim),
00199 dim_(dim),
00200 isInternalBdry_(isInternalBdry),
00201 nFacetCases_(1),
00202 testDerivOrder_(testDerivOrder),
00203 nRefDerivTest_(ipow(spatialDim, testDerivOrder)),
00204 nNodesTest_(testBasis.nReferenceDOFsWithFacets(maxCellType, cellType)),
00205 unkDerivOrder_(unkDerivOrder),
00206 nRefDerivUnk_(ipow(spatialDim, unkDerivOrder)),
00207 nNodesUnk_(unkBasis.nReferenceDOFsWithFacets(maxCellType, cellType)),
00208 nNodes_(nNodesTest_*nNodesUnk_),
00209 order_(2),
00210 alpha_(alpha),
00211 beta_(beta),
00212 cellType_(cellType),
00213 maxCellType_(maxCellType),
00214 evalCellType_(cellType),
00215 testBasis_(testBasis),
00216 unkBasis_(unkBasis),
00217 globalCurve_(globalCurve),
00218 mesh_(mesh)
00219 {
00220 Tabs tab0(0);
00221 SUNDANCE_MSG2(setupVerb(), tab0
00222 << "***** constructing 2-form ElementIntegral");
00223
00224
00225 bool okToRestrictTestToBdry = basisRestrictableToBoundary(testBasis);
00226 bool okToRestrictUnkToBdry = basisRestrictableToBoundary(unkBasis);
00227
00228
00229 Tabs tab1;
00230 SUNDANCE_MSG2(setupVerb(), tab1 << "dim=" << dim << " spatialDim=" << spatialDim);
00231 if (dim != spatialDim)
00232 {
00233 if (isInternalBdry)
00234 {
00235 TEUCHOS_TEST_FOR_EXCEPT(!(okToRestrictTestToBdry && okToRestrictUnkToBdry));
00236 }
00237 if (alwaysUseCofacets() || testDerivOrder>0 || unkDerivOrder>0)
00238 {
00239 Tabs tab2;
00240 evalCellType_ = maxCellType_;
00241 nFacetCases_ = numFacets(maxCellType, dim);
00242 nNodesTest_ = testBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00243 SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesTest=" << nNodesTest_);
00244 nNodesUnk_ = unkBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
00245 SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesUnk=" << nNodesUnk_);
00246 nNodes_ = nNodesTest_ * nNodesUnk_;
00247 TEUCHOS_TEST_FOR_EXCEPT(nNodes_ == 0);
00248 }
00249 else
00250 {
00251 TEUCHOS_TEST_FOR_EXCEPT(okToRestrictTestToBdry != okToRestrictUnkToBdry);
00252 }
00253 }
00254
00255 SUNDANCE_MSG2(setupVerb(), tab1 << "nNodes=" << nNodes_);
00256 }
00257
00258
00259 void ElementIntegral::setVerb(
00260 int integrationVerb,
00261 int transformVerb)
00262 {
00263 integrationVerb_ = integrationVerb;
00264 transformVerb_ = transformVerb;
00265 }
00266
00267 void ElementIntegral::describe(std::ostream& os) const
00268 {
00269 Tabs tab(0);
00270 bool hasTest = testDerivOrder() >= 0;
00271 bool hasUnk = unkDerivOrder() >= 0;
00272
00273 if (hasTest)
00274 {
00275 os << tab << "Test functions:" << std::endl;
00276 Tabs tab1;
00277 os << tab1 << "test basis = " << testBasis() << std::endl;
00278 os << tab1 << "test differentiation order = " << testDerivOrder() << std::endl;
00279 os << tab1 << "alpha = " << alpha() << std::endl;
00280 os << tab1 << "num test gradient components=" << nRefDerivTest() << std::endl;
00281 }
00282 if (hasUnk)
00283 {
00284 os << tab << "Unknown functions:" << std::endl;
00285 Tabs tab1;
00286 os << tab1 << "unk basis = " << unkBasis() << std::endl;
00287 os << tab1 << "unk differentiation order = " << unkDerivOrder() << std::endl;
00288 os << tab1 << "beta = " << beta() << std::endl;
00289 os << tab1 << "num unk gradient components=" << nRefDerivUnk() << std::endl;
00290 }
00291 os << tab << "Geometry:" << std::endl;
00292 Tabs tab1;
00293 os << tab1 << "cell type on which integral is defined: " << cellType()
00294 << std::endl;
00295 os << tab1 << "maximal cell type: " << maxCellType() << std::endl;
00296 os << tab1 << "cell type on which quad pts defined: " << evalCellType()
00297 << std::endl;
00298 os << tab << "Number of evaluation cases: " << nFacetCases() << std::endl;
00299 }
00300
00301
00302 void ElementIntegral::assertBilinearForm() const
00303 {
00304 TEUCHOS_TEST_FOR_EXCEPTION(testDerivOrder() < 0 || testDerivOrder() > 1,
00305 std::logic_error,
00306 "Test function derivative order=" << testDerivOrder()
00307 << " must be 0 or 1");
00308
00309 TEUCHOS_TEST_FOR_EXCEPTION(unkDerivOrder() < 0 || unkDerivOrder() > 1,
00310 std::logic_error,
00311 "Unknown function derivative order=" << unkDerivOrder()
00312 << " must be 0 or 1");
00313 }
00314
00315 void ElementIntegral::assertLinearForm() const
00316 {
00317 TEUCHOS_TEST_FOR_EXCEPTION(testDerivOrder() < 0 || testDerivOrder() > 1,
00318 std::logic_error,
00319 "Test function derivative order=" << testDerivOrder()
00320 << " must be 0 or 1");
00321 }
00322
00323
00324 void ElementIntegral::getQuad(const QuadratureFamily& quad,
00325 int evalCase, Array<Point>& quadPts, Array<double>& quadWeights) const
00326 {
00327 Tabs tab(0);
00328
00329 SUNDANCE_MSG2(setupVerb(), tab << "getting quad points for rule "
00330 << quad);
00331
00332 if (nFacetCases()==1)
00333 {
00334 quad.getPoints(cellType(), quadPts, quadWeights);
00335 }
00336 else
00337 {
00338 int dim = dimension(cellType());
00339 quad.getFacetPoints(maxCellType(), dim, evalCase,
00340 quadPts, quadWeights);
00341 }
00342
00343 if (setupVerb() >= 4)
00344 {
00345 Tabs tab1;
00346 SUNDANCE_MSG4(setupVerb(),
00347 tab1 << "quadrature points on ref cell are:");
00348 printQuad(Out::os(), quadPts, quadWeights);
00349 }
00350 }
00351
00352
00353
00354 Array<double>& ElementIntegral::G(int alpha)
00355 {
00356 static Array<Array<double> > rtn(3);
00357
00358 return rtn[alpha];
00359 }
00360
00361 Array<double>& ElementIntegral::G(int alpha, int beta)
00362 {
00363 static Array<Array<double> > rtn(9);
00364
00365 return rtn[3*alpha + beta];
00366 }
00367
00368 int& ElementIntegral::transformationMatrixIsValid(int alpha, int beta)
00369 {
00370 static Array<int> rtn(9, false);
00371 return rtn[3*alpha + beta];
00372 }
00373
00374 int& ElementIntegral::transformationMatrixIsValid(int alpha)
00375 {
00376 static Array<int> rtn(3, false);
00377 return rtn[alpha];
00378 }
00379
00380 void ElementIntegral::invalidateTransformationMatrices()
00381 {
00382 for (int i=0; i<3; i++)
00383 {
00384 transformationMatrixIsValid(i) = false;
00385 for (int j=0; j<3; j++)
00386 {
00387 transformationMatrixIsValid(i, j) = false;
00388 }
00389 }
00390 }
00391
00392
00393
00394
00395 int ElementIntegral::ipow(int base, int power)
00396 {
00397 int rtn = 1;
00398 for (int i=0; i<power; i++) rtn *= base;
00399 return rtn;
00400 }
00401
00402 void ElementIntegral
00403 ::createTwoFormTransformationMatrix(const CellJacobianBatch& JTrans,
00404 const CellJacobianBatch& JVol) const
00405 {
00406 TimeMonitor timer(transCreationTimer());
00407 Tabs tab;
00408
00409 int flops = 0;
00410
00411 int maxDim = JTrans.cellDim();
00412
00413
00414 if (testDerivOrder() == 1 && unkDerivOrder() == 1)
00415 {
00416 Tabs tab2;
00417 if (transformationMatrixIsValid(alpha(), beta())) return;
00418 transformationMatrixIsValid(alpha(), beta()) = true;
00419
00420 G(alpha(), beta()).resize(JTrans.numCells() * JTrans.cellDim() * JTrans.cellDim());
00421
00422 double* GPtr = &(G(alpha(),beta())[0]);
00423 int k = 0;
00424
00425 for (int c=0; c<JTrans.numCells(); c++)
00426 {
00427 static Array<double> invJ;
00428 JTrans.getInvJ(c, invJ);
00429 double detJ = fabs(JVol.detJ()[c]);
00430 for (int gamma=0; gamma<maxDim; gamma++)
00431 {
00432 for (int delta=0; delta<maxDim; delta++, k++)
00433 {
00434 GPtr[k] = detJ*invJ[alpha() + gamma*maxDim]
00435 * invJ[beta() + maxDim*delta];
00436 }
00437 }
00438 }
00439 flops = 2 * JTrans.numCells() * maxDim * maxDim + JTrans.numCells();
00440 }
00441
00442 else if (testDerivOrder() == 1 && unkDerivOrder() == 0)
00443 {
00444 if (transformationMatrixIsValid(alpha())) return;
00445 transformationMatrixIsValid(alpha()) = true;
00446
00447 G(alpha()).resize(JTrans.numCells() * JTrans.cellDim());
00448
00449 int k = 0;
00450 double* GPtr = &(G(alpha())[0]);
00451
00452 for (int c=0; c<JTrans.numCells(); c++)
00453 {
00454 static Array<double> invJ;
00455 JTrans.getInvJ(c, invJ);
00456 double detJ = fabs(JVol.detJ()[c]);
00457 for (int gamma=0; gamma<maxDim; gamma++,k++)
00458 {
00459 GPtr[k] = detJ*invJ[alpha() + maxDim * gamma];
00460 }
00461 }
00462 flops = JTrans.numCells() * maxDim + JTrans.numCells();
00463 }
00464
00465 else
00466 {
00467 if (transformationMatrixIsValid(beta())) return;
00468 transformationMatrixIsValid(beta()) = true;
00469
00470 G(beta()).resize(JTrans.numCells() * JTrans.cellDim());
00471
00472 int k = 0;
00473 double* GPtr = &(G(beta())[0]);
00474
00475 for (int c=0; c<JTrans.numCells(); c++)
00476 {
00477 static Array<double> invJ;
00478 JTrans.getInvJ(c, invJ);
00479 double detJ = fabs(JVol.detJ()[c]);
00480 for (int gamma=0; gamma<maxDim; gamma++,k++)
00481 {
00482 GPtr[k] = detJ*invJ[beta() + maxDim * gamma];
00483 }
00484 }
00485 flops = JTrans.numCells() * maxDim + JTrans.numCells();
00486 }
00487
00488 addFlops(flops);
00489 }
00490
00491
00492 void ElementIntegral
00493 ::createOneFormTransformationMatrix(const CellJacobianBatch& JTrans,
00494 const CellJacobianBatch& JVol) const
00495 {
00496 TimeMonitor timer(transCreationTimer());
00497 Tabs tab;
00498 SUNDANCE_MSG2(transformVerb(),
00499 tab << "ElementIntegral creating linear form trans matrices");
00500
00501 int maxDim = JTrans.cellDim();
00502
00503 if (transformationMatrixIsValid(alpha())) return;
00504 transformationMatrixIsValid(alpha()) = true;
00505
00506 int flops = JTrans.numCells() * maxDim + JTrans.numCells();
00507
00508 G(alpha()).resize(JTrans.numCells() * JTrans.cellDim());
00509
00510 int k = 0;
00511 double* GPtr = &(G(alpha())[0]);
00512
00513 for (int c=0; c<JTrans.numCells(); c++)
00514 {
00515 Array<double> invJ;
00516 JTrans.getInvJ(c, invJ);
00517 double detJ = fabs(JVol.detJ()[c]);
00518 for (int gamma=0; gamma<maxDim; gamma++, k++)
00519 {
00520 GPtr[k] = detJ*invJ[alpha() + maxDim * gamma];
00521 }
00522 }
00523
00524 addFlops(flops);
00525 }
00526