SundanceMatrixVectorAssemblyKernel.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
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 }

Site Contact