Actual source code: inpututils.c

  1: #define PETSCDM_DLL

  3: /*
  4:        Utilities for inputing, creating and managing simple two dimensional grids
  5: */

 7:  #include src/dm/ao/aoimpl.h
 8:  #include petscbt.h
 9:  #include petscdraw.h

 11: /*
 12:     cell_n        - number of cells
 13:     max_cell      - maximum space allocated for cell
 14:     cell_vertex   - vertices of each cell
 15:     cell_edge     - edges of the cell
 16:     cell_cell     - neighbors of cell
 17:     vertex_n      - number of vertices
 18:     vertex_max    - maximum space allocated for vertices
 19:     x,y           - vertex coordinates

 21:     xmin,ymin,xmax,ymax - bounding box of grid

 23:     edge_n        - total edges in the grid
 24:     edge_vertex   - vertex of all edges 
 25:     edge_max      - maximum space allocated for edge
 26:     edge_cell     - two neighbor cells who share edge

 28:     vertex_boundary - indicates for each vertex if it is a boundary

 30: */



 36: PetscErrorCode  AOData2dGridToAOData(AOData2dGrid agrid,AOData *ao)
 37: {
 39:   PetscInt       *keys,nmax,i;
 40:   AOData         aodata;

 43:   /*
 44:       Create the database 
 45:   */
 46:   nmax = PetscMax(agrid->cell_n,agrid->vertex_n);
 47:   nmax = PetscMax(nmax,agrid->edge_n);
 48:   PetscMalloc(nmax*sizeof(PetscInt),&keys);
 49:   for (i=0; i<nmax; i++) {
 50:     keys[i] = i;
 51:   }
 52:   AODataCreateBasic(PETSC_COMM_WORLD,&aodata);
 53:     AODataKeyAdd(aodata,"cell",PETSC_DECIDE,agrid->cell_n);
 54:       AODataSegmentAdd(aodata,"cell","cell",4,agrid->cell_n,keys,agrid->cell_cell,PETSC_INT);
 55:       AODataSegmentAdd(aodata,"cell","vertex",4,agrid->cell_n,keys,agrid->cell_vertex,PETSC_INT);
 56:       AODataSegmentAdd(aodata,"cell","edge",4,agrid->cell_n,keys,agrid->cell_edge,PETSC_INT);
 57:     AODataKeyAdd(aodata,"edge",PETSC_DECIDE,agrid->edge_n);
 58:       AODataSegmentAdd(aodata,"edge","vertex",2,agrid->edge_n,keys,agrid->edge_vertex,PETSC_INT);
 59:       AODataSegmentAdd(aodata,"edge","cell",2,agrid->edge_n,keys,agrid->edge_cell,PETSC_INT);
 60:     AODataKeyAdd(aodata,"vertex",PETSC_DECIDE,agrid->vertex_n);
 61:       AODataSegmentAdd(aodata,"vertex","values",2,agrid->vertex_n,keys,agrid->vertex,PETSC_DOUBLE);
 62:       AODataSegmentAdd(aodata,"vertex","boundary",1,agrid->vertex_n,keys,agrid->vertex_boundary,PETSC_LOGICAL);
 63:   PetscFree(keys);
 64:   *ao = aodata;
 65:   return(0);
 66: }

 70: /*
 71:        User input the cell by drawing them one at a time
 72: */
 73: PetscErrorCode  AOData2dGridInput(AOData2dGrid agrid,PetscDraw draw)
 74: {
 75:   PetscDraw       popup;                           /* help window */
 76:   PetscDrawButton button;                          /* mouse button pressed */
 78:   PetscInt             cn, *cell;
 79:   PetscReal       *vertex,cx,cy;
 80:   char            title[120];

 83:   agrid->cell_max      = 500;
 84:   agrid->cell_n        = 0;
 85:   agrid->vertex_max    = 500;
 86:   agrid->vertex_n      = 0;
 87:   agrid->xmin          = PETSC_MAX;
 88:   agrid->xmax          = PETSC_MIN;
 89:   agrid->ymin          = PETSC_MAX;
 90:   agrid->ymax          = PETSC_MIN;

 92:   /*
 93:      Allocate large arrays to hold the nodes and cellrilateral lists 
 94:   */
 95:   PetscMalloc(2*agrid->vertex_max*sizeof(PetscReal),&agrid->vertex);
 96:   vertex = agrid->vertex;
 97:   PetscMalloc(4*agrid->cell_max*sizeof(PetscInt),&agrid->cell_vertex);
 98:   cell   = agrid->cell_vertex;


101:   /*
102:      Open help window and enter helpful messages
103:   */
104:   PetscDrawGetPopup(draw,&popup);
105:   PetscDrawString(popup,.1,.9,PETSC_DRAW_BLUE,"Use left button to\n   enter cell.");
106:   PetscDrawString(popup,.1,.7,PETSC_DRAW_BLUE,"Use center button to\n   end.");
107:   PetscDrawFlush(popup);

109:   PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
110:   AOData2dGridAddNode(agrid,cx,cy,&cn);
111:   cell[0] = cn;
112:   sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
113:   PetscDrawSetTitle(draw,title);
114:   while (button == BUTTON_LEFT) {
115:     /* wait for second vertex */
116:     PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
117:     if (button != BUTTON_LEFT) {
118:       SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
119:     }
120:     AOData2dGridAddNode(agrid,cx,cy,&cn);
121:     cell[4*agrid->cell_n+1] = cn;
122:     PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n]],vertex[1+2*cell[4*agrid->cell_n]],
123:                          vertex[2*cell[4*agrid->cell_n+1]],vertex[1+2*cell[4*agrid->cell_n+1]],
124:                          PETSC_DRAW_RED);
125:     sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
126:     PetscDrawSetTitle(draw,title);
127:     /* wait for third vertex */
128:     PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
129:     if (button != BUTTON_LEFT) {
130:       SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
131:     }
132:     AOData2dGridAddNode(agrid,cx,cy,&cn);
133:     cell[4*agrid->cell_n+2] = cn;
134:     PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n+1]],vertex[1+2*cell[4*agrid->cell_n+1]],
135:                          vertex[2*cell[4*agrid->cell_n+2]],vertex[1+2*cell[4*agrid->cell_n+2]],
136:                          PETSC_DRAW_RED);
137:     sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
138:     PetscDrawSetTitle(draw,title);
139:     /* wait for fourth vertex */
140:     PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
141:     if (button != BUTTON_LEFT) {
142:       SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
143:     }
144:     AOData2dGridAddNode(agrid,cx,cy,&cn);
145:     cell[4*agrid->cell_n+3] = cn;
146:     PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n+2]],vertex[1+2*cell[4*agrid->cell_n+2]],
147:                          vertex[2*cell[4*agrid->cell_n+3]],vertex[1+2*cell[4*agrid->cell_n+3]],
148:                          PETSC_DRAW_RED);
149:     PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n]],vertex[1+2*cell[4*agrid->cell_n]],
150:                          vertex[2*cell[4*agrid->cell_n+3]],vertex[1+2*cell[4*agrid->cell_n+3]],
151:                          PETSC_DRAW_RED);
152:     agrid->cell_n++;
153:     sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
154:     PetscDrawSetTitle(draw,title);

