00001
00016 #ifndef _MASSMATRIX_H_
00017 #define _MASSMATRIX_H_
00018
00031 #include "feMatrix.h"
00032
00033 class massMatrix : public ot::fem::feMatrix<massMatrix>
00034 {
00035 public:
00036 massMatrix(daType da);
00047 inline bool ElementalMatVec(int i, int j, int k, PetscScalar ***in, PetscScalar ***out, double scale);
00048 inline bool ElementalMatVec(unsigned int idx, PetscScalar *in, PetscScalar *out, double scale);
00049
00050 inline bool ElementalMatGetDiagonal(int i, int j, int k, PetscScalar ***diag, double scale);
00051 inline bool ElementalMatGetDiagonal(unsigned int idx, PetscScalar *diag, double scale);
00052
00053 inline bool initStencils();
00054
00055 bool preMatVec();
00056 bool postMatVec();
00057
00058 void setNuVec(Vec nv) {
00059 nuvec = nv;
00060 }
00061
00062 private:
00063 PetscScalar*** nuarray;
00064 Vec nuvec;
00065
00066 double m_dHx;
00067
00068 double xFac, yFac, zFac;
00069 unsigned int maxD;
00070 };
00071
00072
00073 massMatrix::massMatrix(daType da) {
00074 #ifdef __DEBUG__
00075 assert ( ( da == PETSC ) || ( da == OCT ) );
00076 #endif
00077 m_daType = da;
00078 m_DA = NULL;
00079 m_octDA = NULL;
00080 m_stencil = NULL;
00081
00082
00083 initStencils();
00084 if (da == OCT)
00085 initOctLut();
00086 }
00087
00088 bool massMatrix::initStencils() {
00089 typedef int* int1Ptr;
00090 typedef int** int2Ptr;
00091
00092 if (m_daType == PETSC) {
00093 int Bjk[8][8] = {
00094 { 64, 32, 32, 16, 32, 16, 16, 8},
00095 { 32, 64, 16, 32, 16, 32, 8, 16},
00096 { 32, 16, 64, 32, 16, 8, 32, 16},
00097 { 16, 32, 32, 64, 8, 16, 16, 32},
00098 { 32, 16, 16, 8, 64, 32, 32, 16},
00099 { 16, 32, 8, 16, 32, 64, 16, 32},
00100 { 16, 8, 32, 16, 32, 16, 64, 32},
00101 { 8, 16, 16, 32, 16, 32, 32, 64}
00102 };
00103
00104 int** Ajk = new int1Ptr[8];
00105 for (int j=0;j<8;j++) {
00106 Ajk[j] = new int[8];
00107 for (int k=0;k<8;k++) {
00108 Ajk[j][k] = Bjk[j][k];
00109 }
00110 }
00111 m_stencil = Ajk;
00112 } else {
00113 int Bijk[8][8][8] = {
00114
00115 {{ 64, 32, 32, 16, 32, 16, 16, 8},
00116 { 32, 64, 16, 32, 16, 32, 8, 16},
00117 { 32, 16, 64, 32, 16, 8, 32, 16},
00118 { 16, 32, 32, 64, 8, 16, 16, 32},
00119 { 32, 16, 16, 8, 64, 32, 32, 16},
00120 { 16, 32, 8, 16, 32, 64, 16, 32},
00121 { 16, 8, 32, 16, 32, 16, 64, 32},
00122 { 8, 16, 16, 32, 16, 32, 32, 64}},
00123
00124
00125 {{ 112, 40, 32, 32, 40, 20, 32, 16},
00126 { 40, 64, 8, 32, 16, 32, 8, 16},
00127 { 32, 8, 16, 16, 8, 4, 16, 8},
00128 { 32, 32, 16, 64, 8, 16, 16, 32},
00129 { 40, 16, 8, 8, 64, 32, 32, 16},
00130 { 20, 32, 4, 16, 32, 64, 16, 32},
00131 { 32, 8, 16, 16, 32, 16, 64, 32},
00132 { 16, 16, 8, 32, 16, 32, 32, 64}},
00133
00134
00135 {{ 168, 36, 36, 48, 48, 36, 36, 24},
00136 { 36, 16, 4, 16, 8, 16, 4, 8},
00137 { 36, 4, 16, 16, 8, 4, 16, 8},
00138 { 48, 16, 16, 64, 8, 16, 16, 32},
00139 { 48, 8, 8, 8, 64, 32, 32, 16},
00140 { 36, 16, 4, 16, 32, 64, 16, 32},
00141 { 36, 4, 16, 16, 32, 16, 64, 32},
00142 { 24, 8, 8, 32, 16, 32, 32, 64}},
00143
00144
00145 {{ 232, 40, 40, 52, 40, 52, 52, 32},
00146 { 40, 16, 4, 16, 4, 16, 4, 8},
00147 { 40, 4, 16, 16, 4, 4, 16, 8},
00148 { 52, 16, 16, 64, 4, 16, 16, 32},
00149 { 40, 4, 4, 4, 16, 16, 16, 8},
00150 { 52, 16, 4, 16, 16, 64, 16, 32},
00151 { 52, 4, 16, 16, 16, 16, 64, 32},
00152 { 32, 8, 8, 32, 8, 32, 32, 64}},
00153
00154
00155 {{ 196, 56, 56, 16, 50, 40, 40, 32},
00156 { 56, 28, 16, 8, 10, 20, 8, 16},
00157 { 56, 16, 28, 8, 10, 8, 20, 16},
00158 { 16, 8, 8, 4, 2, 4, 4, 8},
00159 { 50, 10, 10, 2, 64, 32, 32, 16},
00160 { 40, 20, 8, 4, 32, 64, 16, 32},
00161 { 40, 8, 20, 4, 32, 16, 64, 32},
00162 { 32, 16, 16, 8, 16, 32, 32, 64}},
00163
00164
00165 {{ 262, 61, 61, 17, 41, 56, 56, 40},
00166 { 61, 28, 16, 8, 5, 20, 8, 16},
00167 { 61, 16, 28, 8, 5, 8, 20, 16},
00168 { 17, 8, 8, 4, 1, 4, 4, 8},
00169 { 41, 5, 5, 1, 16, 16, 16, 8},
00170 { 56, 20, 8, 4, 16, 64, 16, 32},
00171 { 56, 8, 20, 4, 16, 16, 64, 32},
00172 { 40, 16, 16, 8, 8, 32, 32, 64}},
00173
00174
00175 {{ 294, 63, 84, 18, 63, 60, 18, 48},
00176 { 63, 28, 18, 8, 7, 20, 2, 16},
00177 { 84, 18, 42, 9, 18, 12, 9, 24},
00178 { 18, 8, 9, 4, 2, 4, 1, 8},
00179 { 63, 7, 18, 2, 28, 20, 8, 16},
00180 { 60, 20, 12, 4, 20, 64, 4, 32},
00181 { 18, 2, 9, 1, 8, 4, 4, 8},
00182 { 48, 16, 24, 8, 16, 32, 8, 64}},
00183
00184
00185 {{ 328, 87, 87, 19, 87, 19, 19, 56},
00186 { 87, 42, 21, 9, 21, 9, 3, 24},
00187 { 87, 21, 42, 9, 21, 3, 9, 24},
00188 { 19, 9, 9, 4, 3, 1, 1, 8},
00189 { 87, 21, 21, 3, 42, 9, 9, 24},
00190 { 19, 9, 3, 1, 9, 4, 1, 8},
00191 { 19, 3, 9, 1, 9, 1, 4, 8},
00192 { 56, 24, 24, 8, 24, 8, 8, 64}}
00193 };
00194
00195 int ***Aijk = new int2Ptr[8];
00196 for (int i=0;i<8;i++) {
00197 Aijk[i] = new int1Ptr[8];
00198 for (int j=0;j<8;j++) {
00199 Aijk[i][j] = new int[8];
00200 for (int k=0;k<8;k++) {
00201 Aijk[i][j][k] = Bijk[i][j][k];
00202 }
00203 }
00204 }
00205 m_stencil = Aijk;
00206 }
00207 return true;
00208 }
00209
00210 bool massMatrix::preMatVec() {
00211 if (m_daType == PETSC) {
00212
00213 int ierr;
00214 PetscInt mx,my,mz;
00215 ierr = DAGetInfo(m_DA,0, &mx, &my, &mz, 0,0,0,0,0,0,0); CHKERRQ(ierr);
00216
00217 m_dHx = m_dLx/(mx -1);
00218 m_dHx = m_dHx*m_dHx*m_dHx;
00219 m_dHx /= 1728.0;
00220 CHKERRQ(ierr);
00221 } else {
00222 maxD = m_octDA->getMaxDepth();
00223
00224
00225
00226 xFac = 1.0/((double)(1u << (maxD-1)));
00227 if (m_octDA->getDimension() > 1) {
00228 yFac = 1.0/((double)(1u << (maxD-1)));
00229 if (m_octDA->getDimension() > 2) {
00230 zFac = 1.0/((double)(1u << (maxD-1)));
00231 }
00232 }
00233 }
00234
00235 return true;
00236 }
00237
00238 bool massMatrix::ElementalMatVec(unsigned int i, PetscScalar *in, PetscScalar *out, double scale) {
00239 unsigned int lev = m_octDA->getLevel(i);
00240 double hx = xFac*(1u << (maxD - lev));
00241 double hy = yFac*(1u << (maxD - lev));
00242 double hz = zFac*(1u << (maxD - lev));
00243
00244 double fac = scale*hx*hy*hz/1728.0;
00245
00246 stdElemType elemType;
00247 unsigned int idx[8];
00248
00249 int ***Aijk = (int ***)m_stencil;
00250
00251 alignElementAndVertices(m_octDA, elemType, idx);
00252
00253
00254 for (int k = 0;k < 8;k++) {
00255 for (int j=0;j<8;j++) {
00256 out[m_uiDof*idx[k]] += fac*(Aijk[elemType][k][j])*in[m_uiDof*idx[j]];
00257
00258
00259 }
00260 }
00261
00262 return true;
00263 }
00264 bool massMatrix::ElementalMatVec(int i, int j, int k, PetscScalar ***in, PetscScalar ***out, double scale){
00265 int dof= m_uiDof;
00266 int idx[8][3]={
00267 {k, j, dof*i},
00268 {k,j,dof*(i+1)},
00269 {k,j+1,dof*i},
00270 {k,j+1,dof*(i+1)},
00271 {k+1, j, dof*i},
00272 {k+1,j,dof*(i+1)},
00273 {k+1,j+1,dof*i},
00274 {k+1,j+1,dof*(i+1)}
00275 };
00276
00277 double stencilScale = m_dHx*scale;
00278 int **Ajk = (int **)m_stencil;
00279
00280 for (int q = 0; q < 8; q++) {
00281 for (int r = 0; r < 8; r++) {
00282 out[idx[q][0]][idx[q][1]][idx[q][2]] += stencilScale*Ajk[q][r]*in[idx[r][0]][idx[r][1]][idx[r][2]];
00283 if(dof > 1) out[idx[q][0]][idx[q][1]][idx[q][2]+1] += 0.0;
00284 }
00285 }
00286 return true;
00287
00288 }
00289
00290 bool massMatrix::postMatVec() {
00291
00292 return true;
00293 }
00294
00295 bool massMatrix::ElementalMatGetDiagonal(unsigned int i, PetscScalar *diag, double scale) {
00296 unsigned int lev = m_octDA->getLevel(i);
00297 double hx = xFac*(1u << (maxD - lev));
00298 double hy = yFac*(1u << (maxD - lev));
00299 double hz = zFac*(1u << (maxD - lev));
00300
00301 double fac = scale*hx*hy*hz/1728.0;
00302
00303 stdElemType elemType;
00304 unsigned int idx[8];
00305
00306 int ***Aijk = (int ***)m_stencil;
00307
00308 alignElementAndVertices(m_octDA, elemType, idx);
00309
00310 for (int k = 0;k < 8;k++) {
00311 diag[m_uiDof*idx[k]] += fac*(Aijk[elemType][k][k]);
00312 }
00313
00314 return true;
00315 }
00316
00317 bool massMatrix::ElementalMatGetDiagonal(int i, int j, int k, PetscScalar ***diag, double scale){
00318 int dof= m_uiDof;
00319 int idx[8][3]={
00320 {k, j, dof*i},
00321 {k,j,dof*(i+1)},
00322 {k,j+1,dof*i},
00323 {k,j+1,dof*(i+1)},
00324 {k+1, j, dof*i},
00325 {k+1,j,dof*(i+1)},
00326 {k+1,j+1,dof*i},
00327 {k+1,j+1,dof*(i+1)}
00328 };
00329
00330 double stencilScale = m_dHx*scale;
00331 int **Ajk = (int **)m_stencil;
00332
00333 for (int q = 0; q < 8; q++) {
00334 diag[idx[q][0]][idx[q][1]][idx[q][2]] += stencilScale*Ajk[q][q];
00335 if(dof > 1) diag[idx[q][0]][idx[q][1]][idx[q][2]+1] += 0.0;
00336 }
00337 return true;
00338 }
00339
00340
00341 #endif
00342