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 "SundanceTrivialGrouper.hpp"
00032 #include "SundanceRefIntegral.hpp"
00033 #include "SundanceQuadratureIntegral.hpp"
00034 #include "SundanceReducedIntegral.hpp"
00035 #include "SundanceMaximalQuadratureIntegral.hpp"
00036 #include "SundanceCurveQuadratureIntegral.hpp"
00037 #include "SundanceEquationSet.hpp"
00038 #include "SundanceIntegralGroup.hpp"
00039 #include "SundanceBasisFamily.hpp"
00040 #include "SundanceSparsitySuperset.hpp"
00041 #include "SundanceQuadratureFamily.hpp"
00042 #include "SundanceReducedQuadrature.hpp"
00043 #include "SundanceMap.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "PlayaTabs.hpp"
00046
00047 using namespace Sundance;
00048 using namespace Teuchos;
00049
00050
00051
00052 void TrivialGrouper::findGroups(const EquationSet& eqn,
00053 const CellType& maxCellType,
00054 int spatialDim,
00055 const CellType& cellType,
00056 int cellDim,
00057 const QuadratureFamily& quad,
00058 const RCP<SparsitySuperset>& sparsity,
00059 bool isInternalBdry,
00060 Array<RCP<IntegralGroup> >& groups,
00061 const ParametrizedCurve& globalCurve,
00062 const Mesh& mesh) const
00063 {
00064 Tabs tab(0);
00065
00066 SUNDANCE_MSG1(setupVerb(),
00067 tab << "in TrivialGrouper::findGroups(), num derivs = "
00068 << sparsity->numDerivs());
00069 SUNDANCE_MSG1(setupVerb(),
00070 tab << "cell type = " << cellType);
00071 SUNDANCE_MSG1(setupVerb(),
00072 tab << "sparsity = " << std::endl << *sparsity << std::endl);
00073
00074 const ReducedQuadrature* rq = dynamic_cast<const ReducedQuadrature*>(quad.ptr(
00075 ).get());
00076 bool useReducedQuad = (rq != 0);
00077 SUNDANCE_MSG1(setupVerb(), tab << "using reduced quadrature: "
00078 << useReducedQuad);
00079
00080
00081 int vecCount=0;
00082 int constCount=0;
00083
00084 bool isMaximal = cellType == maxCellType;
00085 bool useMaxIntegral = isMaximal;
00086
00087
00088
00089
00090 bool doGroups = true;
00091 if (!isMaximal) doGroups = false;
00092
00093
00094 typedef Sundance::Map<OrderedQuartet<int, BasisFamily, int, BasisFamily>, Array<RCP<ElementIntegral> > > twoFormMap;
00095 typedef Sundance::Map<OrderedTriple<int,int,BasisFamily>, Array<RCP<ElementIntegral> > > oneFormMap;
00096 Sundance::Map<OrderedQuartet<int, BasisFamily, int, BasisFamily>, Array<RCP<ElementIntegral> > > twoForms;
00097 Sundance::Map<OrderedQuartet<int, BasisFamily, int, BasisFamily>, Array<int> > twoFormResultIndices;
00098 Sundance::Map<OrderedTriple<int,int,BasisFamily>, Array<RCP<ElementIntegral> > > oneForms;
00099 Sundance::Map<OrderedTriple<int,int,BasisFamily>, Array<int> > oneFormResultIndices;
00100
00101 for (int i=0; i<sparsity->numDerivs(); i++)
00102 {
00103 const MultipleDeriv& d = sparsity->deriv(i);
00104 SUNDANCE_MSG3(setupVerb(),
00105 tab << "--------------------------------------------------");
00106 SUNDANCE_MSG3(setupVerb(),
00107 tab << "defining integration policy for " << d);
00108 SUNDANCE_MSG3(setupVerb(),
00109 tab << "--------------------------------------------------");
00110
00111 if (d.order()==0)
00112 {
00113 RCP<ElementIntegral> integral ;
00114 int resultIndex;
00115 if (sparsity->isConstant(i))
00116 {
00117 if (globalCurve.isCurveValid() && globalCurve.isCurveIntegral() && isMaximal )
00118 {
00119 integral = rcp(new CurveQuadratureIntegral( maxCellType, true ,
00120 quad, globalCurve , mesh , setupVerb() ) );
00121 }
00122 else
00123 {
00124 integral = rcp(new RefIntegral(spatialDim, maxCellType,
00125 cellDim, cellType, quad , isInternalBdry, globalCurve , mesh , setupVerb()));
00126 }
00127 resultIndex = constCount++;
00128 }
00129 else
00130 {
00131 if (useReducedQuad)
00132 {
00133 integral = rcp(new ReducedIntegral(spatialDim, maxCellType,
00134 cellDim, cellType, quad , isInternalBdry, globalCurve , mesh , setupVerb()));
00135 }
00136 else if (useMaxIntegral)
00137 {
00138 if (globalCurve.isCurveValid() && globalCurve.isCurveIntegral() && isMaximal )
00139 {
00140 integral = rcp(new CurveQuadratureIntegral(maxCellType, false ,
00141 quad, globalCurve , mesh , setupVerb()));
00142 }
00143 else
00144 {
00145 integral = rcp(new MaximalQuadratureIntegral(maxCellType,
00146 quad, globalCurve , mesh , setupVerb()));
00147 }
00148 }
00149 else
00150 {
00151 integral = rcp(new QuadratureIntegral(spatialDim, maxCellType,
00152 cellDim, cellType, quad, isInternalBdry, globalCurve , mesh ,
00153 setupVerb()));
00154 }
00155 resultIndex = vecCount++;
00156 }
00157 integral->setVerb(integrationVerb(), transformVerb());
00158 SUNDANCE_MSG3(setupVerb(), tab << "is zero-form");
00159 groups.append(rcp(new IntegralGroup(tuple(integral),
00160 tuple(resultIndex), setupVerb())));
00161 }
00162 else
00163 {
00164 BasisFamily testBasis;
00165 BasisFamily unkBasis;
00166 MultiIndex miTest;
00167 MultiIndex miUnk;
00168 int rawTestID = -1;
00169 int rawUnkID = -1;
00170 int rawParamID = -1;
00171 int testID = -1;
00172 int unkID = -1;
00173 int paramID = -1;
00174 int testBlock = -1;
00175 int unkBlock = -1;
00176 bool isOneForm;
00177 bool hasParam;
00178 extractWeakForm(eqn, d, testBasis, unkBasis, miTest, miUnk,
00179 rawTestID, rawUnkID,
00180 testID, unkID,
00181 testBlock, unkBlock,
00182 rawParamID, paramID,
00183 isOneForm, hasParam);
00184
00185 TEUCHOS_TEST_FOR_EXCEPT(hasParam && !isOneForm);
00186
00187
00188
00189
00190 int mvIndex = 0;
00191 if (hasParam) mvIndex = paramID;
00192
00193
00194
00195
00196
00197
00198
00199 bool transposeNeeded = false;
00200 if (!isOneForm && rawTestID!=rawUnkID
00201 && eqn.hasVarID(rawUnkID) && eqn.hasUnkID(rawTestID))
00202 {
00203 transposeNeeded = true;
00204 }
00205
00206
00207 if (isOneForm)
00208 {
00209 SUNDANCE_MSG3(setupVerb(), tab << "is one-form");
00210 }
00211 else
00212 {
00213 SUNDANCE_MSG3(setupVerb(), tab << "is two-form");
00214 }
00215
00216
00217 if (hasParam)
00218 {
00219 SUNDANCE_MSG3(setupVerb(), tab << "is a parametric derivative");
00220 }
00221 else
00222 {
00223 SUNDANCE_MSG3(setupVerb(), tab << "is not a parametric derivative");
00224 }
00225
00226 SUNDANCE_MSG3(setupVerb(),
00227 tab << "test ID: " << testID << " block=" << testBlock);
00228
00229 if (!isOneForm)
00230 {
00231 SUNDANCE_MSG3(setupVerb(), tab << "unk funcID: " << unkID << " block=" << unkBlock);
00232 }
00233
00234 if (hasParam)
00235 {
00236 SUNDANCE_MSG3(setupVerb(), tab << "paramID=" << paramID);
00237 }
00238
00239 SUNDANCE_MSG3(setupVerb(), tab << "deriv = " << d);
00240 if (sparsity->isConstant(i))
00241 {
00242 SUNDANCE_MSG3(setupVerb(), tab << "coeff is constant");
00243 }
00244 else
00245 {
00246 SUNDANCE_MSG3(setupVerb(), tab << "coeff is non-constant");
00247 }
00248
00249 RCP<ElementIntegral> integral;
00250 RCP<ElementIntegral> transposedIntegral;
00251 int resultIndex;
00252 if (sparsity->isConstant(i))
00253 {
00254 if (isOneForm)
00255 {
00256 int alpha=0;
00257 if (miTest.order()==1)
00258 {
00259 alpha = miTest.firstOrderDirection();
00260 }
00261
00262 if (globalCurve.isCurveValid() && globalCurve.isCurveIntegral() && isMaximal )
00263 {
00264 integral = rcp(new CurveQuadratureIntegral(maxCellType, true ,
00265 testBasis, alpha,
00266 miTest.order(), quad, globalCurve , mesh ,setupVerb()));
00267 }
00268 else
00269 {
00270 integral = rcp(new RefIntegral(spatialDim, maxCellType,
00271 cellDim, cellType,
00272 testBasis, alpha,
00273 miTest.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00274 }
00275 }
00276 else
00277 {
00278 int alpha=0;
00279 int beta=0;
00280 if (miTest.order()==1)
00281 {
00282 alpha = miTest.firstOrderDirection();
00283 }
00284 if (miUnk.order()==1)
00285 {
00286 beta = miUnk.firstOrderDirection();
00287 }
00288
00289 if (globalCurve.isCurveValid() && globalCurve.isCurveIntegral() && isMaximal )
00290 {
00291 integral = rcp(new CurveQuadratureIntegral(maxCellType, true ,
00292 testBasis, alpha,
00293 miTest.order(),
00294 unkBasis, beta,
00295 miUnk.order(), quad, globalCurve , mesh ,setupVerb()));
00296 }
00297 else
00298 {
00299 integral = rcp(new RefIntegral(spatialDim, maxCellType,
00300 cellDim, cellType,
00301 testBasis, alpha, miTest.order(),
00302 unkBasis, beta, miUnk.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00303 }
00304 if (transposeNeeded)
00305 {
00306 if (globalCurve.isCurveValid() && globalCurve.isCurveIntegral() && isMaximal )
00307 {
00308 transposedIntegral = rcp(new CurveQuadratureIntegral(maxCellType, true ,
00309 unkBasis, beta,
00310 miUnk.order(),
00311 testBasis, alpha,
00312 miTest.order(),
00313 quad, globalCurve , mesh ,setupVerb()));
00314 }
00315 else
00316 {
00317 transposedIntegral = rcp(new RefIntegral(spatialDim, maxCellType,
00318 cellDim, cellType,
00319 unkBasis, beta,
00320 miUnk.order(),
00321 testBasis, alpha,
00322 miTest.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00323 }
00324 }
00325 }
00326 resultIndex = constCount++;
00327 }
00328 else
00329 {
00330 if (isOneForm)
00331 {
00332 int alpha=0;
00333 if (miTest.order()==1)
00334 {
00335 alpha = miTest.firstOrderDirection();
00336 }
00337 if (useReducedQuad)
00338 {
00339 integral = rcp(new ReducedIntegral(spatialDim, maxCellType,
00340 cellDim, cellType,
00341 testBasis, alpha,
00342 miTest.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00343 }
00344 else if (useMaxIntegral)
00345 {
00346 if ( globalCurve.isCurveValid() && globalCurve.isCurveIntegral() )
00347 {
00348 integral = rcp(new CurveQuadratureIntegral(maxCellType, false ,
00349 testBasis, alpha,
00350 miTest.order(), quad, globalCurve , mesh ,setupVerb()));
00351 }
00352 else
00353 {
00354 integral = rcp(new MaximalQuadratureIntegral(maxCellType,
00355 testBasis, alpha,
00356 miTest.order(), quad, globalCurve , mesh ,setupVerb()));
00357 }
00358 }
00359 else
00360 {
00361 integral = rcp(new QuadratureIntegral(spatialDim, maxCellType,
00362 cellDim, cellType,
00363 testBasis, alpha,
00364 miTest.order(), quad, isInternalBdry, globalCurve , mesh ,setupVerb()));
00365 }
00366 }
00367 else
00368 {
00369 int alpha=0;
00370 int beta=0;
00371 if (miTest.order()==1)
00372 {
00373 alpha = miTest.firstOrderDirection();
00374 }
00375 if (miUnk.order()==1)
00376 {
00377 beta = miUnk.firstOrderDirection();
00378 }
00379 if (useReducedQuad)
00380 {
00381 integral = rcp(new ReducedIntegral(spatialDim, maxCellType,
00382 cellDim, cellType,
00383 testBasis, alpha, miTest.order(),
00384 unkBasis, beta, miUnk.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00385 if (transposeNeeded)
00386 {
00387 transposedIntegral = rcp(new ReducedIntegral(spatialDim, maxCellType,
00388 cellDim, cellType,
00389 unkBasis, beta,
00390 miUnk.order(),
00391 testBasis, alpha,
00392 miTest.order(), quad , isInternalBdry, globalCurve , mesh ,setupVerb()));
00393 }
00394 }
00395 else if (useMaxIntegral)
00396 {
00397 if ( globalCurve.isCurveValid() && globalCurve.isCurveIntegral() )
00398 {
00399 integral = rcp(new CurveQuadratureIntegral(maxCellType, false ,
00400 testBasis, alpha,
00401 miTest.order(),
00402 unkBasis, beta,
00403 miUnk.order(), quad, globalCurve , mesh ,setupVerb()));
00404 }
00405 else
00406 {
00407 integral = rcp(new MaximalQuadratureIntegral(maxCellType,
00408 testBasis, alpha,
00409 miTest.order(),
00410 unkBasis, beta,
00411 miUnk.order(), quad, globalCurve , mesh ,setupVerb()));
00412 }
00413 if (transposeNeeded)
00414 {
00415 if ( globalCurve.isCurveValid() && globalCurve.isCurveIntegral() )
00416 {
00417 transposedIntegral = rcp(new CurveQuadratureIntegral(maxCellType, false ,
00418 unkBasis, beta, miUnk.order(),
00419 testBasis, alpha, miTest.order(), quad,
00420 globalCurve , mesh ,setupVerb()));
00421 }
00422 else
00423 {
00424 transposedIntegral = rcp(new MaximalQuadratureIntegral(maxCellType,
00425 unkBasis, beta, miUnk.order(),
00426 testBasis, alpha, miTest.order(), quad,
00427 globalCurve , mesh ,setupVerb()));
00428 }
00429 }
00430 }
00431 else
00432 {
00433 integral = rcp(new QuadratureIntegral(spatialDim, maxCellType,
00434 cellDim, cellType,
00435 testBasis, alpha,
00436 miTest.order(),
00437 unkBasis, beta,
00438 miUnk.order(), quad, isInternalBdry, globalCurve , mesh ,setupVerb()));
00439 if (transposeNeeded)
00440 {
00441 transposedIntegral = rcp(new QuadratureIntegral(spatialDim, maxCellType,
00442 cellDim, cellType,
00443 unkBasis, beta, miUnk.order(),
00444 testBasis, alpha, miTest.order(), quad,
00445 isInternalBdry, globalCurve , mesh ,setupVerb()));
00446 }
00447 }
00448 }
00449 resultIndex = vecCount++;
00450 }
00451
00452
00453 integral->setVerb(integrationVerb(), transformVerb());
00454 if (transposeNeeded)
00455 {
00456 transposedIntegral->setVerb(integrationVerb(), transformVerb());
00457 }
00458
00459
00460 if (isOneForm)
00461 {
00462 if (doGroups)
00463 {
00464 OrderedTriple<int,int,BasisFamily> testKey(rawTestID, mvIndex, testBasis);
00465 if (!oneForms.containsKey(testKey))
00466 {
00467 oneForms.put(testKey, tuple(integral));
00468 oneFormResultIndices.put(testKey, tuple(resultIndex));
00469 }
00470 else
00471 {
00472 oneForms[testKey].append(integral);
00473 oneFormResultIndices[testKey].append(resultIndex);
00474 }
00475 }
00476 else
00477 {
00478 groups.append(rcp(new IntegralGroup(tuple(testID), tuple(testBlock),
00479 tuple(mvIndex),
00480 tuple(integral),
00481 tuple(resultIndex), tuple(d), setupVerb())));
00482 }
00483 }
00484 else
00485 {
00486 if (!doGroups)
00487 {
00488 groups.append(rcp(new IntegralGroup(tuple(testID), tuple(testBlock),
00489 tuple(unkID), tuple(unkBlock),
00490 tuple(integral),
00491 tuple(resultIndex), tuple(d), setupVerb())));
00492 if (transposeNeeded)
00493 {
00494 groups.append(rcp(new IntegralGroup(tuple(unkID), tuple(unkBlock),
00495 tuple(testID), tuple(testBlock),
00496 tuple(transposedIntegral),
00497 tuple(resultIndex), tuple(d), setupVerb())));
00498 }
00499 }
00500 else
00501 {
00502 Tabs tab3;
00503 OrderedQuartet<int, BasisFamily, int, BasisFamily> testUnkKey(rawTestID, testBasis, rawUnkID, unkBasis);
00504
00505
00506 SUNDANCE_MSG2(setupVerb(), tab3 << "key=" << testUnkKey);
00507 if (!twoForms.containsKey(testUnkKey))
00508 {
00509 Tabs tab4;
00510 SUNDANCE_MSG2(setupVerb(), tab4 << "key not found");
00511 twoForms.put(testUnkKey, tuple(integral));
00512 twoFormResultIndices.put(testUnkKey, tuple(resultIndex));
00513 }
00514 else
00515 {
00516 Tabs tab4;
00517 SUNDANCE_MSG2(setupVerb(), tab4 << "key found");
00518 twoForms[testUnkKey].append(integral);
00519 twoFormResultIndices[testUnkKey].append(resultIndex);
00520 }
00521 if (transposeNeeded)
00522 {
00523 OrderedQuartet<int, BasisFamily, int, BasisFamily> unkTestKey(rawUnkID, unkBasis, rawTestID, testBasis);
00524
00525 if (!twoForms.containsKey(unkTestKey))
00526 {
00527 Tabs tab4;
00528 SUNDANCE_MSG2(setupVerb(), tab4 << "key not found");
00529 twoForms.put(unkTestKey, tuple(transposedIntegral));
00530 twoFormResultIndices.put(unkTestKey, tuple(resultIndex));
00531 }
00532 else
00533 {
00534 Tabs tab4;
00535 SUNDANCE_MSG2(setupVerb(), tab4 << "key found");
00536 twoForms[unkTestKey].append(transposedIntegral);
00537 twoFormResultIndices[unkTestKey].append(resultIndex);
00538 }
00539 }
00540 }
00541 }
00542 }
00543 }
00544
00545 if (doGroups)
00546 {
00547 Tabs tab;
00548 SUNDANCE_MSG2(setupVerb(), tab << "creating integral groups");
00549 for (twoFormMap::const_iterator i=twoForms.begin(); i!=twoForms.end(); i++)
00550 {
00551 Tabs tab3;
00552 SUNDANCE_MSG2(setupVerb(), tab3 << "integral group number="
00553 << groups.size());
00554 int rawTestID = i->first.a();
00555 BasisFamily testBasis = i->first.b();
00556 int rawUnkID = i->first.c();
00557 BasisFamily unkBasis = i->first.d();
00558 int testID = eqn.reducedVarID(rawTestID);
00559 int unkID = eqn.reducedUnkID(rawUnkID);
00560 int testBlock = eqn.blockForVarID(rawTestID);
00561 int unkBlock = eqn.blockForUnkID(rawUnkID);
00562 const Array<RCP<ElementIntegral> >& integrals = i->second;
00563 const Array<int>& resultIndices
00564 = twoFormResultIndices.get(i->first);
00565 SUNDANCE_MSG2(setupVerb(), tab3 << "creating two-form integral group" << std::endl
00566 << tab3 << "testID=" << rawTestID << std::endl
00567 << tab3 << "unkID=" << rawUnkID << std::endl
00568 << tab3 << "testBlock=" << testBlock << std::endl
00569 << tab3 << "unkBlock=" << unkBlock << std::endl
00570 << tab3 << "testBasis=" << testBasis << std::endl
00571 << tab3 << "unkBasis=" << unkBasis << std::endl
00572 << tab3 << "resultIndices=" << resultIndices);
00573 Array<MultipleDeriv> grpDerivs;
00574 for (int j=0; j<resultIndices.size(); j++)
00575 {
00576 MultipleDeriv d = sparsity->deriv(resultIndices[j]);
00577 SUNDANCE_MSG2(setupVerb(), tab3 << "deriv " << j << " "
00578 << d);
00579 grpDerivs.append(d);
00580 }
00581 groups.append(rcp(new IntegralGroup(tuple(testID), tuple(testBlock),
00582 tuple(unkID), tuple(unkBlock),
00583 integrals, resultIndices, grpDerivs, setupVerb())));
00584 }
00585
00586 for (oneFormMap::const_iterator i=oneForms.begin(); i!=oneForms.end(); i++)
00587 {
00588 Tabs tab3;
00589 SUNDANCE_MSG2(setupVerb(), tab3 << "integral group number="
00590 << groups.size());
00591 int rawTestID = i->first.a();
00592 int mvIndex = i->first.b();
00593 int testID = eqn.reducedVarID(rawTestID);
00594 int testBlock = eqn.blockForVarID(rawTestID);
00595 const Array<RCP<ElementIntegral> >& integrals = i->second;
00596 const Array<int>& resultIndices
00597 = oneFormResultIndices.get(i->first);
00598 SUNDANCE_MSG2(setupVerb(), tab3 << "creating one-form integral group" << std::endl
00599 << tab3 << "testID=" << testID << std::endl
00600 << tab3 << "resultIndices=" << resultIndices);
00601 Array<MultipleDeriv> grpDerivs;
00602 for (int j=0; j<resultIndices.size(); j++)
00603 {
00604 MultipleDeriv d = sparsity->deriv(resultIndices[j]);
00605 SUNDANCE_MSG2(setupVerb(), tab3 << "deriv " << j << " "
00606 << d);
00607 grpDerivs.append(d);
00608 }
00609 groups.append(rcp(new IntegralGroup(tuple(testID), tuple(testBlock),
00610 tuple(mvIndex),
00611 integrals, resultIndices, grpDerivs, setupVerb())));
00612 }
00613 }
00614
00615
00616 }
00617