156:     /* Get the first for the next cellralateral, or BUTTON_CENTER to end */
157:     PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
158:     if (button != BUTTON_LEFT) {break;}
159:     AOData2dGridAddNode(agrid,cx,cy,&cn);
160:     cell[4*agrid->cell_n] = cn;

162:     sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
163:     PetscDrawSetTitle(draw,title);
164:   }
165:   return(0);
166: }

170: /*
171:    Changes the node numbering for the cell to make sure they are all in 
172:    clockwise ordering
173: */
174: PetscErrorCode  AOData2dGridFlipCells(AOData2dGrid agrid)
175: {
176:   PetscInt       i,*cell = agrid->cell_vertex, cell_n = agrid->cell_n;
177:   PetscReal *vertex = agrid->vertex, sign;

180:   for (i=0; i<cell_n; i++) {
181:     /*
182:        compute the quantity

184:             x0      x1    x2      x3
185:             y0      y1    y2      y3
186:      */

188:      sign = vertex[2*cell[4*i]]*vertex[1+2*cell[4*i+1]]   + vertex[2*cell[4*i+1]]*vertex[1+2*cell[4*i+2]] +
189:             vertex[2*cell[4*i+2]]*vertex[1+2*cell[4*i+3]] + vertex[2*cell[4*i+3]]*vertex[1+2*cell[4*i]]   -
190:             vertex[1+2*cell[4*i]]*vertex[2*cell[4*i+1]]   - vertex[1+2*cell[4*i+1]]*vertex[2*cell[4*i+2]] -
191:             vertex[1+2*cell[4*i+2]]*vertex[2*cell[4*i+3]] - vertex[1+2*cell[4*i+3]]*vertex[2*cell[4*i]];

193:      if (sign == 0.0) {
194:        SETERRQ(PETSC_ERR_USER,"Bad cell, zero area");
195:      } else if (sign > 0) {
196:        PetscInt q1tmp = cell[4*i+1];
197:        cell[4*i+1] = cell[4*i+3];
198:        cell[4*i+3] = q1tmp;
199:      }
200:   }
201:   return(0);
202: }

