Actual source code: inpututils.c

  1: /* $Id: inpututils.c,v 1.19 2001/08/07 21:31:52 bsmith Exp $ */

  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: */



 34: int AOData2dGridToAOData(AOData2dGrid agrid,AOData *ao)
 35: {
 36:   int        ierr;
 37:   int        *keys,nmax,i;
 38:   AOData     aodata;

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

 66: /*
 67:        User input the cell by drawing them one at a time
 68: */
 69: int AOData2dGridInput(AOData2dGrid agrid,PetscDraw draw)
 70: {
 71:   PetscDraw       popup;                           /* help window */
 72:   PetscDrawButton button;                          /* mouse button pressed */
 73:   int             cn, ierr,*cell;
 74:   PetscReal       *vertex,cx,cy;
 75:   char            title[120];

 78:   agrid->cell_max      = 500;
 79:   agrid->cell_n        = 0;
 80:   agrid->vertex_max    = 500;
 81:   agrid->vertex_n      = 0;
 82:   agrid->xmin          = PETSC_MAX;
 83:   agrid->xmax          = PETSC_MIN;
 84:   agrid->ymin          = PETSC_MAX;
 85:   agrid->ymax          = PETSC_MIN;

 87:   /*
 88:      Allocate large arrays to hold the nodes and cellrilateral lists 
 89:   */
 90:   ierr   = PetscMalloc(2*agrid->vertex_max*sizeof(PetscReal),&agrid->vertex);
 91:   vertex = agrid->vertex;
 92:   ierr   = PetscMalloc(4*agrid->cell_max*sizeof(int),&agrid->cell_vertex);
 93:   cell   = agrid->cell_vertex;


 96:   /*
 97:      Open help window and enter helpful messages
 98:   */
 99:   PetscDrawGetPopup(draw,&popup);
100:   PetscDrawString(popup,.1,.9,PETSC_DRAW_BLUE,"Use left button ton   enter cell.");
101:   PetscDrawString(popup,.1,.7,PETSC_DRAW_BLUE,"Use center button ton   end.");
102:   PetscDrawFlush(popup);

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

151:     /* Get the first for the next cellralateral, or BUTTON_CENTER to end */
152:     ierr     = PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
153:     if (button != BUTTON_LEFT) {break;}
154:     ierr     = AOData2dGridAddNode(agrid,cx,cy,&cn);
155:     cell[4*agrid->cell_n] = cn;

157:     sprintf(title,"Input grid: Number vertex %d Number cell %d",agrid->vertex_n,agrid->cell_n);
158:     PetscDrawSetTitle(draw,title);
159:   }
160:   return(0);
161: }

163: /*
164:    Changes the node numbering for the cell to make sure they are all in 
165:    clockwise ordering
166: */
167: int AOData2dGridFlipCells(AOData2dGrid agrid)
168: {
169:   int       i,*cell = agrid->cell_vertex, cell_n = agrid->cell_n;
170:   PetscReal *vertex = agrid->vertex, sign;

173:   for (i=0; i<cell_n; i++) {
174:     /*
175:        compute the quantity

177:             x0      x1    x2      x3
178:             y0      y1    y2      y3
179:      */

181:      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]] +
182:             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]]   -
183:             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]] -
184:             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]];

186:      if (sign == 0.0) {
187:        SETERRQ(1,"Bad cell");
188:      } else if (sign > 0) {
189:        int q1tmp = cell[4*i+1];
190:        cell[4*i+1] = cell[4*i+3];
191:        cell[4*i+3] = q1tmp;
192:      }
193:   }
194:   return(0);
195: }

197: /*
198:      AOData2dGridAddNode - Maintains a list of nodes given so far
199: */
200: int AOData2dGridAddNode(AOData2dGrid agrid, PetscReal cx, PetscReal cy, int *cn)
201: {
202:   int i;

205:   for (i=0; i<agrid->vertex_n; i++) {
206:     if ((PetscAbsReal(agrid->vertex[2*i] - cx) < 1.e-9) && (PetscAbsReal(agrid->vertex[1+2*i] - cy) < 1.e-9)) {
207:       *cn = i;
208:       return(0);
209:     }
210:   }
211:   agrid->vertex[2*agrid->vertex_n] = cx;
212:   agrid->vertex[1+2*agrid->vertex_n] = cy;
213:   *cn     = (agrid->vertex_n)++;

215:   if (cx < agrid->xmin)      agrid->xmin = cx;
216:   else if (cx > agrid->xmax) agrid->xmax = cx;
217:   if (cy < agrid->ymin)      agrid->ymin = cy;
218:   else if (cy > agrid->ymax) agrid->ymax = cy;
219:   return(0);
220: }

222: int AOData2dGridComputeNeighbors(AOData2dGrid agrid)
223: {
224:   int  i,j,*cell_edge,*edge_cell,*edge,*cell,*neighbors,e,ierr;

227:   agrid->edge_max = 2*agrid->vertex_n;
228:   agrid->edge_n   = 0;
229:   ierr      = PetscMalloc(2*agrid->edge_max*sizeof(int),&agrid->edge_vertex);
230:   edge      = agrid->edge_vertex;
231:   ierr      = PetscMalloc(4*agrid->cell_max*sizeof(int),agrid->cell_edge);
232:   cell_edge = agrid->cell_edge;
233:   ierr      = PetscMalloc(2*agrid->edge_max*sizeof(int),&agrid->edge_cell);
234:   edge_cell = agrid->edge_cell;

236:   cell      = agrid->cell_vertex;

238:   /*
239:        Mark all neighbors (to start) with -1 to indicate missing neighbor
240:   */
241:   for (i=0; i<2*agrid->edge_max; i++) {
242:     edge_cell[i] = -1;
243:   }

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

311:   }

