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 "SundanceAssembler.hpp"
00032 #include "SundanceDOFMapBuilder.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "PlayaTabs.hpp"
00035 #include "SundanceCellFilter.hpp"
00036 #include "SundanceCellSet.hpp"
00037 #include "SundanceTrivialGrouper.hpp"
00038 #include "SundanceDOFMapBase.hpp"
00039 #include "SundanceEquationSet.hpp"
00040 #include "SundanceDiscreteSpace.hpp"
00041 #include "SundanceDiscreteFunction.hpp"
00042 #include "SundanceIntegralGroup.hpp"
00043 #include "SundanceGrouperBase.hpp"
00044 #include "SundanceEvalManager.hpp"
00045 #include "SundanceStdFwkEvalMediator.hpp"
00046 #include "SundanceEvaluatableExpr.hpp"
00047 #include "PlayaLoadableVector.hpp"
00048 #include "PlayaLoadableMatrix.hpp"
00049 #include "SundanceQuadratureEvalMediator.hpp"
00050 #include "SundanceCurveEvalMediator.hpp"
00051 #include "SundanceEvaluator.hpp"
00052 #include "Teuchos_Time.hpp"
00053 #include "Teuchos_TimeMonitor.hpp"
00054 #include "Epetra_HashTable.h"
00055 #include "SundanceIntHashSet.hpp"
00056 #include "PlayaDefaultBlockVectorSpaceDecl.hpp"
00057 #include "PlayaBlockOperatorBaseDecl.hpp"
00058 #include "PlayaSimpleBlockOpDecl.hpp"
00059 #include "SundanceAssemblyKernelBase.hpp"
00060 #include "SundanceVectorAssemblyKernel.hpp"
00061 #include "SundanceMatrixVectorAssemblyKernel.hpp"
00062 #include "SundanceFunctionalAssemblyKernel.hpp"
00063 #include "SundanceFunctionalGradientAssemblyKernel.hpp"
00064 #include "SundanceAssemblyTransformationBuilder.hpp"
00065 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00066 #include "PlayaLinearOperatorImpl.hpp"
00067 #include "PlayaSimpleBlockOpImpl.hpp"
00068 #include "PlayaDefaultBlockVectorImpl.hpp"
00069 #endif
00070
00071
00072
00073 using namespace Teuchos;
00074 using namespace Playa;
00075 using std::max;
00076 using std::min;
00077
00078
00079 static Time& assemblerCtorTimer()
00080 {
00081 static RCP<Time> rtn
00082 = TimeMonitor::getNewTimer("assembler ctor");
00083 return *rtn;
00084 }
00085
00086
00087
00088
00089 static Time& graphBuildTimer()
00090 {
00091 static RCP<Time> rtn
00092 = TimeMonitor::getNewTimer("matrix graph determination");
00093 return *rtn;
00094 }
00095
00096 static Time& colSearchTimer()
00097 {
00098 static RCP<Time> rtn
00099 = TimeMonitor::getNewTimer("graph column processing");
00100 return *rtn;
00101 }
00102
00103
00104
00105 static Time& matAllocTimer()
00106 {
00107 static RCP<Time> rtn
00108 = TimeMonitor::getNewTimer("matrix allocation");
00109 return *rtn;
00110 }
00111
00112 static Time& matFinalizeTimer()
00113 {
00114 static RCP<Time> rtn
00115 = TimeMonitor::getNewTimer("matrix graph packing");
00116 return *rtn;
00117 }
00118
00119 static Time& graphFlatteningTimer()
00120 {
00121 static RCP<Time> rtn
00122 = TimeMonitor::getNewTimer("tmp graph flattening");
00123 return *rtn;
00124 }
00125
00126
00127
00128 Assembler
00129 ::Assembler(const Mesh& mesh,
00130 const RCP<EquationSet>& eqn,
00131 const Array<VectorType<double> >& rowVectorType,
00132 const Array<VectorType<double> >& colVectorType,
00133 bool partitionBCs)
00134 : partitionBCs_(partitionBCs),
00135 numConfiguredColumns_(0),
00136 mesh_(mesh),
00137 eqn_(eqn),
00138 rowMap_(),
00139 colMap_(),
00140 externalRowSpace_(eqn->numVarBlocks()),
00141 externalColSpace_(eqn->numUnkBlocks()),
00142 privateRowSpace_(eqn->numVarBlocks()),
00143 privateColSpace_(eqn->numUnkBlocks()),
00144 bcRows_(eqn->numVarBlocks()),
00145 rqc_(),
00146 contexts_(),
00147 isBCRqc_(),
00148 isInternalBdry_(),
00149 groups_(),
00150 mediators_(),
00151 evalExprs_(),
00152 evalMgr_(rcp(new EvalManager())),
00153 isBCRow_(eqn->numVarBlocks()),
00154 isBCCol_(eqn->numUnkBlocks()),
00155 remoteBCCols_(eqn->numUnkBlocks()),
00156 lowestRow_(eqn->numVarBlocks()),
00157 lowestCol_(eqn->numUnkBlocks()),
00158 rowVecType_(rowVectorType),
00159 colVecType_(colVectorType),
00160 testIDToBlockMap_(),
00161 unkIDToBlockMap_()
00162 {
00163 TimeMonitor timer(assemblerCtorTimer());
00164 init(mesh, eqn);
00165 }
00166
00167 Assembler
00168 ::Assembler(const Mesh& mesh,
00169 const RCP<EquationSet>& eqn)
00170 : partitionBCs_(false),
00171 numConfiguredColumns_(0),
00172 mesh_(mesh),
00173 eqn_(eqn),
00174 rowMap_(),
00175 colMap_(),
00176 externalRowSpace_(eqn->numVarBlocks()),
00177 externalColSpace_(eqn->numUnkBlocks()),
00178 privateRowSpace_(eqn->numVarBlocks()),
00179 privateColSpace_(eqn->numUnkBlocks()),
00180 bcRows_(eqn->numVarBlocks()),
00181 rqc_(),
00182 contexts_(),
00183 isBCRqc_(),
00184 isInternalBdry_(),
00185 groups_(),
00186 mediators_(),
00187 evalExprs_(),
00188 evalMgr_(rcp(new EvalManager())),
00189 isBCRow_(eqn->numVarBlocks()),
00190 isBCCol_(eqn->numUnkBlocks()),
00191 remoteBCCols_(eqn->numUnkBlocks()),
00192 lowestRow_(eqn->numVarBlocks()),
00193 lowestCol_(eqn->numUnkBlocks()),
00194 rowVecType_(),
00195 colVecType_(),
00196 testIDToBlockMap_(),
00197 unkIDToBlockMap_(),
00198 fixedParamIDToVectorNumber_()
00199 {
00200 TimeMonitor timer(assemblerCtorTimer());
00201 init(mesh, eqn);
00202 }
00203
00204
00205 namespace {
00206 const Set<int> &
00207 findNonZeroIndices(const Array<int> &source, Set<int> &result)
00208 {
00209 result.clear();
00210 for (int i=0; i<source.size(); ++i)
00211 {
00212 if (source[i] != 0)
00213 {
00214 result.insert(result.end(), i);
00215 }
00216 }
00217 return result;
00218 }
00219 }
00220
00221 void Assembler::init(const Mesh& mesh, const RCP<EquationSet>& eqn)
00222 {
00223 Tabs tab0(0);
00224
00225
00226 int verb = 0;
00227 if (eqn->hasActiveWatchFlag())
00228 verb = eqn->maxWatchFlagSetting("assembler setup");
00229
00230 SUNDANCE_BANNER1(verb, tab0, "Assembler setup");
00231
00232
00233
00234 RCP<GrouperBase> grouper
00235 = rcp(new TrivialGrouper());
00236
00237
00238
00239
00240 const Set<ComputationType>& compTypes = eqn->computationTypes();
00241
00242
00243
00244 DOFMapBuilder mapBuilder(eqn->maxWatchFlagSetting("dof map setup"));
00245
00246 if (compTypes.contains(VectorOnly)
00247 || compTypes.contains(Sensitivities)
00248 || compTypes.contains(FunctionalAndGradient))
00249 {
00250 Tabs tab1;
00251 SUNDANCE_MSG2(verb, tab1 << "building row spaces");
00252 mapBuilder = DOFMapBuilder(mesh, eqn->fsr(), partitionBCs_,
00253 eqn->maxWatchFlagSetting("dof map setup"));
00254
00255 rowMap_ = mapBuilder.rowMap();
00256 isBCRow_ = mapBuilder.isBCRow();
00257 isBCCol_ = mapBuilder.isBCCol();
00258
00259 bcRows_.resize(isBCRow_.size());
00260 for (int b=0; b<isBCRow_.size(); ++b)
00261 {
00262 bcRows_[b] = rcp(new Set<int>);
00263 findNonZeroIndices(*isBCRow_[b], *bcRows_[b]);
00264 }
00265
00266 lowestRow_.resize(eqn_->numVarBlocks());
00267
00268 for (int b=0; b<eqn_->numVarBlocks(); b++)
00269 {
00270 Tabs tab2;
00271 lowestRow_[b] = rowMap_[b]->lowestLocalDOF();
00272 SUNDANCE_MSG2(verb, tab2 << "block " << b << ": lowest row="
00273 << lowestRow_[b]);
00274 externalRowSpace_[b] = rcp(
00275 new DiscreteSpace(mesh, testBasisArray(mapBuilder.fsr())[b],
00276 rowMap_[b], rowVecType_[b]));
00277 privateRowSpace_[b] = externalRowSpace_[b];
00278 SUNDANCE_MSG2(verb, tab2 << "block " << b << ": done forming row space");
00279 }
00280 }
00281
00282 if (!eqn->isFunctionalCalculator())
00283 {
00284 Tabs tab1;
00285
00286 SUNDANCE_MSG2(verb, tab1 << "building column spaces");
00287 colMap_ = mapBuilder.colMap();
00288
00289 for (int b=0; b<eqn_->numUnkBlocks(); b++)
00290 {
00291 Tabs tab2;
00292 externalColSpace_[b]
00293 = rcp(new DiscreteSpace(mesh, unkBasisArray(mapBuilder.fsr())[b],
00294 colMap_[b], colVecType_[b]));
00295 privateColSpace_[b] = externalColSpace_[b];
00296 SUNDANCE_MSG2(verb, tab2 << "block " << b << ": done forming col space");
00297 }
00298
00299
00300
00301 groups_.put(MatrixAndVector, Array<Array<RCP<IntegralGroup> > >());
00302 rqcRequiresMaximalCofacets_.put(MatrixAndVector,
00303 Array<IntegrationCellSpecifier>());
00304 skipRqc_.put(MatrixAndVector, Array<int>());
00305 contexts_.put(MatrixAndVector, Array<EvalContext>());
00306 evalExprs_.put(MatrixAndVector, Array<const EvaluatableExpr*>());
00307
00308
00309 groups_.put(VectorOnly, Array<Array<RCP<IntegralGroup> > >());
00310 rqcRequiresMaximalCofacets_.put(VectorOnly,
00311 Array<IntegrationCellSpecifier>());
00312 skipRqc_.put(VectorOnly, Array<int>());
00313 contexts_.put(VectorOnly, Array<EvalContext>());
00314 evalExprs_.put(VectorOnly, Array<const EvaluatableExpr*>());
00315
00316 if (eqn->isSensitivityCalculator())
00317 {
00318 fixedParamIDToVectorNumber_
00319 = eqn->fsr()->fixedParamIDToReducedFixedParamIDMap();
00320
00321
00322 groups_.put(Sensitivities, Array<Array<RCP<IntegralGroup> > >());
00323 rqcRequiresMaximalCofacets_.put(Sensitivities,
00324 Array<IntegrationCellSpecifier>());
00325 skipRqc_.put(Sensitivities, Array<int>());
00326 contexts_.put(Sensitivities, Array<EvalContext>());
00327 evalExprs_.put(Sensitivities, Array<const EvaluatableExpr*>());
00328
00329 }
00330 }
00331 else
00332 {
00333
00334 groups_.put(FunctionalAndGradient, Array<Array<RCP<IntegralGroup> > >());
00335 rqcRequiresMaximalCofacets_.put(FunctionalAndGradient,
00336 Array<IntegrationCellSpecifier>());
00337 skipRqc_.put(FunctionalAndGradient, Array<int>());
00338 contexts_.put(FunctionalAndGradient, Array<EvalContext>());
00339 evalExprs_.put(FunctionalAndGradient, Array<const EvaluatableExpr*>());
00340
00341 groups_.put(FunctionalOnly, Array<Array<RCP<IntegralGroup> > >());
00342 rqcRequiresMaximalCofacets_.put(FunctionalOnly,
00343 Array<IntegrationCellSpecifier>());
00344 skipRqc_.put(FunctionalOnly, Array<int>());
00345 contexts_.put(FunctionalOnly, Array<EvalContext>());
00346 evalExprs_.put(FunctionalOnly, Array<const EvaluatableExpr*>());
00347 }
00348
00349
00350
00351
00352
00353
00354 SUNDANCE_MSG1(verb, tab0 << std::endl
00355 << tab0 << "=== setting up non-BC region-quadrature combinations");
00356
00357 for (int r=0; r<eqn->regionQuadCombos().size(); r++)
00358 {
00359 Tabs tab1;
00360 Tabs tab12;
00361 const RegionQuadCombo& rqc = eqn->regionQuadCombos()[r];
00362
00363
00364 bool watchMe = rqc.watch().isActive();
00365
00366 int rqcVerb = verb;
00367 int integralCtorVerb = 0;
00368 int integrationVerb = 0;
00369 int integralTransformVerb = 0;
00370 if (watchMe)
00371 {
00372 rqcVerb = max(4,rqcVerb);
00373 integralCtorVerb = rqc.watch().param("integration setup");
00374 integrationVerb = rqc.watch().param("integration");
00375 integralTransformVerb = rqc.watch().param("integral transformation");
00376 }
00377
00378
00379
00380 rqc_.append(rqc);
00381 isBCRqc_.append(false);
00382
00383
00384 const Expr& expr = eqn->expr(rqc);
00385
00386 SUNDANCE_MSG2(rqcVerb, tab1 << std::endl << tab1 << "------------------------------------------------");
00387 SUNDANCE_MSG2(rqcVerb, tab1 << "initializing assembly for"
00388 << std::endl << tab12 << "r=" << r << " rqc="
00389 << rqc << std::endl << tab12 << std::endl << tab12 << "------------------------------"
00390 << std::endl << tab12 << "expr = " << expr
00391 << std::endl << tab12 << "------------------------------"
00392 );
00393
00394
00395
00396 int cellDim = CellFilter(rqc.domain()).dimension(mesh);
00397 CellType cellType = mesh.cellType(cellDim);
00398 CellType maxCellType = mesh.cellType(mesh.spatialDim());
00399 QuadratureFamily quad(rqc.quad());
00400
00401
00402 bool isInternalBdry = detectInternalBdry(cellDim, rqc.domain());
00403 isInternalBdry_.append(isInternalBdry);
00404
00405 SUNDANCE_MSG2(rqcVerb, tab12 << "isInternalBdry=" << isInternalBdry);
00406
00407
00408 bool rqcUsed = false;
00409
00410 for (Set<ComputationType>::const_iterator
00411 i=eqn->computationTypes().begin();
00412 i!=eqn->computationTypes().end();
00413 i++)
00414 {
00415 Tabs tab2;
00416 const ComputationType& compType = *i;
00417 SUNDANCE_MSG2(rqcVerb, tab12 << std::endl << tab12
00418 << "** computation type " << compType);
00419
00420
00421
00422
00423 if (eqn->skipRqc(compType, rqc))
00424 {
00425 SUNDANCE_MSG2(rqcVerb, tab2 << "RQC not needed for computation type "
00426 << compType);
00427 skipRqc_[compType].append(true);
00428 EvalContext dummy;
00429 const EvaluatableExpr* dummyEx = 0;
00430 Array<RCP<IntegralGroup> > dummyGroups;
00431 IntegrationCellSpecifier dummyCellSpec ;
00432 contexts_[compType].append(dummy);
00433 evalExprs_[compType].append(dummyEx);
00434 groups_[compType].append(dummyGroups);
00435 rqcRequiresMaximalCofacets_[compType].append(dummyCellSpec);
00436 }
00437 else
00438 {
00439
00440
00441 rqcUsed = true;
00442 skipRqc_[compType].append(false);
00443
00444
00445
00446 EvalContext context = eqn->rqcToContext(compType, rqc);
00447
00448 SUNDANCE_MSG2(rqcVerb, tab2 << "context " << context.brief());
00449
00450
00451 contexts_[compType].append(context);
00452
00453
00454 const EvaluatableExpr* ee = EvaluatableExpr::getEvalExpr(expr);
00455 evalExprs_[compType].append(ee);
00456
00457
00458
00459
00460 const RCP<SparsitySuperset>& sparsity
00461 = ee->sparsitySuperset(context);
00462 SUNDANCE_MSG3(rqcVerb, tab2 << "sparsity pattern " << *sparsity);
00463
00464
00465
00466 Array<RCP<IntegralGroup> > groups;
00467 grouper->setVerb(integralCtorVerb, integrationVerb, integralTransformVerb);
00468 grouper->findGroups(*eqn, maxCellType, mesh.spatialDim(),
00469 cellType, cellDim, quad, sparsity, isInternalBdry, groups , rqc.paramCurve() , mesh_ );
00470 grouper->setVerb(0,0,0);
00471 groups_[compType].append(groups);
00472
00473
00474
00475 IntegrationCellSpecifier cellSpec
00476 = whetherToUseCofacets(groups, ee,
00477 cellDim==mesh_.spatialDim(), rqcVerb);
00478 SUNDANCE_MSG2(rqcVerb, tab2 << "integration: " << cellSpec);
00479 rqcRequiresMaximalCofacets_[compType].append(cellSpec);
00480 }
00481 SUNDANCE_MSG2(rqcVerb, tab12
00482 << "done with computation type " << compType);
00483 }
00484
00485
00486
00487
00488
00489
00490 if (rqcUsed)
00491 {
00492 SUNDANCE_MSG2(rqcVerb, tab12 << "creating evaluation mediator for rqc="
00493 << rqc);
00494 SUNDANCE_MSG2(rqcVerb, tab12 << "expr = " << expr);
00495
00496
00497
00498
00499
00500
00501 if ( rqc.paramCurve().isCurveIntegral() && rqc.paramCurve().isCurveValid() )
00502 {
00503 mediators_.append(rcp(new CurveEvalMediator(mesh, rqc.paramCurve() , cellDim, quad)));
00504 }
00505 else
00506 {
00507 mediators_.append(rcp(new QuadratureEvalMediator(mesh, cellDim, quad)));
00508 }
00509 }
00510 else
00511 {
00512 SUNDANCE_MSG2(rqcVerb, tab1 << "creating empty eval mediator for unused rqc");
00513 mediators_.append(RCP<StdFwkEvalMediator>());
00514 }
00515 SUNDANCE_MSG2(rqcVerb, tab1
00516 << "done with RQC");
00517 }
00518
00519
00520
00521
00522 SUNDANCE_MSG1(verb, tab0 << std::endl
00523 << tab0 << "=== setting up BC region-quadrature combinations");
00524
00525 for (int r=0; r<eqn->bcRegionQuadCombos().size(); r++)
00526 {
00527 Tabs tab1;
00528 const RegionQuadCombo& rqc = eqn->bcRegionQuadCombos()[r];
00529
00530
00531 bool watchMe = rqc.watch().isActive();
00532 int rqcVerb = verb;
00533 int integralCtorVerb = 0;
00534 int integrationVerb = 0;
00535 int integralTransformVerb = 0;
00536 if (watchMe)
00537 {
00538 rqcVerb = max(4,rqcVerb);
00539 integralCtorVerb = rqc.watch().param("integration setup");
00540 integrationVerb = rqc.watch().param("integration");
00541 integralTransformVerb = rqc.watch().param("integral transformation");
00542 }
00543
00544
00545 rqc_.append(rqc);
00546 isBCRqc_.append(true);
00547
00548
00549
00550 const Expr& expr = eqn->bcExpr(rqc);
00551
00552 SUNDANCE_MSG2(rqcVerb, tab1 << std::endl << tab1
00553 << "------------------------------------------------");
00554 SUNDANCE_MSG1(rqcVerb, tab1 << "initializing assembly for BC r=" << r
00555 << " rqc="
00556 << rqc << std::endl << tab1
00557 << "expr = " << expr);
00558
00559
00560 int cellDim = CellFilter(rqc.domain()).dimension(mesh);
00561 CellType cellType = mesh.cellType(cellDim);
00562 CellType maxCellType = mesh.cellType(mesh.spatialDim());
00563 QuadratureFamily quad(rqc.quad());
00564
00565
00566 bool isInternalBdry = detectInternalBdry(cellDim, rqc.domain());
00567 isInternalBdry_.append(isInternalBdry);
00568
00569
00570 bool rqcUsed = false;
00571
00572 for (Set<ComputationType>::const_iterator
00573 i=eqn->computationTypes().begin();
00574 i!=eqn->computationTypes().end();
00575 i++)
00576 {
00577 Tabs tab2;
00578 const ComputationType& compType = *i;
00579 SUNDANCE_MSG2(rqcVerb, tab1 << std::endl << tab1
00580 << "** computation type " << compType);
00581
00582
00583
00584
00585
00586 if (eqn->skipBCRqc(compType, rqc))
00587 {
00588 SUNDANCE_MSG2(rqcVerb,
00589 tab2 << "this rqc not needed for computation type " << compType);
00590 skipRqc_[compType].append(true);
00591 EvalContext dummy;
00592 const EvaluatableExpr* dummyEx = 0;
00593 Array<RCP<IntegralGroup> > dummyGroups;
00594 IntegrationCellSpecifier dummyCellSpec ;
00595 contexts_[compType].append(dummy);
00596 evalExprs_[compType].append(dummyEx);
00597 groups_[compType].append(dummyGroups);
00598 rqcRequiresMaximalCofacets_[compType].append(dummyCellSpec);
00599 }
00600 else
00601 {
00602
00603
00604 rqcUsed = true;
00605 skipRqc_[compType].append(false);
00606
00607
00608
00609 EvalContext context = eqn->bcRqcToContext(compType, rqc);
00610 SUNDANCE_MSG2(rqcVerb, tab2 << "context " << context);
00611
00612
00613 contexts_[compType].append(context);
00614 const EvaluatableExpr* ee = EvaluatableExpr::getEvalExpr(expr);
00615 evalExprs_[compType].append(ee);
00616 const RCP<SparsitySuperset>& sparsity
00617 = ee->sparsitySuperset(context);
00618 SUNDANCE_MSG3(rqcVerb, tab2 << "sparsity pattern " << *sparsity);
00619
00620 Array<RCP<IntegralGroup> > groups;
00621 grouper->setVerb(integralCtorVerb, integrationVerb, integralTransformVerb);
00622 grouper->findGroups(*eqn, maxCellType, mesh.spatialDim(),
00623 cellType, cellDim, quad, sparsity, isInternalBdry, groups , rqc.paramCurve() , mesh_ );
00624 grouper->setVerb(0,0,0);
00625 groups_[compType].append(groups);
00626 IntegrationCellSpecifier cellSpec
00627 = whetherToUseCofacets(groups, ee,
00628 cellDim==mesh_.spatialDim(), rqcVerb);
00629 SUNDANCE_MSG2(rqcVerb, tab2 << "integration: " << cellSpec);
00630 rqcRequiresMaximalCofacets_[compType].append(cellSpec);
00631 SUNDANCE_MSG2(rqcVerb, tab1
00632 << "done with computation type " << compType);
00633 }
00634
00635
00636
00637
00638 if (rqcUsed)
00639 {
00640 SUNDANCE_MSG2(rqcVerb, tab1 << "creating evaluation mediator for BC rqc="
00641 << rqc << std::endl << tab1 << "expr = " << expr);
00642
00643 if ( rqc.paramCurve().isCurveIntegral() && rqc.paramCurve().isCurveValid() )
00644 {
00645 mediators_.append(rcp(new CurveEvalMediator(mesh, rqc.paramCurve(), cellDim, quad)));
00646 }
00647 else
00648 {
00649 mediators_.append(rcp(new QuadratureEvalMediator(mesh, cellDim, quad)));
00650 }
00651 }
00652 else
00653 {
00654 SUNDANCE_MSG2(rqcVerb, tab1 << "creating empty eval mediator for unused BC rqc");
00655 mediators_.append(RCP<StdFwkEvalMediator>());
00656 }
00657 }
00658 SUNDANCE_MSG2(rqcVerb, tab1
00659 << "done with BC RQC");
00660 }
00661 }
00662
00663 bool Assembler::detectInternalBdry(int cellDim,
00664 const CellFilter& filter) const
00665 {
00666 int d = mesh_.spatialDim();
00667 if (cellDim == d-1)
00668 {
00669 CellSet cells = filter.getCells(mesh_);
00670 for (CellIterator c=cells.begin(); c!=cells.end(); c++)
00671 {
00672 if (mesh_.numMaxCofacets(cellDim, *c) > 1) return true;
00673 }
00674 }
00675 return false;
00676 }
00677
00678 IntegrationCellSpecifier Assembler::whetherToUseCofacets(
00679 const Array<RCP<IntegralGroup> >& groups,
00680 const EvaluatableExpr* ee,
00681 bool isMaximalCell,
00682 int verb) const
00683 {
00684 Tabs tab;
00685 SUNDANCE_MSG2(verb,
00686 tab << "deciding whether to use cofacet cells for some integrations");
00687
00688 if (isMaximalCell)
00689 {
00690 Tabs tab1;
00691 SUNDANCE_MSG2(verb,
00692 tab1 << "cofacets not needed because cells are maximal");
00693 return NoTermsNeedCofacets;
00694 }
00695
00696 IntegrationCellSpecifier cellSpec = SomeTermsNeedCofacets;
00697
00698 bool allTermsNeedCofacets = true;
00699 bool noTermsNeedCofacets = true;
00700 for (int g=0; g<groups.size(); g++)
00701 {
00702 Tabs tab1;
00703 switch(groups[g]->usesMaximalCofacets())
00704 {
00705 case NoTermsNeedCofacets:
00706 allTermsNeedCofacets = false;
00707 SUNDANCE_MSG2(verb,
00708 tab1 << "integral group " << g << " does not need cofacets");
00709 break;
00710 case AllTermsNeedCofacets:
00711 case SomeTermsNeedCofacets:
00712 noTermsNeedCofacets = false;
00713 SUNDANCE_MSG2(verb,
00714 tab1 << "integral group " << g << " needs cofacets");
00715 break;
00716 default:
00717 TEUCHOS_TEST_FOR_EXCEPT(1);
00718 }
00719 }
00720
00721 if (allTermsNeedCofacets)
00722 {
00723 cellSpec = AllTermsNeedCofacets;
00724 }
00725 else if (noTermsNeedCofacets)
00726 {
00727 cellSpec = NoTermsNeedCofacets;
00728 }
00729
00730 if (!isMaximalCell && ee->maxDiffOrderOnDiscreteFunctions() > 0)
00731 {
00732 Tabs tab1;
00733 SUNDANCE_MSG2(verb, tab1
00734 << "(*) discrete functions will require cofacet-based transformations");
00735 if (cellSpec==NoTermsNeedCofacets)
00736 {
00737 cellSpec = SomeTermsNeedCofacets;
00738 }
00739 }
00740
00741 SUNDANCE_MSG2(verb, tab << "found: " << cellSpec);
00742
00743 return cellSpec;
00744 }
00745
00746
00747 void Assembler::configureVector(Array<Vector<double> >& b) const
00748 {
00749
00750 TimeMonitor timer(configTimer());
00751
00752 Tabs tab0;
00753 int verb = eqn_->maxWatchFlagSetting("vector config");
00754
00755 SUNDANCE_MSG1(verb, tab0 << "in Assembler::configureVector()");
00756
00757
00758 Array<VectorSpace<double> > vs(eqn_->numVarBlocks());
00759 for (int i=0; i<eqn_->numVarBlocks(); i++)
00760 {
00761 vs[i] = privateRowSpace_[i]->vecSpace();
00762 }
00763 VectorSpace<double> rowSpace;
00764
00765
00766
00767 if (eqn_->numVarBlocks() > 1)
00768 {
00769 rowSpace = Playa::blockSpace(vs);
00770 }
00771 else
00772 {
00773 rowSpace = vs[0];
00774 }
00775
00776
00777 for (int i=0; i<b.size(); i++)
00778 {
00779
00780
00781 b[i] = rowSpace.createMember();
00782
00783
00784 if (!partitionBCs_ && eqn_->numVarBlocks() > 1)
00785 {
00786
00787 Vector<double> vecBlock;
00788 for (int br=0; br<eqn_->numVarBlocks(); br++)
00789 {
00790 configureVectorBlock(br, vecBlock);
00791 b[i].setBlock(br, vecBlock);
00792 }
00793 }
00794 else
00795 {
00796
00797 if (!partitionBCs_)
00798 {
00799 Playa::LoadableVector<double>* lv
00800 = dynamic_cast<Playa::LoadableVector<double>* >(b[i].ptr().get());
00801
00802 TEUCHOS_TEST_FOR_EXCEPTION(lv == 0, std::runtime_error,
00803 "vector is not loadable in Assembler::configureVector()");
00804 }
00805 else
00806 {
00807 }
00808 }
00809 }
00810 numConfiguredColumns_ = b.size();
00811 }
00812
00813 void Assembler::configureVectorBlock(int br, Vector<double>& b) const
00814 {
00815 Tabs tab0;
00816 int verb = eqn_->maxWatchFlagSetting("vector config");
00817 SUNDANCE_MSG2(verb, tab0 << "in Assembler::configureVectorBlock()");
00818 VectorSpace<double> vecSpace = privateRowSpace_[br]->vecSpace();
00819
00820 b = vecSpace.createMember();
00821
00822 if (!partitionBCs_)
00823 {
00824 Playa::LoadableVector<double>* lv
00825 = dynamic_cast<Playa::LoadableVector<double>* >(b.ptr().get());
00826
00827 TEUCHOS_TEST_FOR_EXCEPTION(lv == 0, std::runtime_error,
00828 "vector block is not loadable "
00829 "in Assembler::configureVectorBlock()");
00830 }
00831 }
00832
00833
00834 void Assembler::configureMatrix(LinearOperator<double>& A,
00835 Array<Vector<double> >& b) const
00836 {
00837 TimeMonitor timer(configTimer());
00838 int verb = eqn_->maxWatchFlagSetting("matrix config");
00839 Tabs tab;
00840 SUNDANCE_MSG1(verb, tab << "in Assembler::configureMatrix()");
00841
00842
00843 SUNDANCE_MSG1(verb, tab << "before config: A=" << A.description());
00844 if (matNeedsConfiguration())
00845 {
00846 Tabs tab0;
00847
00848 int nRowBlocks = rowMap_.size();
00849 int nColBlocks = colMap_.size();
00850 Array<Array<int> > isNonzero = findNonzeroBlocks();
00851
00852 if (nRowBlocks==1 && nColBlocks==1)
00853 {
00854 configureMatrixBlock(0,0,A);
00855 }
00856 else
00857 {
00858 A = makeBlockOperator(solnVecSpace(), rowVecSpace());
00859 for (int br=0; br<nRowBlocks; br++)
00860 {
00861 for (int bc=0; bc<nColBlocks; bc++)
00862 {
00863 if (isNonzero[br][bc])
00864 {
00865 LinearOperator<double> matBlock;
00866 configureMatrixBlock(br, bc, matBlock);
00867 A.setBlock(br, bc, matBlock);
00868 }
00869 }
00870 }
00871 A.endBlockFill();
00872 }
00873 cachedAssembledMatrix_ = A;
00874 }
00875 else
00876 {
00877 Tabs tab0;
00878 SUNDANCE_MSG1(verb,
00879 tab0 << "Assembler::configureMatrix() not needed, proceeding to configure vector");
00880 A = cachedAssembledMatrix_;
00881 }
00882 SUNDANCE_MSG1(verb, tab << "after config: A=" << A.description());
00883 configureVector(b);
00884 }
00885
00886 void Assembler::configureMatrixBlock(int br, int bc,
00887 LinearOperator<double>& A) const
00888 {
00889 Tabs tab;
00890 TimeMonitor timer(configTimer());
00891 int verb = eqn_->maxWatchFlagSetting("matrix config");
00892
00893 SUNDANCE_MSG1(verb, tab << "in configureMatrixBlock()");
00894
00895 SUNDANCE_MSG2(verb, tab << "num rows = " << rowMap()[br]->numDOFs());
00896
00897 SUNDANCE_MSG2(verb, tab << "num cols = " << colMap()[bc]->numDOFs());
00898
00899 VectorSpace<double> rowSpace = privateRowSpace_[br]->vecSpace();
00900 VectorSpace<double> colSpace = privateColSpace_[bc]->vecSpace();
00901
00902 RCP<MatrixFactory<double> > matFactory ;
00903
00904 matFactory = rowVecType_[br].createMatrixFactory(colSpace, rowSpace);
00905
00906 IncrementallyConfigurableMatrixFactory* icmf
00907 = dynamic_cast<IncrementallyConfigurableMatrixFactory*>(matFactory.get());
00908
00909 CollectivelyConfigurableMatrixFactory* ccmf
00910 = dynamic_cast<CollectivelyConfigurableMatrixFactory*>(matFactory.get());
00911
00912 TEUCHOS_TEST_FOR_EXCEPTION(ccmf==0 && icmf==0, std::runtime_error,
00913 "Neither incremental nor collective matrix structuring "
00914 "appears to be available");
00915
00916
00917
00918
00919 if (false )
00920 {
00921 Tabs tab1;
00922 SUNDANCE_MSG2(verb, tab1 << "Assembler: doing collective matrix structuring...");
00923 Array<int> graphData;
00924 Array<int> nnzPerRow;
00925 Array<int> rowPtrs;
00926
00927 using Teuchos::createVector;
00928
00929 getGraph(br, bc, graphData, rowPtrs, nnzPerRow);
00930 ccmf->configure(lowestRow_[br], createVector(rowPtrs), createVector(nnzPerRow), createVector(graphData));
00931 }
00932 else
00933 {
00934 Tabs tab1;
00935 SUNDANCE_MSG2(verb, tab1 << "Assembler: doing incremental matrix structuring...");
00936 incrementalGetGraph(br, bc, icmf);
00937 {
00938 TimeMonitor timer1(matFinalizeTimer());
00939 icmf->finalize();
00940 }
00941 }
00942
00943 SUNDANCE_MSG3(verb, tab << "Assembler: allocating matrix...");
00944 {
00945 TimeMonitor timer1(matAllocTimer());
00946 A = matFactory->createMatrix();
00947 }
00948 }
00949
00950 Playa::LinearOperator<double> Assembler::allocateMatrix() const
00951 {
00952 LinearOperator<double> A;
00953 Array<Vector<double> > b;
00954 configureMatrix(A, b);
00955 return A;
00956 }
00957
00958
00959
00960
00961
00962
00963 void Assembler::displayEvaluationResults(
00964 const EvalContext& context,
00965 const EvaluatableExpr* evalExpr,
00966 const Array<double>& constantCoeffs,
00967 const Array<RCP<EvalVector> >& vectorCoeffs) const
00968 {
00969 Tabs tab;
00970 FancyOStream& os = Out::os();
00971
00972 os << tab << "evaluation results: " << std::endl;
00973
00974 const RCP<SparsitySuperset>& sparsity
00975 = evalExpr->sparsitySuperset(context);
00976
00977 sparsity->print(os, vectorCoeffs, constantCoeffs);
00978 }
00979
00980
00981
00982 void Assembler::assemblyLoop(const ComputationType& compType,
00983 RCP<AssemblyKernelBase> kernel) const
00984 {
00985 Tabs tab;
00986 int verb = 0;
00987 if (eqn_->hasActiveWatchFlag()) verb = max(eqn_->maxWatchFlagSetting("assembly loop"), 1);
00988
00989
00990 SUNDANCE_BANNER1(verb, tab, "Assembly loop");
00991
00992 SUNDANCE_MSG1(verb, tab << "computation type is " << compType);
00993
00994
00995
00996
00997 SUNDANCE_MSG2(verb, tab << "work set size is " << workSetSize());
00998 RCP<Array<int> > workSet = rcp(new Array<int>());
00999 workSet->reserve(workSetSize());
01000
01001
01002
01003
01004 RCP<Array<int> > isLocalFlag = rcp(new Array<int>());
01005 isLocalFlag->reserve(workSetSize());
01006
01007
01008
01009
01010
01011
01012 Array<RCP<EvalVector> > vectorCoeffs;
01013 Array<double> constantCoeffs;
01014
01015
01016 RCP<Array<double> > localValues = rcp(new Array<double>());
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 const Array<EvalContext>& contexts = contexts_.get(compType);
01027
01028 const Array<Array<RCP<IntegralGroup> > >& groups = groups_.get(compType);
01029
01030 const Array<const EvaluatableExpr*>& evalExprs
01031 = evalExprs_.get(compType);
01032
01033
01034 const Array<int>& skipRqc = skipRqc_.get(compType);
01035
01036
01037
01038
01039
01040 SUNDANCE_MSG1(verb,
01041 tab << "---------- outer assembly loop over subregions");
01042
01043
01044
01045
01046
01047 Array< Array<RCP<AssemblyTransformationBuilder> > > transformations;
01048
01049
01050 transformations.resize(rqc_.size());
01051 for (int r=0; r<rqc_.size(); r++)
01052 {
01053 transformations[r].resize(groups[r].size());
01054 for (int g=0; g<groups[r].size(); g++)
01055 {
01056 const RCP<IntegralGroup>& group = groups[r][g];
01057
01058
01059 transformations[r][g] = rcp(new AssemblyTransformationBuilder( group , rowMap_ , colMap_ , mesh_));
01060 }
01061 }
01062
01063
01064
01065
01066 int oldKernelVerb = kernel->verb();
01067
01068 TEUCHOS_TEST_FOR_EXCEPT(rqc_.size() != evalExprs.size());
01069
01070
01071 for (int r=0; r<rqc_.size(); r++)
01072 {
01073 Tabs tab0;
01074
01075
01076 int rqcVerb = 0;
01077 int evalVerb = 0;
01078 int evalMedVerb = 0;
01079 int dfEvalVerb = 0;
01080 int fillVerb = 0;
01081
01082
01083 if (rqc_[r].watch().isActive())
01084 {
01085 Tabs tab01;
01086 rqcVerb=verb;
01087 evalVerb = rqc_[r].watch().param("evaluation");
01088 evalMedVerb = rqc_[r].watch().param("eval mediator");
01089 dfEvalVerb = rqc_[r].watch().param("discrete function evaluation");
01090 fillVerb = rqc_[r].watch().param("fill");
01091
01092 SUNDANCE_MSG1(rqcVerb, tab0 << std::endl
01093 << tab0 << "-------------"
01094 << std::endl << tab0 << " doing watched subregion r=" << r << " of "
01095 << rqc_.size() << ", rqc="
01096 << rqc_[r]);
01097 if (skipRqc[r])
01098 {
01099 SUNDANCE_MSG2(rqcVerb, tab01 << "this rqc is not needed in comp type = " << compType);
01100 }
01101 else
01102 {
01103 SUNDANCE_MSG2(rqcVerb, tab01 << "expr is " << evalExprs[r]->toString());
01104 SUNDANCE_MSG2(rqcVerb, tab01 << "isBC= " << isBCRqc_[r]);
01105 }
01106 }
01107 else
01108 {
01109 SUNDANCE_MSG1(verb, tab0 << "unwatched region r=" << r << " of " << rqc_.size());
01110 }
01111 Tabs tab01;
01112
01113 kernel->setVerb(fillVerb);
01114
01115
01116
01117
01118 if ((!isBCRqc_[r] && eqn_->skipRqc(compType, rqc_[r]))
01119 || (isBCRqc_[r] && eqn_->skipBCRqc(compType, rqc_[r])))
01120 {
01121 Tabs tab012;
01122 SUNDANCE_MSG2(rqcVerb, tab012 << "nothing to do for comp type "
01123 << compType);
01124 continue;
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 evalMgr_->setMediator(mediators_[r]);
01137 mediators_[r]->setVerb(evalMedVerb, dfEvalVerb);
01138
01139
01140
01141
01142 evalMgr_->setRegion(contexts_.get(compType)[r]);
01143
01144
01145 CellFilter filter = rqc_[r].domain();
01146
01147
01148
01149
01150
01151 CellSet cells = filter.getCells(mesh_);
01152
01153 int cellDim = filter.dimension(mesh_);
01154
01155
01156
01157
01158
01159
01160 CellType cellType = mesh_.cellType(cellDim);
01161
01162
01163
01164
01165 CellType maxCellType = mesh_.cellType(mesh_.spatialDim());
01166
01167 SUNDANCE_MSG2(rqcVerb, tab01 << "cell type = " << cellType
01168 << ", cellDim = " << cellDim
01169 << ", max cell type = " << maxCellType
01170 << ", max cell dim = " << mesh_.spatialDim());
01171
01172
01173
01174
01175 IntegrationCellSpecifier intCellSpec
01176 = rqcRequiresMaximalCofacets_.get(compType)[r];
01177 SUNDANCE_MSG2(rqcVerb, tab01
01178 << "whether we need to refer to maximal cofacets: " << intCellSpec);
01179
01180
01181
01182 const Array<Set<int> >& requiredVars = eqn_->reducedVarsOnRegion(filter);
01183 const Array<Set<int> >& requiredUnks = eqn_->reducedUnksOnRegion(filter);
01184
01185
01186
01187
01188 SUNDANCE_MSG2(rqcVerb, tab01 << "setting integration specifier in mediator");
01189 mediators_[r]->setIntegrationSpec(intCellSpec);
01190
01191
01192
01193
01194
01195
01196
01197 SUNDANCE_MSG2(rqcVerb, tab01 << "setting cell type=" << cellType << " in mediator");
01198 mediators_[r]->setCellType(cellType, maxCellType, isInternalBdry_[r]);
01199
01200
01201
01202 const Evaluator* evaluator
01203 = evalExprs[r]->evaluator(contexts[r]).get();
01204
01205
01206
01207
01208 CellIterator iter=cells.begin();
01209 int workSetCounter = 0;
01210 int myRank = mesh_.comm().getRank();
01211
01212 SUNDANCE_MSG2(rqcVerb, tab01 << "----- looping over worksets");
01213 while (iter != cells.end())
01214 {
01215 Tabs tab1;
01216
01217
01218
01219
01220
01221
01222 workSet->resize(0);
01223 isLocalFlag->resize(0);
01224 for (int c=0; c<workSetSize() && iter != cells.end(); c++, iter++)
01225 {
01226 workSet->append(*iter);
01227
01228
01229 isLocalFlag->append(myRank==mesh_.ownerProcID(cellDim, *iter));
01230 }
01231
01232 SUNDANCE_MSG2(rqcVerb,
01233 tab1 << "doing work set " << workSetCounter
01234 << " consisting of " << workSet->size() << " cells");
01235 {
01236 Tabs tab2;
01237 SUNDANCE_MSG4(rqcVerb, tab2 << "cells are " << *workSet);
01238 }
01239 workSetCounter++;
01240
01241
01242 evalMgr_->setVerb(evalVerb);
01243
01244
01245
01246
01247 mediators_[r]->setCellBatch(workSet);
01248
01249
01250
01251
01252
01253
01254
01255 const CellJacobianBatch& JVol = mediators_[r]->JVol();
01256 const CellJacobianBatch& JTrans = mediators_[r]->JTrans();
01257
01258
01259
01260
01261 const Array<int>& facetIndices = mediators_[r]->facetIndices();
01262 if (facetIndices.size() > 0)
01263 {
01264 Tabs tab2;
01265 SUNDANCE_MSG2(rqcVerb, tab2 << "facet indices are " << facetIndices);
01266 }
01267
01268
01269
01270
01271 kernel->prepareForWorkSet(
01272 requiredVars,
01273 requiredUnks,
01274 mediators_[r]);
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 evaluator->resetNumCalls();
01287 SUNDANCE_MSG2(rqcVerb, tab1
01288 << "====== evaluating coefficient expressions") ;
01289 try
01290 {
01291 evalExprs[r]->evaluate(*evalMgr_, constantCoeffs, vectorCoeffs);
01292 }
01293 catch(std::exception& exc)
01294 {
01295 Tabs tabX;
01296 SUNDANCE_BANNER1(10, tabX,
01297 "DETECTED EXCEPTION DURING EXPR EVALUATION CALL IN ASSEMBLY LOOP");
01298 Tabs tabX1;
01299 SUNDANCE_MSG1(10, tabX1 << "While working on RQC="
01300 << rqc_[r]);
01301 SUNDANCE_MSG1(10, tabX1 << "While evaluating expr="
01302 << evalExprs[r]->toString());
01303 throw (std::runtime_error(exc.what()));
01304 }
01305
01306
01307 SUNDANCE_MSG2(rqcVerb, tab1 << "====== done evaluating expressions") ;
01308 if (evalVerb > 3)
01309 {
01310 displayEvaluationResults(contexts[r], evalExprs[r], constantCoeffs,
01311 vectorCoeffs);
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326 ElementIntegral::invalidateTransformationMatrices();
01327
01328
01329 SUNDANCE_MSG2(rqcVerb, tab1 << "----- looping over integral groups");
01330 for (int g=0; g<groups[r].size(); g++)
01331 {
01332 Tabs tab2;
01333 SUNDANCE_MSG2(rqcVerb, tab2 << std::endl << tab2
01334 << "--- evaluating integral group g=" << g << " of "
01335 << groups[r].size() );
01336
01337
01338
01339 const RCP<IntegralGroup>& group = groups[r][g];
01340 if (!group->evaluate(JTrans, JVol, *isLocalFlag, facetIndices, workSet,
01341 vectorCoeffs, constantCoeffs, localValues)) continue;
01342
01343
01344
01345
01346
01347 transformations[r][g]->applyTransformsToAssembly(
01348 g , (localValues->size() / workSet->size()),
01349 cellType, cellDim , maxCellType,
01350 JTrans, JVol, facetIndices, workSet, localValues);
01351
01352
01353
01354
01355
01356
01357
01358
01359 {
01360 TimeMonitor fillTM(fillTimer());
01361 kernel->fill(isBCRqc_[r], *group, localValues);
01362 }
01363 }
01364 SUNDANCE_MSG2(rqcVerb, tab1 << "----- done looping over integral groups");
01365 }
01366 SUNDANCE_MSG2(rqcVerb, tab0 << "----- done looping over worksets");
01367
01368 kernel->setVerb(oldKernelVerb);
01369 SUNDANCE_MSG1(verb, tab0 << "----- done rqc");
01370 }
01371 SUNDANCE_MSG1(verb, tab << "----- done looping over rqcs");
01372
01373
01374
01375 SUNDANCE_MSG2(verb, tab << "doing post-loop processing");
01376 kernel->postLoopFinalization();
01377 SUNDANCE_BANNER1(verb, tab, "done assembly loop");
01378
01379
01380 }
01381
01382
01383
01384
01385
01386 void Assembler::assemble(LinearOperator<double>& A,
01387 Array<Vector<double> >& mv) const
01388 {
01389 TimeMonitor timer(assemblyTimer());
01390 Tabs tab;
01391 int verb = 0;
01392 if (eqn_->hasActiveWatchFlag()) verb = max(verb, 1);
01393
01394 SUNDANCE_BANNER1(verb, tab, "Assembling matrix and vector");
01395
01396 TEUCHOS_TEST_FOR_EXCEPTION(!contexts_.containsKey(MatrixAndVector),
01397 std::runtime_error,
01398 "Assembler::assemble(A, b) called for an assembler that "
01399 "does not support matrix/vector assembly");
01400
01401 configureMatrix(A, mv);
01402
01403 RCP<AssemblyKernelBase> kernel
01404 = rcp(new MatrixVectorAssemblyKernel(
01405 rowMap_, isBCRow_, lowestRow_,
01406 colMap_, isBCCol_, lowestCol_,
01407 A, mv, partitionBCs_,
01408 0));
01409
01410 assemblyLoop(MatrixAndVector, kernel);
01411
01412 SUNDANCE_MSG1(verb, tab << "matrix=" << A);
01413 if (verb>0) A.print(Out::os());
01414 SUNDANCE_MSG1(verb, tab << "vectors=" << mv);
01415 for (int i=0; i<mv.size(); i++)
01416 {
01417 SUNDANCE_MSG1(verb, tab << "vectors #" << i);
01418 if (verb>0) mv[i].print(Out::os());
01419 }
01420
01421 SUNDANCE_MSG1(verb, tab << "Assembler: done assembling matrix and vector");
01422 }
01423
01424
01425
01426 void Assembler::assembleSensitivities(LinearOperator<double>& A,
01427 Array<Vector<double> >& mv) const
01428 {
01429 TimeMonitor timer(assemblyTimer());
01430 Tabs tab;
01431 int verb = 0;
01432 if (eqn_->hasActiveWatchFlag()) verb = max(verb, 1);
01433
01434 SUNDANCE_BANNER1(verb, tab, "Assembling matrix and sensitivity vector");
01435
01436 TEUCHOS_TEST_FOR_EXCEPTION(!contexts_.containsKey(Sensitivities),
01437 std::runtime_error,
01438 "Assembler::assembleSensitivities(A, b) called for an assembler that "
01439 "does not support sensitivity assembly");
01440
01441 configureMatrix(A, mv);
01442
01443
01444 RCP<AssemblyKernelBase> kernel
01445 = rcp(new MatrixVectorAssemblyKernel(
01446 rowMap_, isBCRow_, lowestRow_,
01447 colMap_, isBCCol_, lowestCol_,
01448 A, mv, partitionBCs_,
01449 0));
01450
01451 assemblyLoop(Sensitivities, kernel);
01452 SUNDANCE_MSG1(verb, tab << "Assembler: done assembling matrix and sensitivity vector");
01453 }
01454
01455
01456
01457
01458 void Assembler::assemble(Array<Vector<double> >& mv) const
01459 {
01460
01461 Tabs tab;
01462
01463 TimeMonitor timer(assemblyTimer());
01464
01465
01466 int verb = 0;
01467 if (eqn_->hasActiveWatchFlag()) verb = max(verb, 1);
01468
01469 SUNDANCE_BANNER1(verb, tab, "Assembling vector");
01470
01471
01472 TEUCHOS_TEST_FOR_EXCEPTION(!contexts_.containsKey(VectorOnly),
01473 std::runtime_error,
01474 "Assembler::assemble(b) called for an assembler that "
01475 "does not support vector-only assembly");
01476
01477
01478 configureVector(mv);
01479
01480
01481 RCP<AssemblyKernelBase> kernel
01482 = rcp(new VectorAssemblyKernel(
01483 rowMap_, isBCRow_, lowestRow_,
01484 mv, partitionBCs_, 0));
01485
01486 assemblyLoop(VectorOnly, kernel);
01487
01488 SUNDANCE_MSG1(verb, tab << "Assembler: done assembling vector");
01489 }
01490
01491
01492
01493
01494 void Assembler::evaluate(double& value, Array<Vector<double> >& gradient) const
01495 {
01496 Tabs tab;
01497 TimeMonitor timer(assemblyTimer());
01498 int verb = 0;
01499 if (eqn_->hasActiveWatchFlag()) verb = max(verb, 1);
01500
01501 SUNDANCE_BANNER1(verb, tab, "Computing functional and gradient");
01502
01503 TEUCHOS_TEST_FOR_EXCEPTION(!contexts_.containsKey(FunctionalAndGradient),
01504 std::runtime_error,
01505 "Assembler::evaluate(f,df) called for an assembler that "
01506 "does not support value/gradient assembly");
01507
01508 configureVector(gradient);
01509
01510 value = 0.0;
01511
01512 RCP<AssemblyKernelBase> kernel
01513 = rcp(new FunctionalGradientAssemblyKernel(
01514 mesh_.comm(),
01515 rowMap_, isBCRow_, lowestRow_,
01516 gradient, partitionBCs_, &value, verb));
01517
01518 assemblyLoop(FunctionalAndGradient, kernel);
01519
01520 SUNDANCE_BANNER1(verb, tab, "Done computing functional and gradient");
01521
01522 }
01523
01524
01525
01526
01527
01528
01529 void Assembler::evaluate(double& value) const
01530 {
01531 Tabs tab;
01532 TimeMonitor timer(assemblyTimer());
01533 int verb = 0;
01534 if (eqn_->hasActiveWatchFlag()) verb = max(verb, 1);
01535
01536 SUNDANCE_BANNER1(verb, tab, "Computing functional");
01537
01538 TEUCHOS_TEST_FOR_EXCEPTION(!contexts_.containsKey(FunctionalOnly),
01539 std::runtime_error,
01540 "Assembler::evaluate(f) called for an assembler that "
01541 "does not support functional evaluation");
01542
01543 value = 0.0;
01544
01545 RCP<AssemblyKernelBase> kernel
01546 = rcp(new FunctionalAssemblyKernel(mesh_.comm(), &value, verb));
01547
01548 assemblyLoop(FunctionalOnly, kernel);
01549
01550 SUNDANCE_BANNER1(verb, tab, "Done computing functional");
01551 }
01552
01553
01554
01555
01556
01557
01558
01559 void Assembler::getGraph(int br, int bc,
01560 Array<int>& graphData,
01561 Array<int>& rowPtrs,
01562 Array<int>& nnzPerRow) const
01563 {
01564 TimeMonitor timer(graphBuildTimer());
01565 Tabs tab;
01566 int verb = eqn_->maxWatchFlagSetting("matrix config");
01567
01568
01569 RCP<Array<int> > workSet = rcp(new Array<int>());
01570 workSet->reserve(workSetSize());
01571
01572 RCP<Array<Array<int> > > testLocalDOFs
01573 = rcp(new Array<Array<int> >());
01574
01575 RCP<Array<Array<int> > > unkLocalDOFs
01576 = rcp(new Array<Array<int> >());
01577
01578 SUNDANCE_MSG3(verb, tab << "Creating graph: there are "
01579 << rowMap_[br]->numLocalDOFs()
01580 << " local equations");
01581
01582
01583 Array<Set<int> > tmpGraph;
01584 tmpGraph.resize(rowMap_[br]->numLocalDOFs());
01585
01586 {
01587 TimeMonitor timer2(colSearchTimer());
01588 for (int d=0; d<eqn_->numRegions(); d++)
01589 {
01590 Tabs tab0;
01591 CellFilter domain = eqn_->region(d);
01592 const Array<Set<int> >& requiredVars = eqn_->reducedVarsOnRegion(domain);
01593 const Array<Set<int> >& requiredUnks = eqn_->reducedUnksOnRegion(domain);
01594 SUNDANCE_MSG2(verb,
01595 tab0 << "cell set " << domain
01596 << " isBCRegion=" << eqn_->isBCRegion(d));
01597 int dim = domain.dimension(mesh_);
01598 CellSet cells = domain.getCells(mesh_);
01599
01600 RCP<Set<OrderedPair<int, int> > > pairs ;
01601 if (eqn_->hasVarUnkPairs(domain)) pairs = eqn_->varUnkPairs(domain);
01602
01603 SUNDANCE_OUT(verb > 2 && pairs.get() != 0,
01604 tab0 << "non-BC pairs = "
01605 << *pairs);
01606
01607 RCP<Set<OrderedPair<int, int> > > bcPairs ;
01608 if (eqn_->isBCRegion(d))
01609 {
01610 if (eqn_->hasBCVarUnkPairs(domain))
01611 {
01612 bcPairs = eqn_->bcVarUnkPairs(domain);
01613 SUNDANCE_OUT(verb > 2, tab0 << "BC pairs = "
01614 << *bcPairs);
01615 }
01616 }
01617 Array<Set<int> > unksForTestsSet(eqn_->numVarIDs(bc));
01618 Array<Set<int> > bcUnksForTestsSet(eqn_->numVarIDs(bc));
01619
01620 Set<OrderedPair<int, int> >::const_iterator i;
01621
01622 if (pairs.get() != 0)
01623 {
01624 for (i=pairs->begin(); i!=pairs->end(); i++)
01625 {
01626 const OrderedPair<int, int>& p = *i;
01627 int t = p.first();
01628 int u = p.second();
01629
01630 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
01631 "Test function ID " << t << " does not appear "
01632 "in equation set");
01633 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
01634 "Unk function ID " << u << " does not appear "
01635 "in equation set");
01636
01637 if (eqn_->blockForVarID(t) != br) continue;
01638 if (eqn_->blockForUnkID(u) != bc) continue;
01639
01640 unksForTestsSet[eqn_->reducedVarID(t)].put(eqn_->reducedUnkID(u));
01641 }
01642 }
01643 if (bcPairs.get() != 0)
01644 {
01645 for (i=bcPairs->begin(); i!=bcPairs->end(); i++)
01646 {
01647 const OrderedPair<int, int>& p = *i;
01648 int t = p.first();
01649 int u = p.second();
01650
01651 if (eqn_->blockForVarID(t) != br) continue;
01652 if (eqn_->blockForUnkID(u) != bc) continue;
01653
01654 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
01655 "Test function ID " << t << " does not appear "
01656 "in equation set");
01657 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
01658 "Unk function ID " << u << " does not appear "
01659 "in equation set");
01660 bcUnksForTestsSet[eqn_->reducedVarID(t)].put(eqn_->reducedUnkID(u));
01661 }
01662 }
01663
01664 Array<Array<int> > unksForTests(unksForTestsSet.size());
01665 Array<Array<int> > bcUnksForTests(bcUnksForTestsSet.size());
01666
01667 for (int t=0; t<unksForTests.size(); t++)
01668 {
01669 unksForTests[t] = unksForTestsSet[t].elements();
01670 bcUnksForTests[t] = bcUnksForTestsSet[t].elements();
01671 }
01672
01673 Array<int> numTestNodes;
01674 Array<int> numUnkNodes;
01675
01676
01677
01678 int highestRow = lowestRow_[br] + rowMap_[br]->numLocalDOFs();
01679
01680 int nt = eqn_->numVarIDs(br);
01681
01682 CellIterator iter=cells.begin();
01683 while (iter != cells.end())
01684 {
01685
01686 workSet->resize(0);
01687 for (int c=0; c<workSetSize() && iter != cells.end(); c++, iter++)
01688 {
01689 workSet->append(*iter);
01690 }
01691
01692 int nCells = workSet->size();
01693
01694 RCP<const MapStructure> colMapStruct;
01695 RCP<const MapStructure> rowMapStruct
01696 = rowMap_[br]->getDOFsForCellBatch(dim, *workSet,
01697 requiredVars[br], *testLocalDOFs,
01698 numTestNodes, verb);
01699 if (rowMap_[br].get()==colMap_[bc].get())
01700 {
01701 unkLocalDOFs = testLocalDOFs;
01702 numUnkNodes = numTestNodes;
01703 colMapStruct = rowMapStruct;
01704 }
01705 else
01706 {
01707 colMapStruct = colMap_[br]->getDOFsForCellBatch(dim, *workSet,
01708 requiredUnks[bc],
01709 *unkLocalDOFs, numUnkNodes, verb);
01710 }
01711
01712 if (pairs.get() != 0)
01713 {
01714 for (int c=0; c<nCells; c++)
01715 {
01716 for (int t=0; t<nt; t++)
01717 {
01718 int tChunk = rowMapStruct->chunkForFuncID(t);
01719 int nTestFuncs = rowMapStruct->numFuncs(tChunk);
01720 int testFuncIndex = rowMapStruct->indexForFuncID(t);
01721 int nTestNodes = numTestNodes[tChunk];
01722 const Array<int>& testDOFs = (*testLocalDOFs)[tChunk];
01723 for (int uit=0; uit<unksForTests[t].size(); uit++)
01724 {
01725 Tabs tab2;
01726 int u = unksForTests[t][uit];
01727 int uChunk = colMapStruct->chunkForFuncID(u);
01728 int nUnkFuncs = colMapStruct->numFuncs(uChunk);
01729 int unkFuncIndex = colMapStruct->indexForFuncID(u);
01730 const Array<int>& unkDOFs = (*unkLocalDOFs)[uChunk];
01731 int nUnkNodes = numUnkNodes[uChunk];
01732 for (int n=0; n<nTestNodes; n++)
01733 {
01734 int row
01735 = testDOFs[(c*nTestFuncs + testFuncIndex)*nTestNodes + n];
01736 if (row < lowestRow_[br] || row >= highestRow
01737 || (*(isBCRow_[br]))[row-lowestRow_[br]]) continue;
01738 Set<int>& colSet = tmpGraph[row-lowestRow_[br]];
01739 for (int m=0; m<nUnkNodes; m++)
01740 {
01741 int col
01742 = unkDOFs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes + m];
01743 colSet.put(col);
01744 }
01745 }
01746 }
01747 }
01748 }
01749 }
01750 if (bcPairs.get() != 0)
01751 {
01752 for (int c=0; c<nCells; c++)
01753 {
01754 for (int t=0; t<nt; t++)
01755 {
01756 int tChunk = rowMapStruct->chunkForFuncID(t);
01757 int nTestFuncs = rowMapStruct->numFuncs(tChunk);
01758 int testFuncIndex = rowMapStruct->indexForFuncID(t);
01759 int nTestNodes = numTestNodes[tChunk];
01760 const Array<int>& testDOFs = (*testLocalDOFs)[tChunk];
01761 for (int uit=0; uit<bcUnksForTests[t].size(); uit++)
01762 {
01763 Tabs tab2;
01764 int u = bcUnksForTests[t][uit];
01765 int uChunk = colMapStruct->chunkForFuncID(u);
01766 int nUnkFuncs = colMapStruct->numFuncs(uChunk);
01767 int unkFuncIndex = colMapStruct->indexForFuncID(u);
01768 const Array<int>& unkDOFs = (*unkLocalDOFs)[uChunk];
01769 int nUnkNodes = numUnkNodes[uChunk];
01770 for (int n=0; n<nTestNodes; n++)
01771 {
01772 int row
01773 = testDOFs[(c*nTestFuncs + testFuncIndex)*nTestNodes + n];
01774 if (row < lowestRow_[br] || row >= highestRow
01775 || !(*(isBCRow_[br]))[row-lowestRow_[br]]) continue;
01776 Set<int>& colSet = tmpGraph[row-lowestRow_[br]];
01777 for (int m=0; m<nUnkNodes; m++)
01778 {
01779 int col
01780 = unkDOFs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes + m];
01781 colSet.put(col);
01782 }
01783 }
01784 }
01785 }
01786 }
01787 }
01788 }
01789 }
01790 }
01791
01792
01793 {
01794 TimeMonitor t2(graphFlatteningTimer());
01795 int nLocalRows = rowMap_[br]->numLocalDOFs();
01796
01797 int nnz = 0;
01798 rowPtrs.resize(nLocalRows);
01799 nnzPerRow.resize(rowMap_[br]->numLocalDOFs());
01800 for (int i=0; i<nLocalRows; i++)
01801 {
01802 rowPtrs[i] = nnz;
01803 nnzPerRow[i] = tmpGraph[i].size();
01804 nnz += nnzPerRow[i];
01805 }
01806
01807 graphData.resize(nnz);
01808 int* base = &(graphData[0]);
01809 for (int i=0; i<nLocalRows; i++)
01810 {
01811
01812 int* rowBase = base + rowPtrs[i];
01813 const Set<int>& rowSet = tmpGraph[i];
01814 int k = 0;
01815 for (Set<int>::const_iterator
01816 j=rowSet.begin(); j != rowSet.end(); j++, k++)
01817 {
01818 rowBase[k] = *j;
01819 }
01820 }
01821 }
01822
01823 }
01824
01825
01826
01827 void Assembler
01828 ::incrementalGetGraph(int br, int bc,
01829 IncrementallyConfigurableMatrixFactory* icmf) const
01830 {
01831 TimeMonitor timer(graphBuildTimer());
01832 Tabs tab;
01833 int verb = eqn_->maxWatchFlagSetting("matrix config");
01834
01835 RCP<Array<int> > workSet = rcp(new Array<int>());
01836 workSet->reserve(workSetSize());
01837
01838 RCP<Array<Array<int> > > testLocalDOFs
01839 = rcp(new Array<Array<int> >());
01840
01841 RCP<Array<Array<int> > > unkLocalDOFs
01842 = rcp(new Array<Array<int> >());
01843
01844 SUNDANCE_MSG2(verb, tab << "Creating graph: there are "
01845 << rowMap_[br]->numLocalDOFs()
01846 << " local equations");
01847
01848
01849 for (int d=0; d<eqn_->numRegions(); d++)
01850 {
01851 Tabs tab0;
01852 CellFilter domain = eqn_->region(d);
01853 const Array<Set<int> >& requiredVars = eqn_->reducedVarsOnRegion(domain);
01854 const Array<Set<int> >& requiredUnks = eqn_->reducedUnksOnRegion(domain);
01855 Array<int> localVars = requiredVars[br].elements();
01856 Array<int> localUnks = requiredUnks[bc].elements();
01857 SUNDANCE_MSG3(verb,
01858 tab0 << "cell set " << domain
01859 << " isBCRegion=" << eqn_->isBCRegion(d));
01860 int dim = domain.dimension(mesh_);
01861 CellSet cells = domain.getCells(mesh_);
01862
01863 RCP<Set<OrderedPair<int, int> > > pairs ;
01864 if (eqn_->hasVarUnkPairs(domain)) pairs = eqn_->varUnkPairs(domain);
01865
01866 SUNDANCE_OUT(verb > 2 && pairs.get() != 0,
01867 tab0 << "non-BC pairs = "
01868 << *pairs);
01869
01870 RCP<Set<OrderedPair<int, int> > > bcPairs ;
01871 if (eqn_->isBCRegion(d))
01872 {
01873 if (eqn_->hasBCVarUnkPairs(domain))
01874 {
01875 bcPairs = eqn_->bcVarUnkPairs(domain);
01876 SUNDANCE_MSG3(verb, tab0 << "BC pairs = "
01877 << *bcPairs);
01878 }
01879 }
01880 Array<Set<int> > unksForTestsSet(eqn_->numVarIDs(br));
01881 Array<Set<int> > bcUnksForTestsSet(eqn_->numVarIDs(br));
01882
01883 Set<OrderedPair<int, int> >::const_iterator i;
01884
01885 if (pairs.get() != 0)
01886 {
01887 for (i=pairs->begin(); i!=pairs->end(); i++)
01888 {
01889 const OrderedPair<int, int>& p = *i;
01890 int t = p.first();
01891 int u = p.second();
01892
01893 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
01894 "Test function ID " << t << " does not appear "
01895 "in equation set");
01896 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
01897 "Unk function ID " << u << " does not appear "
01898 "in equation set");
01899
01900
01901 if (eqn_->blockForVarID(t) != br) continue;
01902 if (eqn_->blockForUnkID(u) != bc) continue;
01903
01904 unksForTestsSet[eqn_->reducedVarID(t)].put(eqn_->reducedUnkID(u));
01905 }
01906 }
01907 if (bcPairs.get() != 0)
01908 {
01909 for (i=bcPairs->begin(); i!=bcPairs->end(); i++)
01910 {
01911 const OrderedPair<int, int>& p = *i;
01912 int t = p.first();
01913 int u = p.second();
01914 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
01915 "Test function ID " << t << " does not appear "
01916 "in equation set");
01917 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
01918 "Unk function ID " << u << " does not appear "
01919 "in equation set");
01920
01921 if (eqn_->blockForVarID(t) != br) continue;
01922 if (eqn_->blockForUnkID(u) != bc) continue;
01923
01924 bcUnksForTestsSet[eqn_->reducedVarID(t)].put(eqn_->reducedUnkID(u));
01925 }
01926 }
01927
01928 Array<Array<int> > unksForTests(unksForTestsSet.size());
01929 Array<Array<int> > bcUnksForTests(bcUnksForTestsSet.size());
01930
01931 for (int t=0; t<unksForTests.size(); t++)
01932 {
01933 unksForTests[t] = unksForTestsSet[t].elements();
01934 bcUnksForTests[t] = bcUnksForTestsSet[t].elements();
01935 }
01936
01937 Array<int> numTestNodes;
01938 Array<int> numUnkNodes;
01939
01940 int highestRow = lowestRow_[br] + rowMap_[br]->numLocalDOFs();
01941
01942 CellIterator iter=cells.begin();
01943
01944 while (iter != cells.end())
01945 {
01946
01947 workSet->resize(0);
01948 for (int c=0; c<workSetSize() && iter != cells.end(); c++, iter++)
01949 {
01950 workSet->append(*iter);
01951 }
01952
01953 int nCells = workSet->size();
01954
01955 RCP<const MapStructure> colMapStruct;
01956 RCP<const MapStructure> rowMapStruct
01957 = rowMap_[br]->getDOFsForCellBatch(dim, *workSet,
01958 requiredVars[br],
01959 *testLocalDOFs,
01960 numTestNodes, verb);
01961
01962 if (rowMap_[br].get()==colMap_[bc].get())
01963 {
01964 unkLocalDOFs = testLocalDOFs;
01965 numUnkNodes = numTestNodes;
01966 colMapStruct = rowMapStruct;
01967 }
01968 else
01969 {
01970 colMapStruct = colMap_[bc]->getDOFsForCellBatch(dim, *workSet,
01971 requiredUnks[bc],
01972 *unkLocalDOFs, numUnkNodes, verb);
01973 }
01974
01975
01976 if (pairs.get() != 0)
01977 {
01978 for (int c=0; c<nCells; c++)
01979 {
01980 for (int tIndex=0; tIndex<localVars.size(); tIndex++)
01981 {
01982 int t = localVars[tIndex];
01983 int tChunk = rowMapStruct->chunkForFuncID(t);
01984 int nTestFuncs = rowMapStruct->numFuncs(tChunk);
01985 int testFuncIndex = rowMapStruct->indexForFuncID(t);
01986 int nTestNodes = numTestNodes[tChunk];
01987 const Array<int>& testDOFs = (*testLocalDOFs)[tChunk];
01988 for (int uit=0; uit<unksForTests[t].size(); uit++)
01989 {
01990 Tabs tab2;
01991 int u = unksForTests[t][uit];
01992 int uChunk = colMapStruct->chunkForFuncID(u);
01993 int nUnkFuncs = colMapStruct->numFuncs(uChunk);
01994 int unkFuncIndex = colMapStruct->indexForFuncID(u);
01995 const Array<int>& unkDOFs = (*unkLocalDOFs)[uChunk];
01996 int nUnkNodes = numUnkNodes[uChunk];
01997 for (int n=0; n<nTestNodes; n++)
01998 {
01999 int row
02000 = testDOFs[(c*nTestFuncs + testFuncIndex)*nTestNodes + n];
02001 if (row < lowestRow_[br] || row >= highestRow
02002 || (*(isBCRow_[br]))[row-lowestRow_[br]]) continue;
02003 const int* colPtr = &(unkDOFs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes]);
02004 icmf->initializeNonzerosInRow(row, nUnkNodes, colPtr);
02005 }
02006 }
02007 }
02008 }
02009 }
02010 if (bcPairs.get() != 0)
02011 {
02012 for (int c=0; c<nCells; c++)
02013 {
02014 for (int tIndex=0; tIndex<localVars.size(); tIndex++)
02015 {
02016 int t = localVars[tIndex];
02017 int tChunk = rowMapStruct->chunkForFuncID(t);
02018 int nTestFuncs = rowMapStruct->numFuncs(tChunk);
02019 int testFuncIndex = rowMapStruct->indexForFuncID(t);
02020 int nTestNodes = numTestNodes[tChunk];
02021 const Array<int>& testDOFs = (*testLocalDOFs)[tChunk];
02022 for (int uit=0; uit<bcUnksForTests[t].size(); uit++)
02023 {
02024 Tabs tab2;
02025 int u = bcUnksForTests[t][uit];
02026 int uChunk = colMapStruct->chunkForFuncID(u);
02027 int nUnkFuncs = colMapStruct->numFuncs(uChunk);
02028 int unkFuncIndex = colMapStruct->indexForFuncID(u);
02029 const Array<int>& unkDOFs = (*unkLocalDOFs)[uChunk];
02030 int nUnkNodes = numUnkNodes[uChunk];
02031 for (int n=0; n<nTestNodes; n++)
02032 {
02033 int row
02034 = testDOFs[(c*nTestFuncs + testFuncIndex)*nTestNodes + n];
02035 if (row < lowestRow_[br] || row >= highestRow
02036 || !(*(isBCRow_[br]))[row-lowestRow_[br]]) continue;
02037
02038 const int* colPtr = &(unkDOFs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes]);
02039 icmf->initializeNonzerosInRow(row, nUnkNodes, colPtr);
02040 }
02041 }
02042 }
02043 }
02044 }
02045 }
02046 }
02047 }
02048
02049
02050 Array<Array<int> > Assembler::findNonzeroBlocks() const
02051 {
02052 int verb = eqn_->maxWatchFlagSetting("assembler setup");
02053
02054 Array<Array<int> > rtn(eqn_->numVarBlocks());
02055 for (int br=0; br<rtn.size(); br++)
02056 {
02057 rtn[br].resize(eqn_->numUnkBlocks());
02058 for (int bc=0; bc<rtn[br].size(); bc++)
02059 {
02060 rtn[br][bc] = 0 ;
02061 }
02062 }
02063
02064 for (int d=0; d<eqn_->numRegions(); d++)
02065 {
02066 Tabs tab0;
02067 CellFilter domain = eqn_->region(d);
02068 SUNDANCE_MSG3(verb,
02069 tab0 << "cell set " << domain
02070 << " isBCRegion=" << eqn_->isBCRegion(d));
02071
02072 RCP<Set<OrderedPair<int, int> > > pairs ;
02073 if (eqn_->hasVarUnkPairs(domain)) pairs = eqn_->varUnkPairs(domain);
02074
02075 SUNDANCE_OUT(verb > 2 && pairs.get() != 0,
02076 tab0 << "non-BC pairs = "
02077 << *pairs);
02078
02079 RCP<Set<OrderedPair<int, int> > > bcPairs ;
02080 if (eqn_->isBCRegion(d))
02081 {
02082 if (eqn_->hasBCVarUnkPairs(domain))
02083 {
02084 bcPairs = eqn_->bcVarUnkPairs(domain);
02085 SUNDANCE_MSG3(verb, tab0 << "BC pairs = "
02086 << *bcPairs);
02087 }
02088 }
02089
02090 Set<OrderedPair<int, int> >::const_iterator i;
02091
02092 if (pairs.get() != 0)
02093 {
02094 for (i=pairs->begin(); i!=pairs->end(); i++)
02095 {
02096 const OrderedPair<int, int>& p = *i;
02097 int t = p.first();
02098 int u = p.second();
02099
02100 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
02101 "Test function ID " << t << " does not appear "
02102 "in equation set");
02103 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
02104 "Unk function ID " << u << " does not appear "
02105 "in equation set");
02106
02107
02108 int br = eqn_->blockForVarID(t);
02109 int bc = eqn_->blockForUnkID(u);
02110 rtn[br][bc] = 1;
02111 }
02112 }
02113 if (bcPairs.get() != 0)
02114 {
02115 for (i=bcPairs->begin(); i!=bcPairs->end(); i++)
02116 {
02117 const OrderedPair<int, int>& p = *i;
02118 int t = p.first();
02119 int u = p.second();
02120 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasVarID(t), std::logic_error,
02121 "Test function ID " << t << " does not appear "
02122 "in equation set");
02123 TEUCHOS_TEST_FOR_EXCEPTION(!eqn_->hasUnkID(u), std::logic_error,
02124 "Unk function ID " << u << " does not appear "
02125 "in equation set");
02126 int br = eqn_->blockForVarID(t);
02127 int bc = eqn_->blockForUnkID(u);
02128 rtn[br][bc] = 1;
02129 }
02130 }
02131 }
02132
02133 return rtn;
02134 }
02135
02136 VectorSpace<double> Assembler::solnVecSpace() const
02137 {
02138 Array<VectorSpace<double> > rtn(eqn_->numUnkBlocks());
02139
02140 for (int i=0; i<rtn.size(); i++)
02141 {
02142 rtn[i] = solutionSpace()[i]->vecSpace();
02143 }
02144
02145 if ((int) rtn.size() == 1)
02146 {
02147 return rtn[0];
02148 }
02149 return blockSpace(rtn);
02150 }
02151
02152
02153 VectorSpace<double> Assembler::rowVecSpace() const
02154 {
02155 Array<VectorSpace<double> > rtn(eqn_->numVarBlocks());
02156
02157 for (int i=0; i<rtn.size(); i++)
02158 {
02159 rtn[i] = rowSpace()[i]->vecSpace();
02160 }
02161
02162 if ((int) rtn.size() == 1)
02163 {
02164 return rtn[0];
02165 }
02166 return blockSpace(rtn);
02167 }
02168
02169
02170
02171 int& Assembler::workSetSize()
02172 {
02173 static int rtn = defaultWorkSetSize();
02174 return rtn;
02175 }
02176
02177 int Assembler::maxWatchFlagSetting(const std::string& name) const
02178 {
02179 return eqnSet()->maxWatchFlagSetting(name);
02180 }
02181
02182 bool Assembler::matNeedsConfiguration() const
02183 {
02184 return Teuchos::is_null(cachedAssembledMatrix_.ptr());
02185 }
02186
02187
02188 void Assembler::flushConfiguration() const
02189 {
02190 numConfiguredColumns_ = 0;
02191 cachedAssembledMatrix_ = LinearOperator<double>();
02192 mesh_.flushSpecialWeights();
02193 mesh_.flushCurvePoints();
02194
02195
02196 for (int r=0; r<rqc_.size(); r++)
02197 {
02198 const CellFilter filter = rqc_[r].domain();
02199 filter.cfbPtr()->flushCache();
02200 }
02201 }