206: /*
207:      AOData2dGridAddNode - Maintains a list of nodes given so far
208: */
209: PetscErrorCode  AOData2dGridAddNode(AOData2dGrid agrid, PetscReal cx, PetscReal cy, PetscInt *cn)
210: {
211:   PetscInt i;

214:   for (i=0; i<agrid->vertex_n; i++) {
215:     if ((PetscAbsReal(agrid->vertex[2*i] - cx) < 1.e-9) && (PetscAbsReal(agrid->vertex[1+2*i] - cy) < 1.e-9)) {
216:       *cn = i;
217:       return(0);
218:     }
219:   }
220:   agrid->vertex[2*agrid->vertex_n] = cx;
221:   agrid->vertex[1+2*agrid->vertex_n] = cy;
222:   *cn     = (agrid->vertex_n)++;

224:   if (cx < agrid->xmin)      agrid->xmin = cx;
225:   else if (cx > agrid->xmax) agrid->xmax = cx;
226:   if (cy < agrid->ymin)      agrid->ymin = cy;
227:   else if (cy > agrid->ymax) agrid->ymax = cy;
228:   return(0);
229: }

233: PetscErrorCode  AOData2dGridComputeNeighbors(AOData2dGrid agrid)
234: {
236:   PetscInt  i,j,*cell_edge,*edge_cell,*edge,*cell,*neighbors,e;

239:   agrid->edge_max = 2*agrid->vertex_n;
240:   agrid->edge_n   = 0;
241:   PetscMalloc(2*agrid->edge_max*sizeof(PetscInt),&agrid->edge_vertex);
242:   edge      = agrid->edge_vertex;
243:   PetscMalloc(4*agrid->cell_max*sizeof(PetscInt),agrid->cell_edge);
244:   cell_edge = agrid->cell_edge;
245:   PetscMalloc(2*agrid->edge_max*sizeof(PetscInt),&agrid->edge_cell);
246:   edge_cell = agrid->edge_cell;

248:   cell      = agrid->cell_vertex;

250:   /*
251:        Mark all neighbors (to start) with -1 to indicate missing neighbor
252:   */
253:   for (i=0; i<2*agrid->edge_max; i++) {
254:     edge_cell[i] = -1;
255:   }

257:   for (i=0; i<agrid->cell_n; i++) {
258:     for (j=0; j<agrid->edge_n; j++) {
259:       if (cell[4*i] == edge[2*j+1] && cell[4*i+1] == edge[2*j]) {
260:         cell_edge[4*i]   = j;
261:         edge_cell[2*j+1] = i;
262:         goto found0;
263:       }
264:     }
265:     /*
266:        Add a new edge to the list 
267:     */
268:     edge_cell[2*agrid->edge_n]   = i;
269:     edge[2*agrid->edge_n]        = cell[4*i];
270:     edge[2*agrid->edge_n+1]      = cell[4*i+1];
271:     cell_edge[4*i]                = agrid->edge_n;
272:     agrid->edge_n++;
273:     found0:;
274:     for (j=0; j<agrid->edge_n; j++) {
275:       if (cell[4*i+1] == edge[2*j+1] && cell[4*i+2] == edge[2*j]) {
276:         cell_edge[4*i+1] = j;
277:         edge_cell[2*j+1] = i;
278:         goto found1;
279:       }
280:     }
281:     /*
282:        Add a new edge to the list 
283:     */
284:     edge_cell[2*agrid->edge_n]   = i;
285:     edge[2*agrid->edge_n]        = cell[4*i+1];
286:     edge[2*agrid->edge_n+1]      = cell[4*i+2];
287:     cell_edge[4*i+1]              = agrid->edge_n;
288:     agrid->edge_n++;
289:     found1:;
290:     for (j=0; j<agrid->edge_n; j++) {
291:       if (cell[4*i+2] == edge[2*j+1] && cell[4*i+3] == edge[2*j]) {
292:         cell_edge[4*i+2] = j;
293:         edge_cell[2*j+1] = i;
294:         goto found2;
295:       }
296:     }
297:     /*
298:        Add a new edge to the list 
299:     */
300:     edge_cell[2*agrid->edge_n]   = i;
301:     edge[2*agrid->edge_n]        = cell[4*i+2];
302:     edge[2*agrid->edge_n+1]      = cell[4*i+3];
303:     cell_edge[4*i+2]              = agrid->edge_n;
304:     agrid->edge_n++;
305:     found2:;
306:     for (j=0; j<agrid->edge_n; j++) {
307:       if (cell[4*i+3] == edge[2*j+1] && cell[4*i] == edge[2*j]) {
308:         cell_edge[4*i+3] = j;
309:         edge_cell[2*j+1] = i;
310:         goto found3;
311:       }
312:     }
313:     /*
314:        Add a new edge to the list 
315:     */
316:     edge_cell[2*agrid->edge_n]   = i;
317:     edge[2*agrid->edge_n]        = cell[4*i+3];
318:     edge[2*agrid->edge_n+1]      = cell[4*i];
319:     cell_edge[4*i+3]              = agrid->edge_n;
320:     agrid->edge_n++;
321:     found3:;

323:   }

325:   PetscMalloc(4*agrid->cell_n*sizeof(PetscInt),&agrid->cell_cell);
326:   neighbors = agrid->cell_cell;
327:   for (i=0; i<agrid->cell_n; i++) {
328:     for (j=0; j<4; j++) {
329:       e = 2*agrid->cell_edge[4*i+j];

331:       /* get the edge neighbor that is not the current cell */
332:       if (i == agrid->edge_cell[e]) e++;
333:       neighbors[4*i+j] = agrid->edge_cell[e];
334:     }
335:   }

337:   return(0);
338: }

