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 "SundanceQuadratureIntegral.hpp"
00032 #include "SundanceGaussianQuadrature.hpp"
00033 #include "SundanceSpatialDerivSpecifier.hpp"
00034 #include "SundanceOut.hpp"
00035 #include "PlayaTabs.hpp"
00036 #include "Teuchos_TimeMonitor.hpp"
00037
00038 using namespace Sundance;
00039 using namespace Teuchos;
00040
00041 using std::endl;
00042 using std::setw;
00043 using std::setprecision;
00044
00045 extern "C"
00046 {
00047 int dgemm_(const char* transA, const char* transB,
00048 const int* M, const int *N, const int* K,
00049 const double* alpha,
00050 const double* A, const int* ldA,
00051 const double* B, const int* ldB,
00052 const double* beta,
00053 double* C, const int* ldC);
00054 }
00055
00056 static Time& quadrature0Timer()
00057 {
00058 static RCP<Time> rtn
00059 = TimeMonitor::getNewTimer("0-form quadrature");
00060 return *rtn;
00061 }
00062
00063 static Time& quadrature1Timer()
00064 {
00065 static RCP<Time> rtn
00066 = TimeMonitor::getNewTimer("1-form quadrature");
00067 return *rtn;
00068 }
00069
00070 static Time& quadrature2Timer()
00071 {
00072 static RCP<Time> rtn
00073 = TimeMonitor::getNewTimer("2-form quadrature");
00074 return *rtn;
00075 }
00076
00077
00078 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00079 const CellType& maxCellType,
00080 int dim,
00081 const CellType& cellType,
00082 const QuadratureFamily& quad,
00083 bool isInternalBdry,
00084 const ParametrizedCurve& globalCurve,
00085 const Mesh& mesh,
00086 int verb)
00087 : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType, quad,
00088 isInternalBdry, globalCurve, mesh, verb),
00089 W_(),
00090 useSumFirstMethod_(true)
00091 {
00092 Tabs tab0(0);
00093
00094 SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 0-form");
00095 if (setupVerb()) describe(Out::os());
00096
00097 SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);
00098
00099
00100 W_.resize(nFacetCases());
00101 quadPts_.resize(nFacetCases());
00102 quadWeights_.resize(nFacetCases());
00103 quad_ = quad;
00104
00105 for (int fc=0; fc<nFacetCases(); fc++)
00106 {
00107 Tabs tab2;
00108 SUNDANCE_MSG1(setupVerb(), tab2 << "facet case=" << fc
00109 << " of " << nFacetCases());
00110 Tabs tab3;
00111
00112 Array<double> quadWeights;
00113 Array<Point> quadPts;
00114 getQuad(quad, fc, quadPts, quadWeights);
00115 nQuad_ = quadPts.size();
00116 quadPts_[fc] = quadPts;
00117 quadWeights_[fc] = quadWeights;
00118
00119 W_[fc].resize(nQuad());
00120
00121 for (int q=0; q<nQuad(); q++)
00122 {
00123 W_[fc][q] = quadWeights[q];
00124 }
00125 }
00126 }
00127
00128
00129 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00130 const CellType& maxCellType,
00131 int dim,
00132 const CellType& cellType,
00133 const BasisFamily& testBasis,
00134 int alpha,
00135 int testDerivOrder,
00136 const QuadratureFamily& quad,
00137 bool isInternalBdry,
00138 const ParametrizedCurve& globalCurve,
00139 const Mesh& mesh,
00140 int verb)
00141 : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType,
00142 testBasis, alpha, testDerivOrder, quad , isInternalBdry, globalCurve , mesh, verb),
00143 W_(),
00144 useSumFirstMethod_(true)
00145 {
00146 Tabs tab0;
00147
00148 SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 1-form");
00149 if (setupVerb()) describe(Out::os());
00150 assertLinearForm();
00151
00152
00153 SUNDANCE_MSG1(setupVerb(), tab0 << "quadrature family=" << quad);
00154
00155 quad_ = quad;
00156 W_.resize(nFacetCases());
00157
00158 quadPts_.resize(nFacetCases());
00159 quadWeights_.resize(nFacetCases());
00160 W_ACI_F1_.resize(nFacetCases());
00161
00162 for (int fc=0; fc<nFacetCases(); fc++)
00163 {
00164 Tabs tab2;
00165
00166 SUNDANCE_MSG1(setupVerb(), tab2 << "facet case=" << fc
00167 << " of " << nFacetCases());
00168
00169
00170 Array<double> quadWeights;
00171 Array<Point> quadPts;
00172 getQuad(quad, fc, quadPts, quadWeights);
00173 nQuad_ = quadPts.size();
00174 quadPts_[fc] = quadPts;
00175 quadWeights_[fc] = quadWeights;
00176
00177 W_[fc].resize(nQuad() * nRefDerivTest() * nNodesTest());
00178
00179 SUNDANCE_MSG1(setupVerb(), tab2 << "num nodes for test function " << nNodesTest());
00180
00181 Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00182
00183 for (int r=0; r<nRefDerivTest(); r++)
00184 {
00185 Tabs tab3;
00186 SUNDANCE_MSG1(setupVerb(), tab3
00187 << "evaluating basis functions for ref deriv direction " << r);
00188 MultiIndex mi;
00189 testBasisVals[r].resize(testBasis.dim());
00190 if (testDerivOrder==1) mi[r] = 1;
00191 SpatialDerivSpecifier deriv(mi);
00192 testBasis.refEval(evalCellType(), quadPts, deriv,
00193 testBasisVals[r], setupVerb());
00194 }
00195
00196
00197
00198 int vecComp = 0;
00199 W_ACI_F1_[fc].resize(nQuad());
00200 for (int q=0; q<nQuad(); q++)
00201 {
00202 W_ACI_F1_[fc][q].resize(nRefDerivTest());
00203 for (int t=0; t<nRefDerivTest(); t++)
00204 {
00205 W_ACI_F1_[fc][q][t].resize(nNodesTest());
00206 for (int nt=0; nt<nNodesTest(); nt++)
00207 {
00208 wValue(fc, q, t, nt)
00209 = chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt]) ;
00210 W_ACI_F1_[fc][q][t][nt] = chop(testBasisVals[t][vecComp][q][nt]);
00211 }
00212 }
00213 }
00214
00215 addFlops(2*nQuad()*nRefDerivTest()*nNodesTest());
00216 }
00217 }
00218
00219
00220
00221
00222 QuadratureIntegral::QuadratureIntegral(int spatialDim,
00223 const CellType& maxCellType,
00224 int dim,
00225 const CellType& cellType,
00226 const BasisFamily& testBasis,
00227 int alpha,
00228 int testDerivOrder,
00229 const BasisFamily& unkBasis,
00230 int beta,
00231 int unkDerivOrder,
00232 const QuadratureFamily& quad,
00233 bool isInternalBdry,
00234 const ParametrizedCurve& globalCurve,
00235 const Mesh& mesh,
00236 int verb)
00237 : QuadratureIntegralBase(spatialDim, maxCellType, dim, cellType,
00238 testBasis, alpha, testDerivOrder,
00239 unkBasis, beta, unkDerivOrder, quad , isInternalBdry, globalCurve , mesh , verb),
00240 W_(),
00241 useSumFirstMethod_(true)
00242 {
00243 Tabs tab0;
00244
00245 SUNDANCE_MSG1(setupVerb(), tab0 << "QuadratureIntegral ctor for 2-form");
00246 if (setupVerb()) describe(Out::os());
00247 assertBilinearForm();
00248 quad_ = quad;
00249
00250 W_.resize(nFacetCases());
00251 W_ACI_F2_.resize(nFacetCases());
00252
00253 quadPts_.resize(nFacetCases());
00254 quadWeights_.resize(nFacetCases());
00255
00256 for (int fc=0; fc<nFacetCases(); fc++)
00257 {
00258
00259 Array<double> quadWeights;
00260 Array<Point> quadPts;
00261 getQuad(quad, fc, quadPts, quadWeights);
00262
00263 quadPts_[fc] = quadPts;
00264 quadWeights_[fc] = quadWeights;
00265 nQuad_ = quadPts.size();
00266
00267 W_[fc].resize(nQuad() * nRefDerivTest() * nNodesTest()
00268 * nRefDerivUnk() * nNodesUnk());
00269
00270
00271
00272 Array<Array<Array<Array<double> > > > testBasisVals(nRefDerivTest());
00273 Array<Array<Array<Array<double> > > > unkBasisVals(nRefDerivUnk());
00274
00275
00276 for (int r=0; r<nRefDerivTest(); r++)
00277 {
00278 testBasisVals[r].resize(testBasis.dim());
00279 MultiIndex mi;
00280 if (testDerivOrder==1) mi[r] = 1;
00281 SpatialDerivSpecifier deriv(mi);
00282 testBasis.refEval(evalCellType(), quadPts, deriv,
00283 testBasisVals[r], setupVerb());
00284 }
00285
00286 for (int r=0; r<nRefDerivUnk(); r++)
00287 {
00288 unkBasisVals[r].resize(unkBasis.dim());
00289 MultiIndex mi;
00290 if (unkDerivOrder==1) mi[r] = 1;
00291 SpatialDerivSpecifier deriv(mi);
00292 unkBasis.refEval(evalCellType(),
00293 quadPts, deriv, unkBasisVals[r], setupVerb());
00294 }
00295
00296
00297 int vecComp = 0;
00298
00299 W_ACI_F2_[fc].resize(nQuad());
00300 for (int q=0; q<nQuad(); q++)
00301 {
00302 W_ACI_F2_[fc][q].resize(nRefDerivTest());
00303 for (int t=0; t<nRefDerivTest(); t++)
00304 {
00305 W_ACI_F2_[fc][q][t].resize(nNodesTest());
00306 for (int nt=0; nt<nNodesTest(); nt++)
00307 {
00308 W_ACI_F2_[fc][q][t][nt].resize(nRefDerivUnk());
00309 for (int u=0; u<nRefDerivUnk(); u++)
00310 {
00311 W_ACI_F2_[fc][q][t][nt][u].resize(nNodesUnk());
00312 for (int nu=0; nu<nNodesUnk(); nu++)
00313 {
00314 wValue(fc, q, t, nt, u, nu)
00315 = chop(quadWeights[q] * testBasisVals[t][vecComp][q][nt]
00316 * unkBasisVals[u][vecComp][q][nu]);
00317 W_ACI_F2_[fc][q][t][nt][u][nu] =
00318 chop(testBasisVals[t][vecComp][q][nt] * unkBasisVals[u][vecComp][q][nu]);
00319 }
00320 }
00321 }
00322 }
00323 }
00324
00325 addFlops(3*nQuad()*nRefDerivTest()*nNodesTest()*nRefDerivUnk()*nNodesUnk()
00326 + W_[fc].size());
00327 for (int i=0; i<W_[fc].size(); i++) W_[fc][i] = chop(W_[fc][i]);
00328
00329 }
00330
00331 }
00332
00333
00334 void QuadratureIntegral::transformZeroForm(const CellJacobianBatch& JTrans,
00335 const CellJacobianBatch& JVol,
00336 const Array<int>& isLocalFlag,
00337 const Array<int>& facetIndex,
00338 const RCP<Array<int> >& cellLIDs,
00339 const double* const coeff,
00340 RCP<Array<double> >& A) const
00341 {
00342 TimeMonitor timer(quadrature0Timer());
00343 Tabs tabs;
00344 TEUCHOS_TEST_FOR_EXCEPTION(order() != 0, std::logic_error,
00345 "QuadratureIntegral::transformZeroForm() called "
00346 "for form of order " << order());
00347
00348 TEUCHOS_TEST_FOR_EXCEPTION( (int) isLocalFlag.size() != 0
00349 && (int) isLocalFlag.size() != JVol.numCells(),
00350 std::runtime_error,
00351 "mismatch between isLocalFlag.size()=" << isLocalFlag.size()
00352 << " and JVol.numCells()=" << JVol.numCells());
00353
00354 bool checkLocalFlag = (int) isLocalFlag.size() != 0;
00355
00356 const Array<int>* cellLID = cellLIDs.get();
00357
00358 SUNDANCE_MSG1(integrationVerb(), tabs << "doing zero form by quadrature");
00359 double& a = (*A)[0];
00360 SUNDANCE_MSG5(integrationVerb(), tabs << "input A=");
00361 if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00362 double* coeffPtr = (double*) coeff;
00363
00364 int flops = 0;
00365 if (nFacetCases()==1)
00366 {
00367 if (globalCurve().isCurveValid())
00368 {
00369
00370 Array<double> quadWeightsTmp = quadWeights_[0];
00371 Array<Point> quadPointsTmp = quadPts_[0];
00372 bool isCutByCurve;
00373
00374 const Array<double>& w = W_[0];
00375 for (int c=0; c<JVol.numCells(); c++)
00376 {
00377 if (checkLocalFlag && !isLocalFlag[c])
00378 {
00379 coeffPtr += nQuad();
00380 continue;
00381 }
00382 double detJ = fabs(JVol.detJ()[c]);
00383 int fc = 0;
00384
00385 quadWeightsTmp = quadWeights_[fc];
00386 quadPointsTmp = quadPts_[fc];
00387 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00388 globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00389
00390 if (isCutByCurve)
00391 {
00392 for (int q=0; q<nQuad(); q++, coeffPtr++)
00393 {
00394 a += quadWeightsTmp[q]*(*coeffPtr)*detJ;
00395 }
00396 flops += 3*nQuad();
00397 }
00398 else
00399 {
00400 for (int q=0; q<nQuad(); q++, coeffPtr++)
00401 {
00402 a += w[q]*(*coeffPtr)*detJ;
00403 }
00404 flops += 3*nQuad();
00405 }
00406
00407 }
00408 }
00409 else
00410 {
00411 const Array<double>& w = W_[0];
00412 for (int c=0; c<JVol.numCells(); c++)
00413 {
00414 if (checkLocalFlag && !isLocalFlag[c])
00415 {
00416 coeffPtr += nQuad();
00417 continue;
00418 }
00419 double detJ = fabs(JVol.detJ()[c]);
00420
00421 for (int q=0; q<nQuad(); q++, coeffPtr++)
00422 {
00423 a += w[q]*(*coeffPtr)*detJ;
00424 }
00425 flops += 3*nQuad();
00426 }
00427 }
00428 }
00429 else
00430 {
00431 if (globalCurve().isCurveValid())
00432 {
00433 Array<double> quadWeightsTmp = quadWeights_[0];
00434 Array<Point> quadPointsTmp = quadPts_[0];
00435 bool isCutByCurve;
00436
00437 for (int c=0; c<JVol.numCells(); c++)
00438 {
00439 if (checkLocalFlag && !isLocalFlag[c])
00440 {
00441 coeffPtr += nQuad();
00442 continue;
00443 }
00444 double detJ = fabs(JVol.detJ()[c]);
00445 int fc = facetIndex[c];
00446 const Array<double>& w = W_[facetIndex[c]];
00447
00448
00449 quadWeightsTmp = quadWeights_[fc];
00450 quadPointsTmp = quadPts_[fc];
00451 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c], fc ,mesh(),
00452 globalCurve(), quadPointsTmp, quadWeightsTmp, isCutByCurve);
00453
00454 if (isCutByCurve){
00455 for (int q=0; q<nQuad(); q++, coeffPtr++)
00456 a += quadWeightsTmp[q]*(*coeffPtr)*detJ;
00457 flops += 3*nQuad();
00458 }
00459 else{
00460 for (int q=0; q<nQuad(); q++, coeffPtr++)
00461 a += w[q]*(*coeffPtr)*detJ;
00462 flops += 3*nQuad();
00463 }
00464 }
00465 }
00466 else
00467 {
00468 for (int c=0; c<JVol.numCells(); c++)
00469 {
00470 Tabs tab1;
00471 SUNDANCE_MSG4(integrationVerb(), tab1 << "cell #" << c
00472 << " of " << JVol.numCells());
00473 if (checkLocalFlag && !isLocalFlag[c])
00474 {
00475 Tabs tab2;
00476 SUNDANCE_MSG4(integrationVerb(), tab2
00477 << "skipped -- is not local cell");
00478 coeffPtr += nQuad();
00479 continue;
00480 }
00481 double detJ = fabs(JVol.detJ()[c]);
00482 const Array<double>& w = W_[facetIndex[c]];
00483
00484 for (int q=0; q<nQuad(); q++, coeffPtr++)
00485 {
00486 Tabs tab3;
00487 SUNDANCE_MSG4(integrationVerb(),
00488 tab3 << "q=" << q << "\t w=" << w[q]
00489 << "\t\t coeff=" << *coeffPtr << "\t\t |J|=" << detJ);
00490 a += w[q]*(*coeffPtr)*detJ;
00491 }
00492 flops += 3*nQuad();
00493 }
00494 }
00495 }
00496 SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00497 if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00498
00499 addFlops(flops);
00500 }
00501
00502
00503 void QuadratureIntegral::transformOneForm(const CellJacobianBatch& JTrans,
00504 const CellJacobianBatch& JVol,
00505 const Array<int>& facetIndex,
00506 const RCP<Array<int> >& cellLIDs,
00507 const double* const coeff,
00508 RCP<Array<double> >& A) const
00509 {
00510 TimeMonitor timer(quadrature1Timer());
00511 Tabs tabs;
00512 TEUCHOS_TEST_FOR_EXCEPTION(order() != 1, std::logic_error,
00513 "QuadratureIntegral::transformOneForm() called for form "
00514 "of order " << order());
00515 SUNDANCE_MSG2(integrationVerb(), tabs << "doing one form by quadrature");
00516 int flops = 0;
00517
00518 const Array<int>* cellLID = cellLIDs.get();
00519
00520
00521
00522
00523 if (testDerivOrder() == 0)
00524 {
00525 double* aPtr = &((*A)[0]);
00526 SUNDANCE_MSG5(integrationVerb(), tabs << "input A = ");
00527 if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00528
00529 double* coeffPtr = (double*) coeff;
00530 int offset = 0 ;
00531
00532 if (globalCurve().isCurveValid())
00533 {
00534
00535 Array<double> quadWeightsTmp = quadWeights_[0];
00536 Array<Point> quadPointsTmp = quadPts_[0];
00537 bool isCutByCurve;
00538
00539 for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00540 {
00541 Tabs tab2;
00542 double detJ = fabs(JVol.detJ()[c]);
00543 int fc = 0;
00544 if (nFacetCases() != 1) fc = facetIndex[c];
00545 const Array<double>& w = W_[fc];
00546 SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00547
00548 quadWeightsTmp = quadWeights_[fc];
00549 quadPointsTmp = quadPts_[fc];
00550
00551 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00552 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00553 if (isCutByCurve){
00554 Array<double> wi;
00555 wi.resize(nQuad() * nNodes());
00556 for (int ii = 0 ; ii < wi.size() ; ii++ ) { wi[ii] = 0.0; }
00557 for (int n = 0 ; n < nNodes() ; n++)
00558 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00559
00560 wi[n + nNodes()*q] +=
00561 chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][0][n]);
00562
00563 for (int q=0; q<nQuad(); q++, coeffPtr++){
00564 double f = (*coeffPtr)*detJ;
00565 for (int n=0; n<nNodes(); n++){
00566 aPtr[offset+n] += f*wi[n + nNodes()*q];
00567 }
00568 }
00569 }
00570 else
00571 {
00572 for (int q=0; q<nQuad(); q++, coeffPtr++){
00573 double f = (*coeffPtr)*detJ;
00574 for (int n=0; n<nNodes(); n++){
00575 aPtr[offset+n] += f*w[n + nNodes()*q];
00576 }
00577 }
00578 }
00579 }
00580 }
00581 else
00582 {
00583 for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00584 {
00585 Tabs tab2;
00586 double detJ = fabs(JVol.detJ()[c]);
00587 int fc = 0;
00588 if (nFacetCases() != 1) fc = facetIndex[c];
00589 const Array<double>& w = W_[fc];
00590 SUNDANCE_MSG4(integrationVerb(), tab2 << "c=" << c << " detJ=" << detJ);
00591
00592 for (int q=0; q<nQuad(); q++, coeffPtr++)
00593 {
00594 Tabs tab3;
00595 double f = (*coeffPtr)*detJ;
00596 SUNDANCE_MSG4(integrationVerb(), tab3 << "q=" << q << " coeff=" <<
00597 *coeffPtr << " coeff*detJ=" << f);
00598 for (int n=0; n<nNodes(); n++)
00599 {
00600 Tabs tab4;
00601 SUNDANCE_MSG4(integrationVerb(), tab4 << "n=" << n << " w=" <<
00602 w[n + nNodes()*q]);
00603 aPtr[offset+n] += f*w[n + nNodes()*q];
00604 }
00605 }
00606 }
00607 }
00608 if (integrationVerb() >= 4)
00609 {
00610 Tabs tab2;
00611 Out::os() << tab2 << "integration results on cell:" << std::endl;
00612 Out::os() << tab2 << setw(10) << "n" << setw(12) << "I_n" << std::endl;
00613 for (int n=0; n<nNodes(); n++)
00614 {
00615 Out::os() << tab2 << setw(10) << n
00616 << setw(12) << setprecision(6) << aPtr[offset+n] << std::endl;
00617 }
00618 }
00619
00620 SUNDANCE_MSG5(integrationVerb(), tabs << "output A = ");
00621 if (integrationVerb() >= 5) writeTable(Out::os(), tabs, *A, 6);
00622 addFlops( JVol.numCells() * (1 + nQuad() * (1 + 2*nNodes())) );
00623 }
00624 else
00625 {
00626
00627
00628
00629
00630 createOneFormTransformationMatrix(JTrans, JVol);
00631
00632 SUNDANCE_MSG4(transformVerb(),
00633 Tabs() << "transformation matrix=" << G(alpha()));
00634
00635 double* GPtr = &(G(alpha())[0]);
00636
00637 if (useSumFirstMethod())
00638 {
00639 transformSummingFirst(JVol.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00640 }
00641 else
00642 {
00643 transformSummingLast(JVol.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00644 }
00645 }
00646 addFlops(flops);
00647 }
00648
00649
00650 void QuadratureIntegral::transformTwoForm(const CellJacobianBatch& JTrans,
00651 const CellJacobianBatch& JVol,
00652 const Array<int>& facetIndex,
00653 const RCP<Array<int> >& cellLIDs,
00654 const double* const coeff,
00655 RCP<Array<double> >& A) const
00656 {
00657 TimeMonitor timer(quadrature2Timer());
00658 Tabs tabs;
00659 TEUCHOS_TEST_FOR_EXCEPTION(order() != 2, std::logic_error,
00660 "QuadratureIntegral::transformTwoForm() called for form "
00661 "of order " << order());
00662 SUNDANCE_MSG2(integrationVerb(), tabs << "doing two form by quadrature");
00663
00664 const Array<int>* cellLID = cellLIDs.get();
00665
00666
00667
00668
00669 if (testDerivOrder() == 0 && unkDerivOrder() == 0)
00670 {
00671 double* aPtr = &((*A)[0]);
00672 double* coeffPtr = (double*) coeff;
00673 int offset = 0 ;
00674
00675 if (globalCurve().isCurveValid())
00676 {
00677
00678 Array<double> quadWeightsTmp = quadWeights_[0];
00679 Array<Point> quadPointsTmp = quadPts_[0];
00680 bool isCutByCurve;
00681
00682 for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00683 {
00684 double detJ = fabs(JVol.detJ()[c]);
00685 int fc = 0;
00686 if (nFacetCases() != 1) fc = facetIndex[c];
00687 const Array<double>& w = W_[fc];
00688
00689 quadWeightsTmp = quadWeights_[fc];
00690 quadPointsTmp = quadPts_[fc];
00691
00692 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00693 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00694 if (isCutByCurve){
00695 Array<double> wi;
00696 wi.resize(nQuad() * nNodesTest() *nNodesUnk() );
00697 for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00698 for (int nt = 0 ; nt < nNodesTest() ; nt++){
00699 for (int nu=0; nu<nNodesUnk(); nu++)
00700 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00701
00702 wi[nu + nNodesUnk()*(nt + nNodesTest()*q)] +=
00703 chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][0][nt][0][nu]);
00704 }
00705 for (int q=0; q<nQuad(); q++, coeffPtr++){
00706 double f = (*coeffPtr)*detJ;
00707 for (int n=0; n<nNodes(); n++){
00708 aPtr[offset+n] += f*wi[n + nNodes()*q];
00709 }
00710 }
00711 }
00712 else
00713 {
00714 for (int q=0; q<nQuad(); q++, coeffPtr++){
00715 double f = (*coeffPtr)*detJ;
00716 for (int n=0; n<nNodes(); n++){
00717 aPtr[offset+n] += f*w[n + nNodes()*q];
00718 }
00719 }
00720 }
00721 }
00722 }
00723 else
00724 {
00725
00726 for (int c=0; c<JVol.numCells(); c++, offset+=nNodes())
00727 {
00728 double detJ = fabs(JVol.detJ()[c]);
00729 int fc = 0;
00730 if (nFacetCases() != 1) fc = facetIndex[c];
00731 const Array<double>& w = W_[fc];
00732 for (int q=0; q<nQuad(); q++, coeffPtr++)
00733 {
00734 double f = (*coeffPtr)*detJ;
00735 for (int n=0; n<nNodes(); n++)
00736 {
00737 aPtr[offset+n] += f*w[n + nNodes()*q];
00738 }
00739 }
00740 }
00741 }
00742 addFlops( JVol.numCells() * (1 + nQuad() * (1 + 2*nNodes())) );
00743 }
00744 else
00745 {
00746 createTwoFormTransformationMatrix(JTrans, JVol);
00747 double* GPtr;
00748
00749 if (testDerivOrder() == 0)
00750 {
00751 GPtr = &(G(beta())[0]);
00752 SUNDANCE_MSG2(transformVerb(),
00753 Tabs() << "transformation matrix=" << G(beta()));
00754 }
00755 else if (unkDerivOrder() == 0)
00756 {
00757 GPtr = &(G(alpha())[0]);
00758 SUNDANCE_MSG2(transformVerb(),
00759 Tabs() << "transformation matrix=" << G(alpha()));
00760 }
00761 else
00762 {
00763 GPtr = &(G(alpha(), beta())[0]);
00764 SUNDANCE_MSG2(transformVerb(),
00765 Tabs() << "transformation matrix="
00766 << G(alpha(),beta()));
00767 }
00768
00769
00770 if (useSumFirstMethod())
00771 {
00772 transformSummingFirst(JTrans.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00773 }
00774 else
00775 {
00776 transformSummingLast(JTrans.numCells(), facetIndex, cellLIDs, GPtr, coeff, A);
00777 }
00778 }
00779 }
00780
00781 void QuadratureIntegral
00782 ::transformSummingFirst(int nCells,
00783 const Array<int>& facetIndex,
00784 const RCP<Array<int> >& cellLIDs,
00785 const double* const GPtr,
00786 const double* const coeff,
00787 RCP<Array<double> >& A) const
00788 {
00789 double* aPtr = &((*A)[0]);
00790 double* coeffPtr = (double*) coeff;
00791 const Array<int>* cellLID = cellLIDs.get();
00792
00793 int transSize = 0;
00794 if (order()==2)
00795 {
00796 transSize = nRefDerivTest() * nRefDerivUnk();
00797 }
00798 else
00799 {
00800 transSize = nRefDerivTest();
00801 }
00802
00803
00804 static Array<double> sumWorkspace;
00805
00806 int swSize = transSize * nNodes();
00807 sumWorkspace.resize(swSize);
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 if (globalCurve().isCurveValid())
00820 {
00821
00822 Array<double> quadWeightsTmp = quadWeights_[0];
00823 Array<Point> quadPointsTmp = quadPts_[0];
00824 bool isCutByCurve;
00825
00826 for (int c=0; c<nCells; c++)
00827 {
00828
00829 for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00830 int fc = 0;
00831 if (nFacetCases() > 1) fc = facetIndex[c];
00832
00833 const Array<double>& w = W_[fc];
00834
00835 quadWeightsTmp = quadWeights_[fc];
00836 quadPointsTmp = quadPts_[fc];
00837
00838 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00839 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00840 if (isCutByCurve){
00841 Array<double> wi;
00842 if (order()==1){
00843 wi.resize(nQuad() * nRefDerivTest() * nNodesTest());
00844 for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00845 for (int n = 0 ; n < nNodes() ; n++)
00846 for (int t=0; t<nRefDerivTest(); t++)
00847 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00848
00849 wi[n + nNodes()*(t + nRefDerivTest()*q)] +=
00850 chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][t][n]);
00851 }else{
00852 wi.resize(nQuad() * nRefDerivTest() * nNodesTest()
00853 * nRefDerivUnk() * nNodesUnk() );
00854 for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00855
00856 for (int t=0; t<nRefDerivTest(); t++)
00857 for (int nt = 0 ; nt < nNodesTest() ; nt++){
00858 for (int u=0; u<nRefDerivUnk(); u++)
00859 for (int nu=0; nu<nNodesUnk(); nu++)
00860 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00861
00862
00863 wi[nu + nNodesUnk()*(nt + nNodesTest()*(u + nRefDerivUnk()*(t + nRefDerivTest()*q)))] +=
00864 chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][t][nt][u][nu]);
00865 }
00866 }
00867 for (int q=0; q<nQuad(); q++, coeffPtr++){
00868 double f = (*coeffPtr);
00869 for (int n=0; n<swSize; n++){
00870 sumWorkspace[n] += f*wi[n + q*swSize];
00871 }
00872 }
00873 }
00874 else{
00875 for (int q=0; q<nQuad(); q++, coeffPtr++)
00876 {
00877 double f = (*coeffPtr);
00878 for (int n=0; n<swSize; n++)
00879 {
00880 sumWorkspace[n] += f*w[n + q*swSize];
00881 }
00882 }
00883 }
00884 }
00885 }
00886 else
00887 {
00888 for (int c=0; c<nCells; c++)
00889 {
00890
00891 for (int i=0; i<swSize; i++) sumWorkspace[i]=0.0;
00892 int fc = 0;
00893 if (nFacetCases() > 1) fc = facetIndex[c];
00894
00895 const Array<double>& w = W_[fc];
00896
00897 for (int q=0; q<nQuad(); q++, coeffPtr++)
00898 {
00899 double f = (*coeffPtr);
00900 for (int n=0; n<swSize; n++)
00901 {
00902 sumWorkspace[n] += f*w[n + q*swSize];
00903 }
00904 }
00905
00906
00907 const double * const gCell = &(GPtr[transSize*c]);
00908 double* aCell = aPtr + nNodes()*c;
00909 for (int i=0; i<nNodes(); i++)
00910 {
00911 for (int j=0; j<transSize; j++)
00912 {
00913 aCell[i] += sumWorkspace[nNodes()*j + i] * gCell[j];
00914 }
00915 }
00916 }
00917 }
00918 int flops = 2*(nCells * nNodes() * transSize) * (nQuad() + 1) ;
00919 addFlops(flops);
00920 }
00921
00922 void QuadratureIntegral
00923 ::transformSummingLast(int nCells,
00924 const Array<int>& facetIndex,
00925 const RCP<Array<int> >& cellLIDs,
00926 const double* const GPtr,
00927 const double* const coeff,
00928 RCP<Array<double> >& A) const
00929 {
00930 double* aPtr = &((*A)[0]);
00931 int transSize = 0;
00932 const Array<int>* cellLID = cellLIDs.get();
00933
00934 if (order()==2)
00935 {
00936 transSize = nRefDerivTest() * nRefDerivUnk();
00937 }
00938 else
00939 {
00940 transSize = nRefDerivTest();
00941 }
00942
00943
00944
00945 static Array<double> jWorkspace;
00946 jWorkspace.resize(transSize);
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957 if (globalCurve().isCurveValid()){
00958
00959 Array<double> quadWeightsTmp = quadWeights_[0];
00960 Array<Point> quadPointsTmp = quadPts_[0];
00961 bool isCutByCurve;
00962
00963 for (int c=0; c<nCells; c++)
00964 {
00965 const double* const gCell = &(GPtr[transSize*c]);
00966 double* aCell = aPtr + nNodes()*c;
00967 int fc = 0;
00968 if (nFacetCases() > 1) fc = facetIndex[c];
00969 const Array<double>& w = W_[fc];
00970
00971 quadWeightsTmp = quadWeights_[fc];
00972 quadPointsTmp = quadPts_[fc];
00973
00974 quad_.getAdaptedWeights(cellType(), dim(), (*cellLID)[c] , fc ,
00975 mesh() , globalCurve() , quadPointsTmp , quadWeightsTmp , isCutByCurve );
00976 if (isCutByCurve){
00977 Array<double> wi;
00978 if (order()==1){
00979 wi.resize(nQuad() * nRefDerivTest() * nNodesTest());
00980 for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00981 for (int n = 0 ; n < nNodes() ; n++)
00982 for (int t=0; t<nRefDerivTest(); t++)
00983 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00984
00985 wi[n + nNodes()*(t + nRefDerivTest()*q)] +=
00986 chop(quadWeightsTmp[q] * W_ACI_F1_[fc][q][t][n]);
00987 }else{
00988 wi.resize(nQuad() * nRefDerivTest() * nNodesTest()
00989 * nRefDerivUnk() * nNodesUnk() );
00990 for (int ii = 0 ; ii < wi.size() ; ii++ ) wi[ii] = 0.0;
00991
00992 for (int t=0; t<nRefDerivTest(); t++)
00993 for (int nt = 0 ; nt < nNodesTest() ; nt++){
00994 for (int u=0; u<nRefDerivUnk(); u++)
00995 for (int nu=0; nu<nNodesUnk(); nu++)
00996 for (int q=0 ; q < quadWeightsTmp.size() ; q++)
00997
00998
00999 wi[nu + nNodesUnk()*(nt + nNodesTest()*(u + nRefDerivUnk()*(t + nRefDerivTest()*q)))] +=
01000 chop(quadWeightsTmp[q] * W_ACI_F2_[fc][q][t][nt][u][nu]);
01001 }
01002 }
01003 for (int q=0; q<nQuad(); q++){
01004 double f = coeff[c*nQuad() + q];
01005 for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01006
01007 for (int n=0; n<nNodes(); n++){
01008 for (int t=0; t<transSize; t++){
01009 aCell[n] += jWorkspace[t]*wi[n + nNodes()*(t + transSize*q)];
01010 }
01011 }
01012 }
01013 }
01014 else{
01015 for (int q=0; q<nQuad(); q++){
01016 double f = coeff[c*nQuad() + q];
01017 for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01018
01019 for (int n=0; n<nNodes(); n++){
01020 for (int t=0; t<transSize; t++){
01021 aCell[n] += jWorkspace[t]*w[n + nNodes()*(t + transSize*q)];
01022 }
01023 }
01024 }
01025 }
01026 }
01027 }
01028 else
01029 {
01030 for (int c=0; c<nCells; c++)
01031 {
01032 const double* const gCell = &(GPtr[transSize*c]);
01033 double* aCell = aPtr + nNodes()*c;
01034 int fc = 0;
01035 if (nFacetCases() > 1) fc = facetIndex[c];
01036 const Array<double>& w = W_[fc];
01037 for (int q=0; q<nQuad(); q++)
01038 {
01039 double f = coeff[c*nQuad() + q];
01040 for (int t=0; t<transSize; t++) jWorkspace[t]=f*gCell[t];
01041
01042 for (int n=0; n<nNodes(); n++)
01043 {
01044 for (int t=0; t<transSize; t++)
01045 {
01046 aCell[n] += jWorkspace[t]*w[n + nNodes()*(t + transSize*q)];
01047 }
01048 }
01049 }
01050 }
01051 }
01052 int flops = nCells * nQuad() * transSize * (1 + 2*nNodes()) ;
01053 addFlops(flops);
01054 }