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: }