Actual source code: elemvec2d.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: elemvec2d.c,v 1.14 2000/01/31 17:51:54 knepley Exp $";
  3: #endif

  5: #include "src/grid/gridimpl.h"         /*I "grid.h" I*/
  6: #include "src/mesh/impls/triangular/triimpl.h"
  7: #include "elemvec2d.h"

  9: /*--------------------------------------------- Element Vector Functions --------------------------------------------*/
 10: #undef  __FUNCT__
 12: int PrintVecIndices_Private(Grid grid, const char option[], int field, int node, int comp, int rowStart, int *rowIdx) {
 13:   MPI_Comm   comm;
 14:   int        rank;
 15:   int        var;
 16:   PetscTruth opt;
 17:   int        ierr;

 20:   PetscOptionsHasName(PETSC_NULL, option, &opt);
 21:   if (opt == PETSC_FALSE) return(0);
 22:   PetscObjectGetComm((PetscObject) grid, &comm);
 23:   MPI_Comm_rank(comm, &rank);
 24:   PetscPrintf(PETSC_COMM_SELF, "[%d]field: %d node: %d\n", rank, field, node);
 25:   for(var = rowStart-comp; var < rowStart; var++)
 26:     PetscPrintf(PETSC_COMM_SELF, "[%d]rowIdx[%d]: %d\n", rank, var, rowIdx[var]);
 27:   return(0);
 28: }

 30: #undef  __FUNCT__
 32: /*
 33:   Reduction:

 35:   When the variables associated with boundary conditions are being reduced, the element vector is compressed
 36:   to account for their absence. This reduction only happens in the global numbering. When using the local
 37:   numbering, the original variable numbers are replaced by the corresponding index in grid->bdReduceVec
 38:   which contains the boundary values. In order to distinguish these indices, they are stored as -(idx+1).
 39:   The boundary values are retieved by GridLocalToElement(). The useOldStructs flag signals that we are
 40:   interpolating from a previous mesh, and thus the constraints must be calculated from the previous values.
 41: */
 42: int GridCalcElementVecIndices_Triangular_2D(Grid grid, Mesh mesh, int elem, VarOrdering order, VarOrdering reduceOrder,
 43:                                             PetscTruth localNumbering, PetscTruth useOldStructs, ElementVec vec)
 44: {
 45:   int                   numCorners   = mesh->numCorners;
 46:   int                   numNodes     = mesh->numNodes;
 47:   PetscConstraintObject constCtx     = grid->constraintCtx;
 48:   int                  *firstVar     = order->firstVar;
 49:   int                  *offsets      = order->offsets;
 50:   int                  *localOffsets = order->localOffsets;
 51:   int                 **localStart   = order->localStart;
 52:   int                  *rowIdx       = vec->indices;
 53:   int                   rank         = mesh->part->rank;
 54:   int                   size         = vec->size;
 55:   PetscScalar          *array        = vec->array;
 56:   FieldClassMap         map;
 57:   int                   numFields;
 58:   int                  *fields;
 59:   int                 **fieldClasses, **reduceFieldClasses;
 60:   int                  *classes;
 61:   PetscTruth            isReduced, isConstrained;
 62:   int                  *isConst;
 63:   int                  *reduceFirstVar     = PETSC_NULL;
 64:   int                  *reduceOffsets      = PETSC_NULL;
 65:   int                  *reduceLocalOffsets = PETSC_NULL;
 66:   int                 **reduceLocalStart   = PETSC_NULL;
 67:   int                   field, node, nclass, comp, startVar, diff, inc;
 68:   int                   i, f, count, source, corner, row;
 69:   int                   ierr;

 72:   VarOrderingGetClassMap(order, &map);
 73:   numFields          = map->numFields;
 74:   fields             = map->fields;
 75:   fieldClasses       = map->fieldClasses;
 76:   reduceFieldClasses = map->reduceFieldClasses;
 77:   classes            = map->classes;
 78:   isReduced          = map->isReduced;
 79:   isConstrained      = map->isConstrained;
 80:   isConst            = map->isClassConstrained;
 81:   if (isReduced == PETSC_TRUE) {
 82:     reduceFirstVar     = reduceOrder->firstVar;
 83:     reduceOffsets      = reduceOrder->offsets;
 84:     reduceLocalOffsets = reduceOrder->localOffsets;
 85:     reduceLocalStart   = reduceOrder->localStart;
 86:   }
 87:   for(f = 0, count = 0, source = 0, inc = 0; f < numFields; f++) {
 88:     field = fields[f];
 89:     comp  = grid->fields[field].disc->comp;

 91:     for(corner = 0; corner < numCorners; corner++) {
 92:       MeshGetNodeFromElement(mesh, elem, corner, &node);
 93:       nclass = classes[node];
 94:       if ((isReduced == PETSC_TRUE) && (reduceFieldClasses[f][nclass])) {
 95:         if (localNumbering == PETSC_FALSE) {
 96:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
 97:           source += comp;
 98:           inc    -= comp;
 99:         } else {
100:           if (node >= numNodes)
101:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
102:           else
103:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
104:           for(i = 0; i < comp; i++, count++) {
105:             rowIdx[count] = -(startVar + i + 1);
106:           }
107: #ifdef PETSC_USE_BOPT_g
108:           PrintVecIndices_Private(grid, "-trace_vec_assembly", field, node, comp, count, rowIdx);
109: #endif
110:         }
111:       } else if ((isConstrained == PETSC_TRUE) && (isConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
112:         /* We guarantee that count <= source here */
113:         diff = grid->fields[field].constraintCompDiff;
114:         inc += diff;
115:         /* Move rows to operate on */
116:         if (count < source) {
117:           for(row = 0; row < comp; row++)
118:             array[count+row] = array[source+row];
119:         }
120:         source += comp;
121:         /* We must replace this field with the constraint field and prevent overwriting in element vector */
122:         if (source - count < comp + diff) {
123:           /* Move old fields */
124:           for(row = size-(diff+1); row >= source; row--)
125:             array[row+diff] = array[row];
126:           source += diff;
127:         }
128:         /* Apply P^T to get constraint fields */
129:         (*constCtx->ops->constrainelemvec)(constCtx, mesh, order, field, node, count, localNumbering,
130:                                                   useOldStructs, CONSTRAINT_ROW, vec);
131: 
132:         count += comp + diff;
133:       } else if (fieldClasses[f][nclass]) {
134:         if (localNumbering == PETSC_FALSE) {
135:           startVar = offsets[node] + localStart[field][nclass];
136:         } else {
137:           if (node >= numNodes)
138:             startVar = localOffsets[node-numNodes] + localStart[field][nclass];
139:           else
140:             startVar = offsets[node] - firstVar[rank] + localStart[field][nclass];
141:         }
142:         for(i = 0; i < comp; i++, count++, source++) {
143:           rowIdx[count] = startVar + i;
144:           array[count]  = array[source];
145:         }
146: #ifdef PETSC_USE_BOPT_g
147:         PrintVecIndices_Private(grid, "-trace_vec_assembly", field, node, comp, count, rowIdx);
148: #endif
149:       }
150:     }
151:   }
152: #ifdef PETSC_USE_BOPT_g
153:   if (count != vec->reduceSize + inc) {
154:     SETERRQ3(PETSC_ERR_PLIB, "Invalid variable numbering elem: %d size: %d count: %d\n", elem, vec->reduceSize+inc, count);
155:   }
156:   if (count > vec->size) {
157:     SETERRQ3(PETSC_ERR_PLIB, "Number of indices %d in elem %d exceeded maximum size %d\n", count, elem, vec->size);
158:   }
159: #endif
160:   /* Set true vector size */
161:   vec->reduceSize = count;

163:   return(0);
164: }

166: #undef  __FUNCT__
168: /*
169:   Projection:

171:   We would like a mechanism to convert from the constrained to unconstrained variables, and vice versa,
172:   for an element vector. This code is also embedded in the element vector index calculation, and could
173:   perhaps be split out. This function is generally called to take a constrained element vector to
174:   unconstrained variables before an element integral is performed.
175: */
176: int GridProjectElementVec_Triangular_2D(Grid grid, Mesh mesh, int elem, VarOrdering order, VarOrdering reduceOrder,
177:                                         PetscTruth constrain, PetscTruth useOldStructs, ElementVec vec)
178: {
179:   int                   numCorners   = mesh->numCorners;
180:   PetscConstraintObject constCtx     = grid->constraintCtx;
181:   int                   size         = vec->size;
182:   int                  *rowIdx       = vec->indices;
183:   PetscScalar          *array        = vec->array;
184:   FieldClassMap         map;
185:   int                   numFields;
186:   int                  *fields;
187:   int                 **fieldClasses, **reduceFieldClasses;
188:   int                  *classes;
189:   PetscTruth            isReduced, isConstrained;
190:   int                  *isConst;
191:   int                   field, node, nclass, comp, diff, inc;
192:   int                   i, f, count, source, corner, row;
193:   int                   ierr;

196:   VarOrderingGetClassMap(order, &map);
197:   numFields          = map->numFields;
198:   fields             = map->fields;
199:   fieldClasses       = map->fieldClasses;
200:   classes            = map->classes;
201:   isReduced          = map->isReduced;
202:   isConstrained      = map->isConstrained;
203:   isConst            = map->isClassConstrained;
204:   reduceFieldClasses = map->reduceFieldClasses;
205:   if (isConstrained == PETSC_FALSE)
206:     return(0);
207:   for(f = 0, count = 0, source = 0, inc = 0; f < numFields; f++) {
208:     field = fields[f];
209:     comp  = grid->fields[field].disc->comp;

211:     for(corner = 0; corner < numCorners; corner++) {
212:       MeshGetNodeFromElement(mesh, elem, corner, &node);
213:       nclass = classes[node];
214:       if ((isReduced == PETSC_TRUE) && (reduceFieldClasses[f][nclass])) {
215:         for(i = 0; i < comp; i++, count++, source++) {
216:           rowIdx[count] = rowIdx[source];
217:           array[count]  = array[source];
218:         }
219:       } else if ((isConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
220:         /* We guarantee that count <= source here */
221:         if (constrain == PETSC_TRUE) {
222:           diff  = grid->fields[field].constraintCompDiff;
223:         } else {
224:           diff  = -grid->fields[field].constraintCompDiff;
225:           comp += grid->fields[field].constraintCompDiff;
226:         }
227:         inc += diff;
228:         /* Move rows to operate on */
229:         if (count < source) {
230:           for(row = 0; row < comp; row++)
231:             array[count+row] = array[source+row];
232:         }
233:         source += comp;
234:         /* We must replace this field with the constraint field and prevent overwriting in element vector */
235:         if (source - count < comp + diff) {
236:           /* Move old fields */
237:           for(row = size-(diff+1); row >= source; row--)
238:             array[row+diff] = array[row];
239:           source += diff;
240:         }
241:         if (constrain == PETSC_TRUE) {
242:           /* Apply P^T to get constraint fields */
243:           (*constCtx->ops->constrainelemvec)(constCtx, mesh, order, field, node, count, PETSC_FALSE,
244:                                                     useOldStructs, CONSTRAINT_ROW, vec);
245: 
246:           count += comp + diff;
247:         } else {
248:           /* Apply P to get unconstrained fields */
249:           (*constCtx->ops->constrainelemvec)(constCtx, mesh, order, field, node, count, PETSC_FALSE,
250:                                                     useOldStructs, CONSTRAINT_ROW_TRANS, vec);
251: 
252:           count += comp + diff;
253:           comp  -= grid->fields[field].constraintCompDiff;
254:         }
255:       } else if (fieldClasses[f][nclass]) {
256:         for(i = 0; i < comp; i++, count++, source++) {
257:           rowIdx[count] = rowIdx[source];
258:           array[count]  = array[source];
259:         }
260:       }
261:     }
262:   }
263: #ifdef PETSC_USE_BOPT_g
264:   if (count != vec->reduceSize + inc) {
265:     SETERRQ3(PETSC_ERR_PLIB, "Invalid variable numbering elem: %d size: %d count: %d\n", elem, vec->reduceSize+inc, count);
266:   }
267:   if (count > vec->size) {
268:     SETERRQ3(PETSC_ERR_PLIB, "Number of indices %d in elem %d exceeded maximum size %d\n", count, elem, vec->size);
269:   }
270: #endif
271:   /* Set true vector size */
272:   vec->reduceSize = count;

274:   return(0);
275: }

277: #undef  __FUNCT__
279: int GridCalcBoundaryElementVecIndices_Triangular_2D(Grid grid, int bd, int edge, int midnode, VarOrdering order,
280:                                                     VarOrdering reduceOrder, PetscTruth localNumbering, ElementVec vec)
281: {
282:   Mesh_Triangular      *tri           = (Mesh_Triangular *) grid->mesh->data;
283:   int                  *edges         = tri->edges;
284:   int                   numNodes      = grid->mesh->numNodes;
285:   PetscConstraintObject constCtx      = grid->constraintCtx;
286:   int                  *firstVar      = order->firstVar;
287:   int                  *offsets       = order->offsets;
288:   int                  *localOffsets  = order->localOffsets;
289:   int                 **localStart    = order->localStart;
290:   int                  *rowIdx        = vec->indices;
291:   int                   size          = vec->size;
292:   PetscScalar          *array         = vec->array;
293:   int                   rank;
294:   FieldClassMap         map;
295:   int                   numFields;
296:   int                  *fields;
297:   int                 **fieldClasses, **reduceFieldClasses;
298:   int                  *classes;
299:   PetscTruth            isReduced, isConstrained;
300:   int                  *isConst;
301:   int                  *reduceFirstVar     = PETSC_NULL;
302:   int                  *reduceOffsets      = PETSC_NULL;
303:   int                  *reduceLocalOffsets = PETSC_NULL;
304:   int                 **reduceLocalStart   = PETSC_NULL;
305:   int                   field, node, nclass, comp, startVar, diff, inc;
306:   int                   i, f, count, source, corner, row;
307:   int                   ierr;

310:   MPI_Comm_rank(grid->comm, &rank);
311:   VarOrderingGetClassMap(order, &map);
312:   numFields          = map->numFields;
313:   fields             = map->fields;
314:   fieldClasses       = map->fieldClasses;
315:   reduceFieldClasses = map->reduceFieldClasses;
316:   classes            = map->classes;
317:   isReduced          = map->isReduced;
318:   isConstrained      = map->isConstrained;
319:   isConst            = map->isClassConstrained;
320:   if (isReduced == PETSC_TRUE) {
321:     reduceFirstVar     = reduceOrder->firstVar;
322:     reduceOffsets      = reduceOrder->offsets;
323:     reduceLocalOffsets = reduceOrder->localOffsets;
324:     reduceLocalStart   = reduceOrder->localStart;
325:   }
326:   for(f = 0, count = 0, source = 0, inc = 0; f < numFields; f++) {
327:     field = fields[f];
328:     comp  = grid->fields[field].disc->bdDisc->comp;

330:     for(corner = 0; corner < 2; corner++) {
331:       node   = edges[edge*2+corner];
332:       nclass = classes[node];

334:       if ((isReduced == PETSC_TRUE) && (reduceFieldClasses[f][nclass])) {
335:         if (localNumbering == PETSC_FALSE) {
336:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
337:           source += comp;
338:           inc    -= comp;
339:         } else {
340:           if (node >= numNodes)
341:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
342:           else
343:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
344:           for(i = 0; i < comp; i++, count++) {
345:             rowIdx[count] = -(startVar + i + 1);
346:           }
347: #ifdef PETSC_USE_BOPT_g
348:           PrintVecIndices_Private(grid, "-trace_vec_assembly", field, node, comp, count, rowIdx);
349: #endif
350:         }
351:       } else if ((isConstrained == PETSC_TRUE) && (isConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
352:         /* We guarantee that count <= source here */
353:         diff = grid->fields[field].constraintCompDiff;
354:         inc += diff;
355:         /* Move rows to operate on */
356:         if (count < source) {
357:           for(row = 0; row < comp; row++)
358:             array[count+row] = array[source+row];
359:         }
360:         source += comp;
361:         /* We must replace this field with the constraint field and prevent overwriting in element vector */
362:         if (source - count < comp + diff) {
363:           /* Move old fields */
364:           for(row = size-(diff+1); row >= source; row--)
365:             array[row+diff] = array[row];
366:           source += diff;
367:         }
368:         /* Apply P^T to get constraint fields */
369:         (*constCtx->ops->constrainelemvec)(constCtx, grid->mesh, order, field, node, count, localNumbering,
370:                                                   PETSC_FALSE, CONSTRAINT_ROW, vec);
371: 
372:         count += comp + diff;
373:       } else if (fieldClasses[f][nclass]) {
374:         if (localNumbering == PETSC_FALSE) {
375:           startVar = offsets[node] + localStart[field][nclass];
376:         } else {
377:           if (node >= numNodes)
378:             startVar = localOffsets[node-numNodes] + localStart[field][nclass];
379:           else
380:             startVar = offsets[node] - firstVar[rank] + localStart[field][nclass];
381:         }
382:         for(i = 0; i < comp; i++, count++, source++) {
383:           rowIdx[count] = startVar + i;
384:           array[count]  = array[source];
385:         }
386: #ifdef PETSC_USE_BOPT_g
387:         PrintVecIndices_Private(grid, "-trace_vec_assembly", field, node, comp, count, rowIdx);
388: #endif
389:       }
390:     }

392:     if (midnode >= 0) {
393:       nclass = classes[midnode];

395:       if ((isReduced == PETSC_TRUE) && (reduceFieldClasses[f][nclass])) {
396:         if (localNumbering == PETSC_FALSE) {
397:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
398:           source += comp;
399:           inc    -= comp;
400:         } else {
401:           if (midnode >= numNodes)
402:             startVar = reduceLocalOffsets[midnode-numNodes] + reduceLocalStart[field][nclass];
403:           else
404:             startVar = reduceOffsets[midnode] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
405:           for(i = 0; i < comp; i++, count++) {
406:             rowIdx[count] = -(startVar + i + 1);
407:           }
408: #ifdef PETSC_USE_BOPT_g
409:           PrintVecIndices_Private(grid, "-trace_vec_assembly", field, midnode, comp, count, rowIdx);
410: #endif
411:         }
412:       } else if ((isConstrained == PETSC_TRUE) && (isConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
413:         /* We guarantee that count <= source here */
414:         diff = grid->fields[field].constraintCompDiff;
415:         inc += diff;
416:         /* Move rows to operate on */
417:         if (count < source) {
418:           for(row = 0; row < comp; row++)
419:             array[count+row] = array[source+row];
420:         }
421:         source += comp;
422:         /* We must replace this field with the constraint field and prevent overwriting in element vector */
423:         if (source - count < comp + diff) {
424:           /* Move old fields */
425:           for(row = size-(diff+1); row >= source; row--)
426:             array[row+diff] = array[row];
427:           source += diff;
428:         }
429:         /* Apply P^T to get constraint fields */
430:         (*constCtx->ops->constrainelemvec)(constCtx, grid->mesh, order, field, midnode, count, localNumbering,
431:                                                   PETSC_FALSE, CONSTRAINT_ROW, vec);
432: 
433:         count += comp + diff;
434:       } else if (fieldClasses[f][nclass]) {
435:         if (localNumbering == PETSC_FALSE) {
436:           startVar = offsets[midnode] + localStart[field][nclass];
437:         } else {
438:           if (midnode >= numNodes)
439:             startVar = localOffsets[midnode-numNodes] + localStart[field][nclass];
440:           else
441:             startVar = offsets[midnode] - firstVar[rank] + localStart[field][nclass];
442:         }
443:         for(i = 0; i < comp; i++, count++, source++) {
444:           rowIdx[count] = startVar + i;
445:           array[count]  = array[source];
446:         }
447: #ifdef PETSC_USE_BOPT_g
448:         PrintVecIndices_Private(grid, "-trace_vec_assembly", field, midnode, comp, count, rowIdx);
449: #endif
450:       }
451:     }
452:   }
453: #ifdef PETSC_USE_BOPT_g
454:   if (count != vec->reduceSize + inc) {
455:     SETERRQ3(PETSC_ERR_PLIB, "Invalid variable numbering edge: %d size: %d count: %d\n", edge, vec->reduceSize+inc, count);
456:   }
457:   if (count > vec->size) {
458:     SETERRQ3(PETSC_ERR_PLIB, "Number of indices %d on edge %d exceeded maximum size %d\n", count, edge, vec->size);
459:   }
460: #endif
461:   /* Set true vector size */
462:   vec->reduceSize = count;

464:   return(0);
465: }

467: /*--------------------------------------------- Element Matrix Functions --------------------------------------------*/
468: /*
469:   Element Matrix Structure:

471:   The structure of the element matrix is diagrammed in src/gvec/grid/gridimpl.h.

473:   Reduction:

475:   When the variables associated with boundary conditions are being reduced, the element matrix is compressed
476:   to account for their absence. This reduction only happens in the global numbering. When using the local
477:   numbering, the original variable numbers are replaced by the corresponding index in grid->bdReduceVec
478:   which contains the boundary values. In order to distinguish these indices, they are stored as -(idx+1).
479:   The boundary values are retieved by GridLocalToElement().
480: */
481: #undef  __FUNCT__
483: int GridCalcElementMatIndices_Triangular_2D(Grid grid, int elem, VarOrdering sOrder, VarOrdering tOrder,
484:                                             VarOrdering reduceOrder, PetscTruth localNumbering, ElementMat mat)
485: {
486:   Mesh                  mesh;
487:   int                   numCorners      = grid->mesh->numCorners;
488:   PetscConstraintObject constCtx        = grid->constraintCtx;
489:   int                  *colFirstVar     = sOrder->firstVar;
490:   int                  *colOffsets      = sOrder->offsets;
491:   int                  *colLocalOffsets = sOrder->localOffsets;
492:   int                 **colLocalStart   = sOrder->localStart;
493:   int                  *rowFirstVar     = tOrder->firstVar;
494:   int                  *rowOffsets      = tOrder->offsets;
495:   int                  *rowLocalOffsets = tOrder->localOffsets;
496:   int                 **rowLocalStart   = tOrder->localStart;
497:   int                  *rowIdx          = mat->rowIndices;
498:   int                  *colIdx          = mat->colIndices;
499:   int                   rowSize         = mat->reduceRowSize;
500:   int                   colSize         = mat->reduceColSize;
501:   int                   origRowSize     = mat->reduceRowSize;
502:   int                   origColSize     = mat->reduceColSize;
503:   int                  *newCols         = mat->reduceCols;
504:   PetscScalar          *array           = mat->array;
505:   PetscScalar          *tempArray       = mat->tempArray;
506:   int                   rank            = grid->mesh->part->rank;
507:   FieldClassMap         rowMap,                  colMap;
508:   int                   numNodes;
509:   int                   numRowFields,            numColFields;
510:   int                  *rowFields,              *colFields;
511:   int                 **rowFieldClasses,       **colFieldClasses;
512:   int                 **rowReduceFieldClasses, **colReduceFieldClasses;
513:   int                  *rowClasses,             *colClasses;
514:   PetscTruth            rowIsReduced,            colIsReduced;
515:   PetscTruth            rowIsConstrained,        colIsConstrained;
516:   int                  *rowIsConst,             *colIsConst;
517:   int                  *reduceFirstVar     = PETSC_NULL;
518:   int                  *reduceOffsets      = PETSC_NULL;
519:   int                  *reduceLocalOffsets = PETSC_NULL;
520:   int                 **reduceLocalStart   = PETSC_NULL;
521:   int                   field, node, nclass, comp, startVar, diff, inc;
522:   int                   i, f, corner, rowCount, rowSource, colCount, colSource, row, col, newCol;
523:   int                   ierr;

526:   GridGetMesh(grid, &mesh);
527:   VarOrderingGetClassMap(tOrder, &rowMap);
528:   VarOrderingGetClassMap(sOrder, &colMap);
529:   numNodes              = rowMap->numNodes;
530:   numRowFields          = rowMap->numFields;
531:   rowFields             = rowMap->fields;
532:   rowFieldClasses       = rowMap->fieldClasses;
533:   rowReduceFieldClasses = rowMap->reduceFieldClasses;
534:   rowClasses            = rowMap->classes;
535:   rowIsReduced          = rowMap->isReduced;
536:   rowIsConstrained      = rowMap->isConstrained;
537:   rowIsConst            = rowMap->isClassConstrained;
538:   numColFields          = colMap->numFields;
539:   colFields             = colMap->fields;
540:   colFieldClasses       = colMap->fieldClasses;
541:   colReduceFieldClasses = colMap->reduceFieldClasses;
542:   colClasses            = colMap->classes;
543:   colIsReduced          = colMap->isReduced;
544:   colIsConstrained      = colMap->isConstrained;
545:   colIsConst            = colMap->isClassConstrained;
546:   if ((rowIsReduced == PETSC_TRUE) || (colIsReduced == PETSC_TRUE)) {
547:     reduceFirstVar     = reduceOrder->firstVar;
548:     reduceOffsets      = reduceOrder->offsets;
549:     reduceLocalOffsets = reduceOrder->localOffsets;
550:     reduceLocalStart   = reduceOrder->localStart;
551:   }
552:   for(f = 0, rowCount = 0, rowSource = 0, inc = 0; f < numRowFields; f++) {
553:     field = rowFields[f];
554:     comp  = grid->fields[field].disc->comp;

556:     for(corner = 0; corner < numCorners; corner++) {
557:       MeshGetNodeFromElement(mesh, elem, corner, &node);
558:       nclass = rowClasses[node];

560:       if ((rowIsReduced == PETSC_TRUE) && (rowReduceFieldClasses[f][nclass])) {
561:         if (localNumbering == PETSC_FALSE) {
562:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
563:           rowSource += comp;
564:           inc       -= comp;
565:         } else {
566:           if (node >= numNodes)
567:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
568:           else
569:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
570:           for(i = 0; i < comp; i++, rowCount++, rowSource++) {
571:             rowIdx[rowCount] = -(startVar + i + 1);
572:           }
573:         }
574:       } else if ((rowIsConstrained == PETSC_TRUE) && (rowIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
575:         /* We guarantee that rowCount <= rowSource here */
576:         diff = grid->fields[field].constraintCompDiff;
577:         inc += diff;
578:         /* Move rows to operate on */
579:         if (rowCount < rowSource) {
580:           for(row = 0; row < comp; row++)
581:             for(col = 0; col < colSize; col++)
582:               array[(rowCount+row)*colSize+col] = array[(rowSource+row)*colSize+col];
583:         }
584:         rowSource += comp;
585:         /* We must replace this field with the constraint field and prevent overwriting in element matrix */
586:         if (rowSource - rowCount < comp + diff) {
587:           /* Move old fields */
588:           for(row = rowSize-1; row >= rowSource; row--)
589:             for(col = 0; col < colSize; col++)
590:               array[(row+diff)*colSize+col] = array[row*colSize+col];
591:           rowSource += diff;
592:           rowSize   += diff;
593:         }
594:         /* Apply P^T to get constraint fields */
595:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, tOrder, field, node, rowCount, CONSTRAINT_ROW, mat);
596: 
597:         rowCount += comp + diff;
598:       } else if (rowFieldClasses[f][nclass]) {
599:         if (localNumbering == PETSC_FALSE) {
600:           startVar = rowOffsets[node] + rowLocalStart[field][nclass];
601:         } else {
602:           if (node >= numNodes)
603:             startVar = rowLocalOffsets[node-numNodes] + rowLocalStart[field][nclass];
604:           else
605:             startVar = rowOffsets[node] - rowFirstVar[rank] + rowLocalStart[field][nclass];
606:         }
607:         for(i = 0; i < comp; i++, rowCount++, rowSource++) {
608:           rowIdx[rowCount] = startVar + i;
609:           /* Shrink rows -- I do not see a way around shrinking the whole matrix */
610:           if (rowCount != rowSource) {
611:             for(col = 0; col < colSize; col++)
612:               array[rowCount*colSize+col] = array[rowSource*colSize+col];
613:           }
614:         }
615:       }
616:     }
617:   }
618:   if (rowCount != origRowSize + inc) {
619:     SETERRQ3(PETSC_ERR_PLIB, "Invalid row numbering elem: %d size: %d count: %d\n", elem, origRowSize+inc, rowCount);
620:   }
621:   if (rowSize  > mat->rowSize) {
622:     SETERRQ3(PETSC_ERR_PLIB, "Number of row indices %d in elem %d exceeded maximum size %d\n", rowSize, elem, mat->rowSize);
623:   }
624:   if (rowCount > mat->rowSize) {
625:     SETERRQ3(PETSC_ERR_PLIB, "Number of row indices %d in elem %d exceeded maximum size %d\n", rowCount, elem, mat->rowSize);
626:   }
627:   mat->reduceRowSize = rowCount;

629:   /* Calculate the columns ordering after reduction --
630:        colCount  - Number of columns stacked into mat
631:        colSource - Current column of mat being accessed
632:        inc       - The difference in size of the constrained matrix from the original
633:        newCols   - The column reordering, newCols[colSource] is the current column in the matrix, -1 for not present
634:   */
635:   for(f = 0, colCount = 0, colSource = 0, newCol = origColSize, inc = 0; f < numColFields; f++) {
636:     field = colFields[f];
637:     comp  = grid->fields[field].disc->comp;

639:     for(corner = 0; corner < numCorners; corner++) {
640:       MeshGetNodeFromElement(mesh, elem, corner, &node);
641:       nclass = colClasses[node];
642: 
643:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
644:         if (localNumbering == PETSC_FALSE) {
645:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
646:           for(i = 0; i < comp; i++, colSource++) {
647:             newCols[colSource] = -1;
648:           }
649:           inc       -= comp;
650:         } else {
651:           /* Put in negative indices corresponding to boundary values */
652:           for(i = 0; i < comp; i++, colCount++, colSource++) {
653:             newCols[colSource] = colCount;
654:           }
655:         }
656:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
657:         /* We must replace this field with the constraint field and prevent overwriting in element matrix */
658:         diff = grid->fields[field].constraintCompDiff;
659:         inc += diff;
660:         if (diff > 0) {
661:           /* Assume new field were previously in the last columns */
662:           for(i = 0; i < comp; i++, colCount++, colSource++)
663:             newCols[colSource] = colCount;
664:           for(i = 0; i < diff; i++, colCount++, newCol++)
665:             newCols[newCol]    = colCount;
666:         } else {
667:           /* Just squeeze matrix */
668:           for(i = 0; i < comp + diff; i++, colCount++, colSource++)
669:             newCols[colSource] = colCount;
670:           for(i = comp+diff; i < comp; i++, colSource++)
671:             newCols[colSource] = -1;
672:         }
673:       } else if (colFieldClasses[f][nclass]) {
674:         for(i = 0; i < comp; i++, colCount++, colSource++) {
675:           newCols[colSource] = colCount;
676:         }
677:       }
678:     }
679:   }
680: #ifdef PETSC_USE_BOPT_g
681:   if (colCount != origColSize + inc) {
682:     SETERRQ3(PETSC_ERR_PLIB, "Invalid column numbering elem: %d size: %d count: %d\n", elem, origColSize+inc, colCount);
683:   }
684:   if (colCount > mat->colSize) {
685:     SETERRQ3(PETSC_ERR_PLIB, "Number of column indices %d in elem %d exceeded maximum size %d\n", colCount, elem, mat->colSize);
686:   }
687: #endif
688:   mat->reduceColSize = colCount;

690:   /* Reform the element matrix: newCols[original col] = new col */
691:   if (mat->reduceColSize != origColSize) {
692:     if (colIsConstrained == PETSC_TRUE) {
693:       for(row = 0; row < mat->reduceRowSize; row++)
694:         for(col = 0; col < origColSize; col++)
695:           if (newCols[col] >= 0)
696:             tempArray[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
697:       PetscMemcpy(array, tempArray, mat->reduceRowSize*mat->reduceColSize * sizeof(PetscScalar));
698:     } else {
699:       /* Can copy in place if no constraints were applied since BC just delete entries */
700:       for(row = 0; row < mat->reduceRowSize; row++)
701:         for(col = 0; col < origColSize; col++)
702:           if (newCols[col] >= 0)
703:             array[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
704:     }
705:   }

707:   /* Calculate indices and constrained matrix elements */
708:   for(f = 0, colCount = 0; f < numColFields; f++) {
709:     field = colFields[f];
710:     comp  = grid->fields[field].disc->comp;

712:     for(corner = 0; corner < numCorners; corner++) {
713:       MeshGetNodeFromElement(mesh, elem, corner, &node);
714:       nclass = colClasses[node];
715: 
716:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
717:         if (localNumbering == PETSC_TRUE) {
718:           if (node >= numNodes)
719:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
720:           else
721:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
722:           for(i = 0; i < comp; i++, colCount++) {
723:             colIdx[colCount] = -(startVar + i + 1);
724:           }
725:         }
726:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
727:         /* Apply P to get constraint fields */
728:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, sOrder, field, node, colCount, CONSTRAINT_COL, mat);
729: 
730:         colCount  += comp + grid->fields[field].constraintCompDiff;
731:       } else if (colFieldClasses[f][nclass]) {
732:         if (localNumbering == PETSC_FALSE) {
733:           startVar = colOffsets[node] + colLocalStart[field][nclass];
734:         } else {
735:           if (node >= numNodes)
736:             startVar = colLocalOffsets[node-numNodes] + colLocalStart[field][nclass];
737:           else
738:             startVar = colOffsets[node] - colFirstVar[rank] + colLocalStart[field][nclass];
739:         }
740:         for(i = 0; i < comp; i++, colCount++) {
741:           colIdx[colCount] = startVar + i;
742:         }
743:       }
744:     }
745:   }

747:   return(0);
748: }

750: #undef  __FUNCT__
752: int GridCalcBoundaryElementMatIndices_Triangular_2D(Grid grid, int bd, int edge, int midnode, VarOrdering sOrder,
753:                                                     VarOrdering tOrder, VarOrdering reduceOrder, PetscTruth localNumbering,
754:                                                     ElementMat mat)
755: {
756:   Mesh_Triangular      *tri             = (Mesh_Triangular *) grid->mesh->data;
757:   int                   numCorners      = grid->mesh->numCorners;
758:   int                  *elements        = tri->faces;
759:   int                  *edges           = tri->edges;
760:   PetscConstraintObject constCtx        = grid->constraintCtx;
761:   int                  *colFirstVar     = sOrder->firstVar;
762:   int                  *colOffsets      = sOrder->offsets;
763:   int                  *colLocalOffsets = sOrder->localOffsets;
764:   int                 **colLocalStart   = sOrder->localStart;
765:   int                  *rowFirstVar     = tOrder->firstVar;
766:   int                  *rowOffsets      = tOrder->offsets;
767:   int                  *rowLocalOffsets = tOrder->localOffsets;
768:   int                 **rowLocalStart   = tOrder->localStart;
769:   int                  *rowIdx          = mat->rowIndices;
770:   int                  *colIdx          = mat->colIndices;
771:   int                   rowSize         = mat->reduceRowSize;
772:   int                   colSize         = mat->reduceColSize;
773:   int                   origRowSize     = mat->reduceRowSize;
774:   int                   origColSize     = mat->reduceColSize;
775:   int                  *newCols         = mat->reduceCols;
776:   PetscScalar          *array           = mat->array;
777:   PetscScalar          *tempArray       = mat->tempArray;
778:   int                   rank            = grid->mesh->part->rank;
779:   FieldClassMap         rowMap,                  colMap;
780:   int                   numNodes;
781:   int                   numRowFields,            numColFields;
782:   int                  *rowFields,              *colFields;
783:   int                 **rowFieldClasses,       **colFieldClasses;
784:   int                 **rowReduceFieldClasses, **colReduceFieldClasses;
785:   int                  *rowClasses,             *colClasses;
786:   PetscTruth            rowIsReduced,            colIsReduced;
787:   PetscTruth            rowIsConstrained,        colIsConstrained;
788:   int                  *rowIsConst,             *colIsConst;
789:   int                  *reduceFirstVar     = PETSC_NULL;
790:   int                  *reduceOffsets      = PETSC_NULL;
791:   int                  *reduceLocalOffsets = PETSC_NULL;
792:   int                 **reduceLocalStart   = PETSC_NULL;
793:   int                   field, node, nclass, comp, startVar, diff, inc;
794:   int                   i, f, elem, corner, rowCount, rowSource, colCount, colSource, row, col, newCol;
795:   int                   ierr;

798:   VarOrderingGetClassMap(tOrder, &rowMap);
799:   VarOrderingGetClassMap(sOrder, &colMap);
800:   numNodes              = rowMap->numNodes;
801:   numRowFields          = rowMap->numFields;
802:   rowFields             = rowMap->fields;
803:   rowFieldClasses       = rowMap->fieldClasses;
804:   rowReduceFieldClasses = rowMap->reduceFieldClasses;
805:   rowClasses            = rowMap->classes;
806:   rowIsReduced          = rowMap->isReduced;
807:   rowIsConstrained      = rowMap->isConstrained;
808:   rowIsConst            = rowMap->isClassConstrained;
809:   numColFields          = colMap->numFields;
810:   colFields             = colMap->fields;
811:   colFieldClasses       = colMap->fieldClasses;
812:   colReduceFieldClasses = colMap->reduceFieldClasses;
813:   colClasses            = colMap->classes;
814:   colIsReduced          = colMap->isReduced;
815:   colIsConstrained      = colMap->isConstrained;
816:   colIsConst            = colMap->isClassConstrained;
817:   if ((rowIsReduced == PETSC_TRUE) || (colIsReduced == PETSC_TRUE)) {
818:     reduceFirstVar     = reduceOrder->firstVar;
819:     reduceOffsets      = reduceOrder->offsets;
820:     reduceLocalOffsets = reduceOrder->localOffsets;
821:     reduceLocalStart   = reduceOrder->localStart;
822:   }
823:   MeshGetBdElementFromEdge(grid->mesh, edge, &elem);
824:   for(f = 0, rowCount = 0, rowSource = 0, inc = 0; f < numRowFields; f++) {
825:     field = rowFields[f];
826:     comp  = grid->fields[field].disc->comp;

828:     for(corner = 0; corner < numCorners; corner++) {
829:       node   = elements[elem*numCorners+corner];
830:       nclass = rowClasses[node];

832:       if ((rowIsReduced == PETSC_TRUE) && (rowReduceFieldClasses[f][nclass])) {
833:         if (localNumbering == PETSC_FALSE) {
834:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
835:           rowSource += comp;
836:           inc       -= comp;
837:         } else {
838:           if (node >= numNodes)
839:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
840:           else
841:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
842:           for(i = 0; i < comp; i++, rowCount++, rowSource++) {
843:             rowIdx[rowCount] = -(startVar + i + 1);
844:           }
845:         }
846:       } else if ((rowIsConstrained == PETSC_TRUE) && (rowIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
847:         /* We guarantee that rowCount <= rowSource here */
848:         diff = grid->fields[field].constraintCompDiff;
849:         inc += diff;
850:         /* Move rows to operate on */
851:         if (rowCount < rowSource) {
852:           for(row = 0; row < comp; row++)
853:             for(col = 0; col < colSize; col++)
854:               array[(rowCount+row)*colSize+col] = array[(rowSource+row)*colSize+col];
855:         }
856:         rowSource += comp;
857:         /* We must replace this field with the constraint field and prevent overwriting in element matrix */
858:         if (rowSource - rowCount < comp + diff) {
859:           /* Move old fields */
860:           for(row = rowSize-1; row >= rowSource; row--)
861:             for(col = 0; col < colSize; col++)
862:               array[(row+diff)*colSize+col] = array[row*colSize+col];
863:           rowSource += diff;
864:           rowSize   += diff;
865:         }
866:         /* Apply P^T to get constraint fields */
867:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, tOrder, field, node, rowCount, CONSTRAINT_ROW, mat);
868: 
869:         rowCount += comp + diff;
870:       } else if (rowFieldClasses[f][nclass]) {
871:         if (localNumbering == PETSC_FALSE) {
872:           startVar = rowOffsets[node] + rowLocalStart[field][nclass];
873:         } else {
874:           if (node >= numNodes)
875:             startVar = rowLocalOffsets[node-numNodes] + rowLocalStart[field][nclass];
876:           else
877:             startVar = rowOffsets[node] - rowFirstVar[rank] + rowLocalStart[field][nclass];
878:         }
879:         for(i = 0; i < comp; i++, rowCount++, rowSource++) {
880:           rowIdx[rowCount] = startVar + i;
881:           /* Shrink rows -- I do not see a way around shrinking the whole matrix */
882:           if (rowCount != rowSource) {
883:             for(col = 0; col < colSize; col++)
884:               array[rowCount*colSize+col] = array[rowSource*colSize+col];
885:           }
886:         }
887:       }
888:     }
889:   }
890:   if (rowCount != origRowSize + inc) {
891:     SETERRQ3(PETSC_ERR_PLIB, "Invalid row numbering edge: %d size: %d count: %d\n", edge, origRowSize+inc, rowCount);
892:   }
893:   if (rowSize  > mat->rowSize) {
894:     SETERRQ3(PETSC_ERR_PLIB, "Number of row indices %d on edge %d exceeded maximum size %d\n", rowSize, edge, mat->rowSize);
895:   }
896:   if (rowCount > mat->rowSize) {
897:     SETERRQ3(PETSC_ERR_PLIB, "Number of row indices %d on edge %d exceeded maximum size %d\n", rowCount, edge, mat->rowSize);
898:   }
899:   mat->reduceRowSize = rowCount;

901:   /* Calculate the columns ordering after reduction --
902:        colCount  - Number of columns stacked into mat
903:        colSource - Current column of mat being accessed
904:        inc       - The difference in size of the constrained matrix from the original
905:        newCols   - The column reordering, newCols[colSource] is the current column in the matrix, -1 for not present
906:   */
907:   for(f = 0, colCount = 0, colSource = 0, newCol = origColSize, inc = 0; f < numColFields; f++) {
908:     field = colFields[f];
909:     comp  = grid->fields[field].disc->bdDisc->comp;

911:     for(corner = 0; corner < 2; corner++) {
912:       node   = edges[edge*2+corner];
913:       nclass = colClasses[node];

915:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
916:         if (localNumbering == PETSC_FALSE) {
917:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
918:           for(i = 0; i < comp; i++, colSource++) {
919:             newCols[colSource] = -1;
920:           }
921:           inc       -= comp;
922:         } else {
923:           /* Put in negative indices corresponding to boundary values */
924:           for(i = 0; i < comp; i++, colCount++, colSource++) {
925:             newCols[colSource] = colCount;
926:           }
927:         }
928:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
929:         /* We must replace this field with the constraint field and prevent overwriting in element matrix */
930:         diff = grid->fields[field].constraintCompDiff;
931:         inc += diff;
932:         if (diff > 0) {
933:           /* Assume new field were previously in the last columns */
934:           for(i = 0; i < comp; i++, colCount++, colSource++)
935:             newCols[colSource] = colCount;
936:           for(i = 0; i < diff; i++, colCount++, newCol++)
937:             newCols[newCol]    = colCount;
938:         } else {
939:           /* Just squeeze matrix */
940:           for(i = 0; i < comp + diff; i++, colCount++, colSource++)
941:             newCols[colSource] = colCount;
942:           for(i = comp+diff; i < comp; i++, colSource++)
943:             newCols[colSource] = -1;
944:         }
945:       } else if (colFieldClasses[f][nclass]) {
946:         for(i = 0; i < comp; i++, colCount++, colSource++) {
947:           newCols[colSource] = colCount;
948:         }
949:       }
950:     }

952:     if (midnode >= 0) {
953:       nclass = colClasses[midnode];

955:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
956:         if (localNumbering == PETSC_FALSE) {
957:           /* Increment source pointer in value array, which corresponds to skipping constrained variables */
958:           for(i = 0; i < comp; i++, colSource++) {
959:             newCols[colSource] = -1;
960:           }
961:           inc       -= comp;
962:         } else {
963:           /* Put in negative indices corresponding to boundary values */
964:           for(i = 0; i < comp; i++, colCount++, colSource++) {
965:             newCols[colSource] = colCount;
966:           }
967:         }
968:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
969:         /* We must replace this field with the constraint field and prevent overwriting in element matrix */
970:         diff = grid->fields[field].constraintCompDiff;
971:         inc += diff;
972:         if (diff > 0) {
973:           /* Assume new field were previously in the last columns */
974:           for(i = 0; i < comp; i++, colCount++, colSource++)
975:             newCols[colSource] = colCount;
976:           for(i = 0; i < diff; i++, colCount++, newCol++)
977:             newCols[newCol]    = colCount;
978:         } else {
979:           /* Just squeeze matrix */
980:           for(i = 0; i < comp + diff; i++, colCount++, colSource++)
981:             newCols[colSource] = colCount;
982:           for(i = comp+diff; i < comp; i++, colSource++)
983:             newCols[colSource] = -1;
984:         }
985:       } else if (colFieldClasses[f][nclass]) {
986:         for(i = 0; i < comp; i++, colCount++, colSource++) {
987:           newCols[colSource] = colCount;
988:         }
989:       }
990:     }
991:   }
992: #ifdef PETSC_USE_BOPT_g
993:   if (colCount != origColSize + inc) {
994:     SETERRQ3(PETSC_ERR_PLIB, "Invalid column numbering edge: %d size: %d count: %d\n", edge, origColSize+inc, colCount);
995:   }
996:   if (colCount > mat->colSize) {
997:     SETERRQ3(PETSC_ERR_PLIB, "Number of column indices %d on edge %d exceeded maximum size %d\n", colCount, edge, mat->colSize);
998:   }
999: #endif
1000:   mat->reduceColSize = colCount;

1002:   /* Reform the element matrix: newCols[original col] = new col */
1003:   if (mat->reduceColSize != origColSize) {
1004:     if (colIsConstrained == PETSC_TRUE) {
1005:       for(row = 0; row < mat->reduceRowSize; row++)
1006:         for(col = 0; col < origColSize; col++)
1007:           if (newCols[col] >= 0)
1008:             tempArray[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
1009:       PetscMemcpy(array, tempArray, mat->reduceRowSize*mat->reduceColSize * sizeof(PetscScalar));
1010:     } else {
1011:       /* Can copy in place if no constraints were applied since BC just delete entries */
1012:       for(row = 0; row < mat->reduceRowSize; row++)
1013:         for(col = 0; col < origColSize; col++)
1014:           if (newCols[col] >= 0)
1015:             array[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
1016:     }
1017:   }

1019:   /* Calculate indices and constrained matrix elements */
1020:   for(f = 0, colCount = 0; f < numColFields; f++) {
1021:     field = colFields[f];
1022:     comp  = grid->fields[field].disc->comp;

1024:     for(corner = 0; corner < 2; corner++) {
1025:       node   = edges[edge*2+corner];
1026:       nclass = colClasses[node];
1027: 
1028:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
1029:         if (localNumbering == PETSC_TRUE) {
1030:           if (node >= numNodes)
1031:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
1032:           else
1033:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
1034:           for(i = 0; i < comp; i++, colCount++) {
1035:             colIdx[colCount] = -(startVar + i + 1);
1036:           }
1037:         }
1038:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
1039:         /* Apply P to get constraint fields */
1040:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, sOrder, field, node, colCount, CONSTRAINT_COL, mat);
1041: 
1042:         colCount  += comp + grid->fields[field].constraintCompDiff;
1043:       } else if (colFieldClasses[f][nclass]) {
1044:         if (localNumbering == PETSC_FALSE) {
1045:           startVar = colOffsets[node] + colLocalStart[field][nclass];
1046:         } else {
1047:           if (node >= numNodes)
1048:             startVar = colLocalOffsets[node-numNodes] + colLocalStart[field][nclass];
1049:           else
1050:             startVar = colOffsets[node] - colFirstVar[rank] + colLocalStart[field][nclass];
1051:         }
1052:         for(i = 0; i < comp; i++, colCount++) {
1053:           colIdx[colCount] = startVar + i;
1054:         }
1055:       }
1056:     }

1058:     if (midnode >= 0) {
1059:       nclass = colClasses[midnode];
1060: 
1061:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
1062:         if (localNumbering == PETSC_TRUE) {
1063:           if (midnode >= numNodes)
1064:             startVar = reduceLocalOffsets[midnode-numNodes] + reduceLocalStart[field][nclass];
1065:           else
1066:             startVar = reduceOffsets[midnode] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
1067:           for(i = 0; i < comp; i++, colCount++) {
1068:             colIdx[colCount] = -(startVar + i + 1);
1069:           }
1070:         }
1071:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
1072:         /* Apply P to get constraint fields */
1073:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, sOrder, field, midnode, colCount, CONSTRAINT_COL, mat);
1074: 
1075:         colCount  += comp + grid->fields[field].constraintCompDiff;
1076:       } else if (colFieldClasses[f][nclass]) {
1077:         if (localNumbering == PETSC_FALSE) {
1078:           startVar = colOffsets[midnode] + colLocalStart[field][nclass];
1079:         } else {
1080:           if (midnode >= numNodes)
1081:             startVar = colLocalOffsets[midnode-numNodes] + colLocalStart[field][nclass];
1082:           else
1083:             startVar = colOffsets[midnode] - colFirstVar[rank] + colLocalStart[field][nclass];
1084:         }
1085:         for(i = 0; i < comp; i++, colCount++) {
1086:           colIdx[colCount] = startVar + i;
1087:         }
1088:       }
1089:     }
1090:   }

1092:   return(0);
1093: }