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: int PrintVecIndices_Private(Grid grid, const char option[], int field, int node, int comp, int rowStart, int *rowIdx) {
 11:   MPI_Comm   comm;
 12:   int        rank;
 13:   int        var;
 14:   PetscTruth opt;
 15:   int        ierr;

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

 28: /*
 29:   Reduction:

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

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

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

159:   return(0);
160: }

162: /*
163:   Projection:

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

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

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

268:   return(0);
269: }

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

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

322:     for(corner = 0; corner < 2; corner++) {
323:       node   = edges[edge*2+corner];
324:       nclass = classes[node];

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

384:     if (midnode >= 0) {
385:       nclass = classes[midnode];

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

456:   return(0);
457: }

459: /*--------------------------------------------- Element Matrix Functions --------------------------------------------*/
460: /*
461:   Element Matrix Structure:

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

465:   Reduction:

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

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

546:     for(corner = 0; corner < numCorners; corner++) {
547:       MeshGetNodeFromElement(mesh, elem, corner, &node);
548:       nclass = rowClasses[node];

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

619:   /* Calculate the columns ordering after reduction --
620:        colCount  - Number of columns stacked into mat
621:        colSource - Current column of mat being accessed
622:        inc       - The difference in size of the constrained matrix from the original
623:        newCols   - The column reordering, newCols[colSource] is the current column in the matrix, -1 for not present
624:   */
625:   for(f = 0, colCount = 0, colSource = 0, newCol = origColSize, inc = 0; f < numColFields; f++) {
626:     field = colFields[f];
627:     comp  = grid->fields[field].disc->comp;

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

680:   /* Reform the element matrix: newCols[original col] = new col */
681:   if (mat->reduceColSize != origColSize) {
682:     if (colIsConstrained == PETSC_TRUE) {
683:       for(row = 0; row < mat->reduceRowSize; row++)
684:         for(col = 0; col < origColSize; col++)
685:           if (newCols[col] >= 0)
686:             tempArray[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
687:       PetscMemcpy(array, tempArray, mat->reduceRowSize*mat->reduceColSize * sizeof(PetscScalar));
688:     } else {
689:       /* Can copy in place if no constraints were applied since BC just delete entries */
690:       for(row = 0; row < mat->reduceRowSize; row++)
691:         for(col = 0; col < origColSize; col++)
692:           if (newCols[col] >= 0)
693:             array[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
694:     }
695:   }

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

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

737:   return(0);
738: }

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

786:   VarOrderingGetClassMap(tOrder, &rowMap);
787:   VarOrderingGetClassMap(sOrder, &colMap);
788:   numNodes              = rowMap->numNodes;
789:   numRowFields          = rowMap->numFields;
790:   rowFields             = rowMap->fields;
791:   rowFieldClasses       = rowMap->fieldClasses;
792:   rowReduceFieldClasses = rowMap->reduceFieldClasses;
793:   rowClasses            = rowMap->classes;
794:   rowIsReduced          = rowMap->isReduced;
795:   rowIsConstrained      = rowMap->isConstrained;
796:   rowIsConst            = rowMap->isClassConstrained;
797:   numColFields          = colMap->numFields;
798:   colFields             = colMap->fields;
799:   colFieldClasses       = colMap->fieldClasses;
800:   colReduceFieldClasses = colMap->reduceFieldClasses;
801:   colClasses            = colMap->classes;
802:   colIsReduced          = colMap->isReduced;
803:   colIsConstrained      = colMap->isConstrained;
804:   colIsConst            = colMap->isClassConstrained;
805:   if ((rowIsReduced == PETSC_TRUE) || (colIsReduced == PETSC_TRUE)) {
806:     reduceFirstVar     = reduceOrder->firstVar;
807:     reduceOffsets      = reduceOrder->offsets;
808:     reduceLocalOffsets = reduceOrder->localOffsets;
809:     reduceLocalStart   = reduceOrder->localStart;
810:   }
811:   MeshGetBdElementFromEdge(grid->mesh, edge, &elem);
812:   for(f = 0, rowCount = 0, rowSource = 0, inc = 0; f < numRowFields; f++) {
813:     field = rowFields[f];
814:     comp  = grid->fields[field].disc->comp;

816:     for(corner = 0; corner < numCorners; corner++) {
817:       node   = elements[elem*numCorners+corner];
818:       nclass = rowClasses[node];

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

889:   /* Calculate the columns ordering after reduction --
890:        colCount  - Number of columns stacked into mat
891:        colSource - Current column of mat being accessed
892:        inc       - The difference in size of the constrained matrix from the original
893:        newCols   - The column reordering, newCols[colSource] is the current column in the matrix, -1 for not present
894:   */
895:   for(f = 0, colCount = 0, colSource = 0, newCol = origColSize, inc = 0; f < numColFields; f++) {
896:     field = colFields[f];
897:     comp  = grid->fields[field].disc->bdDisc->comp;

899:     for(corner = 0; corner < 2; corner++) {
900:       node   = edges[edge*2+corner];
901:       nclass = colClasses[node];

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

940:     if (midnode >= 0) {
941:       nclass = colClasses[midnode];

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

990:   /* Reform the element matrix: newCols[original col] = new col */
991:   if (mat->reduceColSize != origColSize) {
992:     if (colIsConstrained == PETSC_TRUE) {
993:       for(row = 0; row < mat->reduceRowSize; row++)
994:         for(col = 0; col < origColSize; col++)
995:           if (newCols[col] >= 0)
996:             tempArray[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
997:       PetscMemcpy(array, tempArray, mat->reduceRowSize*mat->reduceColSize * sizeof(PetscScalar));
998:     } else {
999:       /* Can copy in place if no constraints were applied since BC just delete entries */
1000:       for(row = 0; row < mat->reduceRowSize; row++)
1001:         for(col = 0; col < origColSize; col++)
1002:           if (newCols[col] >= 0)
1003:             array[row*mat->reduceColSize+newCols[col]] = array[row*origColSize+col];
1004:     }
1005:   }

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

1012:     for(corner = 0; corner < 2; corner++) {
1013:       node   = edges[edge*2+corner];
1014:       nclass = colClasses[node];
1015: 
1016:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
1017:         if (localNumbering == PETSC_TRUE) {
1018:           if (node >= numNodes)
1019:             startVar = reduceLocalOffsets[node-numNodes] + reduceLocalStart[field][nclass];
1020:           else
1021:             startVar = reduceOffsets[node] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
1022:           for(i = 0; i < comp; i++, colCount++) {
1023:             colIdx[colCount] = -(startVar + i + 1);
1024:           }
1025:         }
1026:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
1027:         /* Apply P to get constraint fields */
1028:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, sOrder, field, node, colCount, CONSTRAINT_COL, mat);
1029: 
1030:         colCount  += comp + grid->fields[field].constraintCompDiff;
1031:       } else if (colFieldClasses[f][nclass]) {
1032:         if (localNumbering == PETSC_FALSE) {
1033:           startVar = colOffsets[node] + colLocalStart[field][nclass];
1034:         } else {
1035:           if (node >= numNodes)
1036:             startVar = colLocalOffsets[node-numNodes] + colLocalStart[field][nclass];
1037:           else
1038:             startVar = colOffsets[node] - colFirstVar[rank] + colLocalStart[field][nclass];
1039:         }
1040:         for(i = 0; i < comp; i++, colCount++) {
1041:           colIdx[colCount] = startVar + i;
1042:         }
1043:       }
1044:     }

1046:     if (midnode >= 0) {
1047:       nclass = colClasses[midnode];
1048: 
1049:       if ((colIsReduced == PETSC_TRUE) && (colReduceFieldClasses[f][nclass])) {
1050:         if (localNumbering == PETSC_TRUE) {
1051:           if (midnode >= numNodes)
1052:             startVar = reduceLocalOffsets[midnode-numNodes] + reduceLocalStart[field][nclass];
1053:           else
1054:             startVar = reduceOffsets[midnode] - reduceFirstVar[rank] + reduceLocalStart[field][nclass];
1055:           for(i = 0; i < comp; i++, colCount++) {
1056:             colIdx[colCount] = -(startVar + i + 1);
1057:           }
1058:         }
1059:       } else if ((colIsConstrained == PETSC_TRUE) && (colIsConst[nclass]) && (grid->fields[field].isConstrained == PETSC_TRUE)) {
1060:         /* Apply P to get constraint fields */
1061:         (*constCtx->ops->constrainelemmat)(constCtx, grid->mesh, sOrder, field, midnode, colCount, CONSTRAINT_COL, mat);
1062: 
1063:         colCount  += comp + grid->fields[field].constraintCompDiff;
1064:       } else if (colFieldClasses[f][nclass]) {
1065:         if (localNumbering == PETSC_FALSE) {
1066:           startVar = colOffsets[midnode] + colLocalStart[field][nclass];
1067:         } else {
1068:           if (midnode >= numNodes)
1069:             startVar = colLocalOffsets[midnode-numNodes] + colLocalStart[field][nclass];
1070:           else
1071:             startVar = colOffsets[midnode] - colFirstVar[rank] + colLocalStart[field][nclass];
1072:         }
1073:         for(i = 0; i < comp; i++, colCount++) {
1074:           colIdx[colCount] = startVar + i;
1075:         }
1076:       }
1077:     }
1078:   }

1080:   return(0);
1081: }