313:   PetscMalloc(4*agrid->cell_n*sizeof(int),&agrid->cell_cell);
314:   neighbors = agrid->cell_cell;
315:   for (i=0; i<agrid->cell_n; i++) {
316:     for (j=0; j<4; j++) {
317:       e = 2*agrid->cell_edge[4*i+j];

319:       /* get the edge neighbor that is not the current cell */
320:       if (i == agrid->edge_cell[e]) e++;
321:       neighbors[4*i+j] = agrid->edge_cell[e];
322:     }
323:   }

325:   return(0);
326: }

328: int AOData2dGridComputeVertexBoundary(AOData2dGrid agrid)
329: {
330:   int  i,j,*count,*cell_vertex = agrid->cell_vertex,ierr;

333:   /*
334:       allocate bitarray for boundary info
335:   */
336:   PetscBTCreate(agrid->vertex_n,agrid->vertex_boundary);

338:   /*
339:       count contains number of cell that contain the given vertex 
340:   */
341:   PetscMalloc(agrid->vertex_n*sizeof(int),&count);
342:   PetscMemzero(count,agrid->vertex_n*sizeof(int));

344:   for (i=0; i<agrid->cell_n; i++) {
345:     for (j=0; j<4; j++) {
346:       count[cell_vertex[4*i+j]]++;
347:     }
348:   }


351:   for (i=0; i<agrid->vertex_n; i++) {
352:     /* UGLY! Just for a quick solution: I want Dirichlet b.c. only at left edge! */
353:     PetscTruth neumann_bc;
354:     PetscOptionsHasName(PETSC_NULL,"-dirichlet_on_left",&neumann_bc);
355:     if (neumann_bc) {
356:       if ((count[i] < 4) && (agrid->vertex[2*i] == agrid->xmin)) {
357:         PetscBTSet(agrid->vertex_boundary,i);
358:       }
359:     } else {
360:       if (count[i] < 4) {
361:         PetscBTSet(agrid->vertex_boundary,i);
362:       }
363:     }
364:   }

366:   PetscFree(count);

368:   return(0);
369: }

371: /*
372:      Show the numbering of the vertex, cell and edge
373: */
374: int AOData2dGridDraw(AOData2dGrid agrid,PetscDraw draw)
375: {
376:   int       i, *cell = agrid->cell_vertex, *edge = agrid->edge_vertex,ierr;
377:   char      str[5];
378:   PetscReal *vertex = agrid->vertex,xx,yy,xmin,xmax,ymin,ymax,h,w;

381:   w = agrid->xmax - agrid->xmin;
382:   h = agrid->ymax - agrid->ymin;
383:   xmin = agrid->xmin - .1*w;
384:   xmax = agrid->xmax + .1*w;
385:   ymin = agrid->ymin - .1*h;
386:   ymax = agrid->ymax + .1*h;
387:   PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);

389:   /*
390:      Number the vertex
391:   */
392:   for (i=0; i<agrid->vertex_n; i++) {
393:     sprintf(str,"%d",i);
394:     PetscDrawString(draw,vertex[2*i],vertex[1+2*i],PETSC_DRAW_BLUE,str);
395:   }

397:   /*
398:      Number the cell
399:   */
400:   for (i=0; i<agrid->cell_n; i++) {
401:     sprintf(str,"%d",i);
402:     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]]);
403:     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]]);
404:     PetscDrawString(draw,xx,yy,PETSC_DRAW_GREEN,str);
405:   }

407:   /*
408:      Number the edge
409:   */
410:   for (i=0; i<agrid->edge_n; i++) {
411:     sprintf(str,"%d",i);
412:     xx = .5*(vertex[2*edge[2*i]] + vertex[2*edge[2*i+1]]);
413:     yy = .5*(vertex[1+2*edge[2*i]] + vertex[1+2*edge[2*i+1]]);
414:     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);
415:     PetscDrawString(draw,xx,yy,PETSC_DRAW_VIOLET,str);
416:   }

418:   return(0);
419: }

421: /*
422:     Frees all the memory space allocated in AGrid
423: */
424: int AOData2dGridDestroy(AOData2dGrid agrid)
425: {

429:    PetscFree(agrid->vertex);
430:    PetscFree(agrid->cell_vertex);
431:    PetscFree(agrid->cell_edge);
432:    PetscFree(agrid->edge_vertex);
433:    PetscFree(agrid->edge_cell);
434:    PetscFree(agrid->cell_cell);
435:    PetscFree(agrid->vertex_boundary);
436:    PetscFree(agrid);
437:    return(0);
438: }

440: /*
441:     
442: */
443: int AOData2dGridCreate(AOData2dGrid *agrid)
444: {
447:   PetscNew(struct _p_AOData2dGrid,agrid);
448:   return(0);
449: }