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