342: PetscErrorCode  AOData2dGridComputeVertexBoundary(AOData2dGrid agrid)
343: {
345:   PetscInt  i,j,*count,*cell_vertex = agrid->cell_vertex;

348:   /*
349:       allocate bitarray for boundary info
350:   */
351:   PetscBTCreate(agrid->vertex_n,agrid->vertex_boundary);

353:   /*
354:       count contains number of cell that contain the given vertex 
355:   */
356:   PetscMalloc(agrid->vertex_n*sizeof(PetscInt),&count);
357:   PetscMemzero(count,agrid->vertex_n*sizeof(PetscInt));

359:   for (i=0; i<agrid->cell_n; i++) {
360:     for (j=0; j<4; j++) {
361:       count[cell_vertex[4*i+j]]++;
362:     }
363:   }


366:   for (i=0; i<agrid->vertex_n; i++) {
367:     /* UGLY! Just for a quick solution: I want Dirichlet b.c. only at left edge! */
368:     PetscTruth neumann_bc;
369:     PetscOptionsHasName(PETSC_NULL,"-dirichlet_on_left",&neumann_bc);
370:     if (neumann_bc) {
371:       if ((count[i] < 4) && (agrid->vertex[2*i] == agrid->xmin)) {
372:         PetscBTSet(agrid->vertex_boundary,i);
373:       }
374:     } else {
375:       if (count[i] < 4) {
376:         PetscBTSet(agrid->vertex_boundary,i);
377:       }
378:     }
379:   }

381:   PetscFree(count);

383:   return(0);
384: }

