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