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 "SundanceOut.hpp"
00032 #include "PlayaTabs.hpp"
00033 #include "SundanceMatrixVectorAssemblyKernel.hpp"
00034 #include "PlayaSimpleZeroOpDecl.hpp"
00035
00036
00037
00038
00039
00040
00041 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00042 #include "PlayaSimpleZeroOpImpl.hpp"
00043 #include "PlayaVectorImpl.hpp"
00044 #endif
00045
00046 using namespace Sundance;
00047 using namespace Sundance;
00048 using namespace Sundance;
00049 using namespace Teuchos;
00050 using namespace Playa;
00051 using std::setw;
00052 using std::setprecision;
00053 using std::ios_base;
00054 using std::endl;
00055
00056
00057
00058 void MatrixVectorAssemblyKernel::init(
00059 const Array<RCP<DOFMapBase> >& rowMap,
00060 const Array<RCP<DOFMapBase> >& colMap,
00061 LinearOperator<double> A,
00062 bool partitionBCs)
00063 {
00064 Tabs tab;
00065 SUNDANCE_MSG2(verb(), tab << "begin MVAssemblyKernel::init()");
00066
00067 int numRowBlocks = rowMap.size();
00068 int numColBlocks = colMap.size();
00069
00070 for (int br=0; br<numRowBlocks; br++)
00071 {
00072 Vector<double> vecBlock;
00073
00074 mat_[br].resize(numColBlocks);
00075 for (int bc=0; bc<numColBlocks; bc++)
00076 {
00077 Tabs tab1;
00078 LinearOperator<double> matBlock;
00079 if (partitionBCs && numRowBlocks==1 && numColBlocks==1)
00080 {
00081 matBlock = A;
00082 }
00083 else
00084 {
00085 matBlock = A.getBlock(br, bc);
00086 }
00087 if (matBlock.ptr().get() == 0) continue;
00088 const SimpleZeroOp<double>* zp
00089 = dynamic_cast<const SimpleZeroOp<double>*>(matBlock.ptr().get());
00090 if (zp)
00091 {
00092 SUNDANCE_MSG3(verb(), tab1 << "block(br=" << br << ", "
00093 << bc << ") is zero");
00094 TEUCHOS_TEST_FOR_EXCEPTION(numRowBlocks==1 && numColBlocks==1 && zp,
00095 std::runtime_error, "no nonzero block in target matrix");
00096 continue;
00097 }
00098 mat_[br][bc]
00099 = dynamic_cast<Playa::LoadableMatrix<double>* >(matBlock.ptr().get());
00100 TEUCHOS_TEST_FOR_EXCEPTION(mat_[br][bc]==0, std::runtime_error,
00101 "matrix block (" << br << ", " << bc
00102 << ") is not loadable in Assembler::assemble()");
00103 mat_[br][bc]->zero();
00104 }
00105 }
00106 SUNDANCE_MSG2(verb(), tab << "end MVAssemblyKernel::init()");
00107 }
00108
00109
00110
00111 void MatrixVectorAssemblyKernel::fill(
00112 bool isBC,
00113 const IntegralGroup& group,
00114 const RCP<Array<double> >& localValues)
00115 {
00116 Tabs tab0;
00117 SUNDANCE_MSG1(verb(), tab0 << "in MatrixVectorAssemblyKernel::fill()");
00118 SUNDANCE_MSG1(verb(), tab0 << "filling for integral group " << group.derivs());
00119
00120 bool useCofacets = group.usesMaximalCofacets();
00121
00122 if (group.isOneForm())
00123 {
00124 Tabs tab1;
00125 SUNDANCE_MSG2(verb(), tab1 << "group is one form");
00126 insertLocalVectorBatch(isBC, useCofacets,
00127 group.testID(), group.testBlock(), group.mvIndices(),
00128 *localValues);
00129 }
00130 else if (group.isTwoForm())
00131 {
00132 Tabs tab1;
00133 SUNDANCE_MSG2(verb(), tab1 << "group is two form");
00134 insertLocalMatrixBatch(isBC, useCofacets,
00135 group.testID(), group.testBlock(),
00136 group.unkID(), group.unkBlock(),
00137 *localValues);
00138 }
00139 else
00140 {
00141 Tabs tab1;
00142 SUNDANCE_MSG2(verb(), tab1 << "is zero form -- nothing to do here");
00143 }
00144
00145 SUNDANCE_MSG1(verb(), tab0 << "done MatrixVectorAssemblyKernel::fill()");
00146 }
00147
00148
00149 void MatrixVectorAssemblyKernel::prepareForWorkSet(
00150 const Array<Set<int> >& requiredTests,
00151 const Array<Set<int> >& requiredUnks,
00152 RCP<StdFwkEvalMediator> mediator)
00153 {
00154 Tabs tab0;
00155 SUNDANCE_MSG1(verb(), tab0
00156 << "in MatrixVectorAssemblyKernel::prepareForWorkSet()");
00157
00158 IntegrationCellSpecifier intCellSpec = mediator->integrationCellSpec();
00159 SUNDANCE_MSG2(verb(), tab0
00160 << "integration cell specifier is " << intCellSpec);
00161
00162 SUNDANCE_MSG2(verb(), tab0 << "building row DOF maps");
00163 buildLocalDOFMaps(mediator, intCellSpec, requiredTests);
00164
00165 SUNDANCE_MSG2(verb(), tab0 << "building column DOF maps");
00166 cmb_.buildLocalDOFMaps(mediator, intCellSpec, requiredUnks, verb());
00167
00168 SUNDANCE_MSG1(verb(), tab0 << "done MatrixVectorAssemblyKernel::prepareForWorkSet()");
00169 }
00170
00171
00172 void MatrixVectorAssemblyKernel::insertLocalMatrixBatch(
00173 bool isBCRqc,
00174 bool useCofacetCells,
00175 const Array<int>& testID,
00176 const Array<int>& testBlock,
00177 const Array<int>& unkID,
00178 const Array<int>& unkBlock,
00179 const Array<double>& localValues) const
00180 {
00181 Tabs tab;
00182
00183 SUNDANCE_MSG1(verb(), tab << "inserting local matrices");
00184
00185 static Array<int> skipRow;
00186 static Array<int> rows;
00187 static Array<int> cols;
00188
00189 int nCells = rmb().nCells();
00190
00191 for (int t=0; t<testID.size(); t++)
00192 {
00193 Tabs tab1;
00194 int br = testBlock[t];
00195
00196 SUNDANCE_MSG3(verb(), tab1 << "block row = " << br
00197 << tab1 << "function ID = "<< testID[t]
00198 << " of " << testID.size() << std::endl
00199 << tab1 << "is BC eqn = " << isBCRqc << std::endl
00200 << tab1 << "num cells = " << nCells << std::endl
00201 << tab1 << "using cofacet cells = " << useCofacetCells);
00202 SUNDANCE_MSG3(verb(), tab1 << "local values=" << localValues);
00203
00204 const RCP<DOFMapBase>& rowMap = rmb().dofMap(br);
00205 int lowestLocalRow = rmb().lowestLocalIndex(br);
00206 int highestRowIndex = lowestLocalRow + rowMap->numLocalDOFs();
00207 int testChunk = rmb().mapStruct(br,
00208 useCofacetCells)->chunkForFuncID(testID[t]);
00209 int testFuncIndex = rmb().mapStruct(br,
00210 useCofacetCells)->indexForFuncID(testID[t]);
00211 const Array<int>& testDofs = rmb().localDOFs(br, useCofacetCells, testChunk);
00212 int nTestFuncs = rmb().mapStruct(br, useCofacetCells)->numFuncs(testChunk);
00213 int nTestNodes = rmb().nNodesInChunk(br, useCofacetCells, testChunk);
00214
00215 SUNDANCE_MSG3(verb(), tab1 << "lowestLocalRow = " << lowestLocalRow << std::endl
00216 << tab1 << "test chunk = " << testChunk << std::endl
00217 << tab1 << "func offset into local DOF map = "
00218 << testFuncIndex << std::endl
00219 << tab1 << "local test dofs = " << testDofs << std::endl
00220 << tab1 << "num test funcs in chunk = " << nTestFuncs << std::endl
00221 << tab1 << "num test nodes in chunk = " << nTestNodes);
00222
00223 int numRows = nCells * nTestNodes;
00224 SUNDANCE_MSG3(verb(), tab1 << "numRows=" << numRows);
00225 const Array<int>& isBCRow = *(rmb().isBCIndex(br));
00226 rows.resize(numRows);
00227 skipRow.resize(numRows);
00228 int r=0;
00229 for (int c=0; c<nCells; c++)
00230 {
00231 for (int n=0; n<nTestNodes; n++, r++)
00232 {
00233 int row = testDofs[(c*nTestFuncs + testFuncIndex)*nTestNodes + n];
00234 rows[r] = row;
00235 int localRow = rows[r]-lowestLocalRow;
00236 skipRow[r] = row < lowestLocalRow || row >= highestRowIndex
00237 || (isBCRqc && !isBCRow[localRow])
00238 || (!isBCRqc && isBCRow[localRow]);
00239 }
00240 }
00241
00242 SUNDANCE_MSG3(verb(), tab1 << "rows=" << rows);
00243 SUNDANCE_MSG3(verb(), tab1 << "skipRow=" << skipRow);
00244 for (int u=0; u<unkID.size(); u++)
00245 {
00246 Tabs tab2;
00247 int bc = unkBlock[u];
00248
00249 int lowestLocalCol = cmb().lowestLocalIndex(bc);
00250 int unkChunk = cmb().mapStruct(bc,
00251 useCofacetCells)->chunkForFuncID(unkID[u]);
00252 int unkFuncIndex = cmb().mapStruct(bc,
00253 useCofacetCells)->indexForFuncID(unkID[u]);
00254 const Array<int>& unkDofs = cmb().localDOFs(bc, useCofacetCells, unkChunk);
00255 int nUnkFuncs = cmb().mapStruct(bc, useCofacetCells)->numFuncs(unkChunk);
00256 int nUnkNodes = cmb().nNodesInChunk(bc, useCofacetCells, unkChunk);
00257
00258
00259 SUNDANCE_MSG3(verb(), tab2 << "lowestLocalCol = "
00260 << lowestLocalCol << std::endl
00261 << tab2 << "block col = " << bc << std::endl
00262 << tab2 << "unk ID = "<< unkID[t]
00263 << " of " << unkID.size() << std::endl
00264 << tab2 << "unk chunk = " << unkChunk << std::endl
00265 << tab2 << "func offset into local DOF map = "
00266 << unkFuncIndex << std::endl
00267 << tab2 << "local unk dofs = " << unkDofs << std::endl
00268 << tab2 << "num unk funcs in chunk = " << nUnkFuncs << std::endl
00269 << tab2 << "num unk nodes in chunk = " << nUnkNodes);
00270
00271 cols.resize(nCells*nUnkNodes);
00272
00273 int j=0;
00274 for (int c=0; c<nCells; c++)
00275 {
00276 for (int n=0; n<nUnkNodes; n++, j++)
00277 {
00278 cols[j] = unkDofs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes + n];
00279 }
00280 }
00281
00282 if (verb() >= 3)
00283 {
00284 writeLSMs(br, bc, useCofacetCells,
00285 nTestNodes, nTestFuncs, testFuncIndex, testDofs,
00286 nUnkNodes, nUnkFuncs, unkFuncIndex, unkDofs, localValues);
00287 }
00288
00289 SUNDANCE_MSG2(verb(), tab2 << "calling addToElementBatch()");
00290 TEUCHOS_TEST_FOR_EXCEPT(mat_[br][bc]==0);
00291 mat_[br][bc]->addToElementBatch(numRows,
00292 nTestNodes,
00293 &(rows[0]),
00294 nUnkNodes,
00295 &(cols[0]),
00296 &(localValues[0]),
00297 &(skipRow[0]));
00298 SUNDANCE_MSG2(verb(), tab2 << "done calling addToElementBatch()");
00299 }
00300 }
00301
00302 SUNDANCE_MSG1(verb(), tab << "done inserting local matrices");
00303 }
00304
00305
00306 void MatrixVectorAssemblyKernel::writeLSMs(
00307 int blockRow,
00308 int blockCol,
00309 bool useCofacetCells,
00310 int nTestNodes,
00311 int nTestFuncs,
00312 int testFuncIndex,
00313 const Array<int>& testDofs,
00314 int nUnkNodes,
00315 int nUnkFuncs,
00316 int unkFuncIndex,
00317 const Array<int>& unkDofs,
00318 const Array<double>& localValues) const
00319 {
00320 FancyOStream& os = Out::os();
00321
00322 int nCells = rmb().nCells();
00323
00324 RCP<const Array<int> > workSet = rmb().workSet(blockRow, useCofacetCells);
00325
00326 int lr = 0;
00327
00328 ios_base::fmtflags oldFlags = os.flags();
00329 os.setf(ios_base::right);
00330 os.setf(ios_base::showpoint);
00331
00332 for (int c=0; c<nCells; c++)
00333 {
00334 Tabs tab3;
00335 os << tab3 << std::endl
00336 << tab3 << "c="<< c << ", cellLID=" << (*workSet)[c] << std::endl;
00337
00338 os << tab3 << "num values per cell = " << localValues.size()/nCells
00339 << ", num test nodes=" << nTestNodes << ", num unk nodes="
00340 << nUnkNodes << std::endl;
00341 Array<int> lsmCols(nUnkNodes);
00342 os << tab3 << setw(17);
00343
00344 os << "|";
00345 for (int n=0; n<nUnkNodes; n++)
00346 {
00347 int colDof = unkDofs[(c*nUnkFuncs + unkFuncIndex)*nUnkNodes + n];
00348 lsmCols[n] = colDof;
00349 os << setw(12) << colDof;
00350 }
00351 os << std::endl << tab3 << "---------------------------------------------------------------" << std::endl;
00352
00353
00354 for (int m=0; m<nTestNodes; m++, lr++)
00355 {
00356 int globalRow
00357 = testDofs[(c*nTestFuncs + testFuncIndex)*nTestNodes+m];
00358 os << tab3 << setw(6) << m << setw(10) << globalRow << "|";
00359
00360 for (int n=0; n<nUnkNodes; n++)
00361 {
00362 double Amn = localValues[lr*nUnkNodes + n];
00363 os << setw(12) << setprecision(5) << Amn;
00364 }
00365 os << std::endl;
00366 }
00367 }
00368 os.flags(oldFlags);
00369 }