388: /*
389:      Show the numbering of the vertex, cell and edge
390: */
391: PetscErrorCode  AOData2dGridDraw(AOData2dGrid agrid,PetscDraw draw)
392: {
394:   PetscInt       i, *cell = agrid->cell_vertex, *edge = agrid->edge_vertex;
395:   char      str[5];
396:   PetscReal *vertex = agrid->vertex,xx,yy,xmin,xmax,ymin,ymax,h,w;

399:   w = agrid->xmax - agrid->xmin;
400:   h = agrid->ymax - agrid->ymin;
401:   xmin = agrid->xmin - .1*w;
402:   xmax = agrid->xmax + .1*w;
403:   ymin = agrid->ymin - .1*h;
404:   ymax = agrid->ymax + .1*h;
405:   PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);

407:   /*
408:      Number the vertex
409:   */
410:   for (i=0; i<agrid->vertex_n; i++) {
411:     sprintf(str,"%d",(int)i);
412:     PetscDrawString(draw,vertex[2*i],vertex[1+2*i],PETSC_DRAW_BLUE,str);
413:   }

415:   /*
416:      Number the cell
417:   */
418:   for (i=0; i<agrid->cell_n; i++) {
419:     sprintf(str,"%d",(int)i);
420:     xx = .25*(vertex[2*cell[4*i]] + vertex[2*cell[4*i+1]] + vertex[2*cell[4*i+2]] + vertex[2*cell[4*i+3]]);
421:     yy = .25*(vertex[1+2*cell[4*i]] + vertex[1+2*cell[4*i+1]] + vertex[1+2*cell[4*i+2]] + vertex[1+2*cell[4*i+3]]);
422:     PetscDrawString(draw,xx,yy,PETSC_DRAW_GREEN,str);
423:   }

425:   /*
426:      Number the edge
427:   */
428:   for (i=0; i<agrid->edge_n; i++) {
429:     sprintf(str,"%d",(int)i);
430:     xx = .5*(vertex[2*edge[2*i]] + vertex[2*edge[2*i+1]]);
431:     yy = .5*(vertex[1+2*edge[2*i]] + vertex[1+2*edge[2*i+1]]);
432:     PetscDrawLine(draw,vertex[2*edge[2*i]],vertex[1+2*edge[2*i]],vertex[2*edge[2*i+1]],vertex[1+2*edge[2*i+1]],PETSC_DRAW_BLACK);
433:     PetscDrawString(draw,xx,yy,PETSC_DRAW_VIOLET,str);
434:   }

436:   return(0);
437: }

441: /*
442:     Frees all the memory space allocated in AGrid
443: */
444: PetscErrorCode  AOData2dGridDestroy(AOData2dGrid agrid)
445: {

449:    PetscFree(agrid->vertex);
450:    PetscFree(agrid->cell_vertex);
451:    PetscFree(agrid->cell_edge);
452:    PetscFree(agrid->edge_vertex);
453:    PetscFree(agrid->edge_cell);
454:    PetscFree(agrid->cell_cell);
455:    PetscFree(agrid->vertex_boundary);
456:    PetscFree(agrid);
457:    return(0);
458: }

462: /*
463:     
464: */
465: PetscErrorCode  AOData2dGridCreate(AOData2dGrid *agrid)
466: {
469:   PetscNew(struct _n_AOData2dGrid,agrid);
470:   return(0);
471: }