Actual source code: inpututils.c
1: /*
2: Utilities for inputing, creating and managing simple two dimensional grids
3: */
5: #include src/dm/ao/aoimpl.h
6: #include petscbt.h
7: #include petscdraw.h
9: /*
10: cell_n - number of cells
11: max_cell - maximum space allocated for cell
12: cell_vertex - vertices of each cell
13: cell_edge - edges of the cell
14: cell_cell - neighbors of cell
15: vertex_n - number of vertices
16: vertex_max - maximum space allocated for vertices
17: x,y - vertex coordinates
19: xmin,ymin,xmax,ymax - bounding box of grid
21: edge_n - total edges in the grid
22: edge_vertex - vertex of all edges
23: edge_max - maximum space allocated for edge
24: edge_cell - two neighbor cells who share edge
26: vertex_boundary - indicates for each vertex if it is a boundary
28: */
34: PetscErrorCode AOData2dGridToAOData(AOData2dGrid agrid,AOData *ao)
35: {
37: PetscInt *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(PetscInt),&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: }
68: /*
69: User input the cell by drawing them one at a time
70: */
71: PetscErrorCode AOData2dGridInput(AOData2dGrid agrid,PetscDraw draw)
72: {
73: PetscDraw popup; /* help window */
74: PetscDrawButton button; /* mouse button pressed */
76: PetscInt cn, *cell;
77: PetscReal *vertex,cx,cy;
78: char title[120];
81: agrid->cell_max = 500;
82: agrid->cell_n = 0;
83: agrid->vertex_max = 500;
84: agrid->vertex_n = 0;
85: agrid->xmin = PETSC_MAX;
86: agrid->xmax = PETSC_MIN;
87: agrid->ymin = PETSC_MAX;
88: agrid->ymax = PETSC_MIN;
90: /*
91: Allocate large arrays to hold the nodes and cellrilateral lists
92: */
93: PetscMalloc(2*agrid->vertex_max*sizeof(PetscReal),&agrid->vertex);
94: vertex = agrid->vertex;
95: PetscMalloc(4*agrid->cell_max*sizeof(PetscInt),&agrid->cell_vertex);
96: cell = agrid->cell_vertex;
99: /*
100: Open help window and enter helpful messages
101: */
102: PetscDrawGetPopup(draw,&popup);
103: PetscDrawString(popup,.1,.9,PETSC_DRAW_BLUE,"Use left button to\n enter cell.");
104: PetscDrawString(popup,.1,.7,PETSC_DRAW_BLUE,"Use center button to\n end.");
105: PetscDrawFlush(popup);
107: PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
108: AOData2dGridAddNode(agrid,cx,cy,&cn);
109: cell[0] = cn;
110: sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
111: PetscDrawSetTitle(draw,title);
112: while (button == BUTTON_LEFT) {
113: /* wait for second vertex */
114: PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
115: if (button != BUTTON_LEFT) {
116: SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
117: }
118: AOData2dGridAddNode(agrid,cx,cy,&cn);
119: cell[4*agrid->cell_n+1] = cn;
120: PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n]],vertex[1+2*cell[4*agrid->cell_n]],
121: vertex[2*cell[4*agrid->cell_n+1]],vertex[1+2*cell[4*agrid->cell_n+1]],
122: PETSC_DRAW_RED);
123: sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
124: PetscDrawSetTitle(draw,title);
125: /* wait for third vertex */
126: PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
127: if (button != BUTTON_LEFT) {
128: SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
129: }
130: AOData2dGridAddNode(agrid,cx,cy,&cn);
131: cell[4*agrid->cell_n+2] = cn;
132: PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n+1]],vertex[1+2*cell[4*agrid->cell_n+1]],
133: vertex[2*cell[4*agrid->cell_n+2]],vertex[1+2*cell[4*agrid->cell_n+2]],
134: PETSC_DRAW_RED);
135: sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
136: PetscDrawSetTitle(draw,title);
137: /* wait for fourth vertex */
138: PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
139: if (button != BUTTON_LEFT) {
140: SETERRQ(PETSC_ERR_USER,"Must press left button to complete quadrilateral");
141: }
142: AOData2dGridAddNode(agrid,cx,cy,&cn);
143: cell[4*agrid->cell_n+3] = cn;
144: PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n+2]],vertex[1+2*cell[4*agrid->cell_n+2]],
145: vertex[2*cell[4*agrid->cell_n+3]],vertex[1+2*cell[4*agrid->cell_n+3]],
146: PETSC_DRAW_RED);
147: PetscDrawLine(draw,vertex[2*cell[4*agrid->cell_n]],vertex[1+2*cell[4*agrid->cell_n]],
148: vertex[2*cell[4*agrid->cell_n+3]],vertex[1+2*cell[4*agrid->cell_n+3]],
149: PETSC_DRAW_RED);
150: agrid->cell_n++;
151: sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
152: PetscDrawSetTitle(draw,title);
154: /* Get the first for the next cellralateral, or BUTTON_CENTER to end */
155: PetscDrawGetMouseButton(draw,&button,&cx,&cy,PETSC_NULL,PETSC_NULL);
156: if (button != BUTTON_LEFT) {break;}
157: AOData2dGridAddNode(agrid,cx,cy,&cn);
158: cell[4*agrid->cell_n] = cn;
160: sprintf(title,"Input grid: Number vertex %d Number cell %d",(int)agrid->vertex_n,(int)agrid->cell_n);
161: PetscDrawSetTitle(draw,title);
162: }
163: return(0);
164: }
168: /*
169: Changes the node numbering for the cell to make sure they are all in
170: clockwise ordering
171: */
172: PetscErrorCode AOData2dGridFlipCells(AOData2dGrid agrid)
173: {
174: PetscInt i,*cell = agrid->cell_vertex, cell_n = agrid->cell_n;
175: PetscReal *vertex = agrid->vertex, sign;
178: for (i=0; i<cell_n; i++) {
179: /*
180: compute the quantity
182: x0 x1 x2 x3
183: y0 y1 y2 y3
184: */
186: 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]] +
187: 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]] -
188: 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]] -
189: 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]];
191: if (sign == 0.0) {
192: SETERRQ(PETSC_ERR_USER,"Bad cell, zero area");
193: } else if (sign > 0) {
194: PetscInt q1tmp = cell[4*i+1];
195: cell[4*i+1] = cell[4*i+3];
196: cell[4*i+3] = q1tmp;
197: }
198: }
199: return(0);
200: }
204: /*
205: AOData2dGridAddNode - Maintains a list of nodes given so far
206: */
207: PetscErrorCode AOData2dGridAddNode(AOData2dGrid agrid, PetscReal cx, PetscReal cy, PetscInt *cn)
208: {
209: PetscInt i;
212: for (i=0; i<agrid->vertex_n; i++) {
213: if ((PetscAbsReal(agrid->vertex[2*i] - cx) < 1.e-9) && (PetscAbsReal(agrid->vertex[1+2*i] - cy) < 1.e-9)) {
214: *cn = i;
215: return(0);
216: }
217: }
218: agrid->vertex[2*agrid->vertex_n] = cx;
219: agrid->vertex[1+2*agrid->vertex_n] = cy;
220: *cn = (agrid->vertex_n)++;
222: if (cx < agrid->xmin) agrid->xmin = cx;
223: else if (cx > agrid->xmax) agrid->xmax = cx;
224: if (cy < agrid->ymin) agrid->ymin = cy;
225: else if (cy > agrid->ymax) agrid->ymax = cy;
226: return(0);
227: }
231: PetscErrorCode AOData2dGridComputeNeighbors(AOData2dGrid agrid)
232: {
234: PetscInt i,j,*cell_edge,*edge_cell,*edge,*cell,*neighbors,e;
237: agrid->edge_max = 2*agrid->vertex_n;
238: agrid->edge_n = 0;
239: PetscMalloc(2*agrid->edge_max*sizeof(PetscInt),&agrid->edge_vertex);
240: edge = agrid->edge_vertex;
241: PetscMalloc(4*agrid->cell_max*sizeof(PetscInt),agrid->cell_edge);
242: cell_edge = agrid->cell_edge;
243: PetscMalloc(2*agrid->edge_max*sizeof(PetscInt),&agrid->edge_cell);
244: edge_cell = agrid->edge_cell;
246: cell = agrid->cell_vertex;
248: /*
249: Mark all neighbors (to start) with -1 to indicate missing neighbor
250: */
251: for (i=0; i<2*agrid->edge_max; i++) {
252: edge_cell[i] = -1;
253: }
255: for (i=0; i<agrid->cell_n; i++) {
256: for (j=0; j<agrid->edge_n; j++) {
257: if (cell[4*i] == edge[2*j+1] && cell[4*i+1] == edge[2*j]) {
258: cell_edge[4*i] = j;
259: edge_cell[2*j+1] = i;
260: goto found0;
261: }
262: }
263: /*
264: Add a new edge to the list
265: */
266: edge_cell[2*agrid->edge_n] = i;
267: edge[2*agrid->edge_n] = cell[4*i];
268: edge[2*agrid->edge_n+1] = cell[4*i+1];
269: cell_edge[4*i] = agrid->edge_n;
270: agrid->edge_n++;
271: found0:;
272: for (j=0; j<agrid->edge_n; j++) {
273: if (cell[4*i+1] == edge[2*j+1] && cell[4*i+2] == edge[2*j]) {
274: cell_edge[4*i+1] = j;
275: edge_cell[2*j+1] = i;
276: goto found1;
277: }
278: }
279: /*
280: Add a new edge to the list
281: */
282: edge_cell[2*agrid->edge_n] = i;
283: edge[2*agrid->edge_n] = cell[4*i+1];
284: edge[2*agrid->edge_n+1] = cell[4*i+2];
285: cell_edge[4*i+1] = agrid->edge_n;
286: agrid->edge_n++;
287: found1:;
288: for (j=0; j<agrid->edge_n; j++) {
289: if (cell[4*i+2] == edge[2*j+1] && cell[4*i+3] == edge[2*j]) {
290: cell_edge[4*i+2] = j;
291: edge_cell[2*j+1] = i;
292: goto found2;
293: }
294: }
295: /*
296: Add a new edge to the list
297: */
298: edge_cell[2*agrid->edge_n] = i;
299: edge[2*agrid->edge_n] = cell[4*i+2];
300: edge[2*agrid->edge_n+1] = cell[4*i+3];
301: cell_edge[4*i+2] = agrid->edge_n;
302: agrid->edge_n++;
303: found2:;
304: for (j=0; j<agrid->edge_n; j++) {
305: if (cell[4*i+3] == edge[2*j+1] && cell[4*i] == edge[2*j]) {
306: cell_edge[4*i+3] = j;
307: edge_cell[2*j+1] = i;
308: goto found3;
309: }
310: }
311: /*
312: Add a new edge to the list
313: */
314: edge_cell[2*agrid->edge_n] = i;
315: edge[2*agrid->edge_n] = cell[4*i+3];
316: edge[2*agrid->edge_n+1] = cell[4*i];
317: cell_edge[4*i+3] = agrid->edge_n;
318: agrid->edge_n++;
319: found3:;
321: }
323: PetscMalloc(4*agrid->cell_n*sizeof(PetscInt),&agrid->cell_cell);
324: neighbors = agrid->cell_cell;
325: for (i=0; i<agrid->cell_n; i++) {
326: for (j=0; j<4; j++) {
327: e = 2*agrid->cell_edge[4*i+j];
329: /* get the edge neighbor that is not the current cell */
330: if (i == agrid->edge_cell[e]) e++;
331: neighbors[4*i+j] = agrid->edge_cell[e];
332: }
333: }
335: return(0);
336: }
340: PetscErrorCode AOData2dGridComputeVertexBoundary(AOData2dGrid agrid)
341: {
343: PetscInt i,j,*count,*cell_vertex = agrid->cell_vertex;
346: /*
347: allocate bitarray for boundary info
348: */
349: PetscBTCreate(agrid->vertex_n,agrid->vertex_boundary);
351: /*
352: count contains number of cell that contain the given vertex
353: */
354: PetscMalloc(agrid->vertex_n*sizeof(PetscInt),&count);
355: PetscMemzero(count,agrid->vertex_n*sizeof(PetscInt));
357: for (i=0; i<agrid->cell_n; i++) {
358: for (j=0; j<4; j++) {
359: count[cell_vertex[4*i+j]]++;
360: }
361: }
364: for (i=0; i<agrid->vertex_n; i++) {
365: /* UGLY! Just for a quick solution: I want Dirichlet b.c. only at left edge! */
366: PetscTruth neumann_bc;
367: PetscOptionsHasName(PETSC_NULL,"-dirichlet_on_left",&neumann_bc);
368: if (neumann_bc) {
369: if ((count[i] < 4) && (agrid->vertex[2*i] == agrid->xmin)) {
370: PetscBTSet(agrid->vertex_boundary,i);
371: }
372: } else {
373: if (count[i] < 4) {
374: PetscBTSet(agrid->vertex_boundary,i);
375: }
376: }
377: }
379: PetscFree(count);
381: return(0);
382: }
386: /*
387: Show the numbering of the vertex, cell and edge
388: */
389: PetscErrorCode AOData2dGridDraw(AOData2dGrid agrid,PetscDraw draw)
390: {
392: PetscInt i, *cell = agrid->cell_vertex, *edge = agrid->edge_vertex;
393: char str[5];
394: PetscReal *vertex = agrid->vertex,xx,yy,xmin,xmax,ymin,ymax,h,w;
397: w = agrid->xmax - agrid->xmin;
398: h = agrid->ymax - agrid->ymin;
399: xmin = agrid->xmin - .1*w;
400: xmax = agrid->xmax + .1*w;
401: ymin = agrid->ymin - .1*h;
402: ymax = agrid->ymax + .1*h;
403: PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);
405: /*
406: Number the vertex
407: */
408: for (i=0; i<agrid->vertex_n; i++) {
409: sprintf(str,"%d",(int)i);
410: PetscDrawString(draw,vertex[2*i],vertex[1+2*i],PETSC_DRAW_BLUE,str);
411: }
413: /*
414: Number the cell
415: */
416: for (i=0; i<agrid->cell_n; i++) {
417: sprintf(str,"%d",(int)i);
418: 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]]);
419: 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]]);
420: PetscDrawString(draw,xx,yy,PETSC_DRAW_GREEN,str);
421: }
423: /*
424: Number the edge
425: */
426: for (i=0; i<agrid->edge_n; i++) {
427: sprintf(str,"%d",(int)i);
428: xx = .5*(vertex[2*edge[2*i]] + vertex[2*edge[2*i+1]]);
429: yy = .5*(vertex[1+2*edge[2*i]] + vertex[1+2*edge[2*i+1]]);
430: 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);
431: PetscDrawString(draw,xx,yy,PETSC_DRAW_VIOLET,str);
432: }
434: return(0);
435: }
439: /*
440: Frees all the memory space allocated in AGrid
441: */
442: PetscErrorCode AOData2dGridDestroy(AOData2dGrid agrid)
443: {
447: PetscFree(agrid->vertex);
448: PetscFree(agrid->cell_vertex);
449: PetscFree(agrid->cell_edge);
450: PetscFree(agrid->edge_vertex);
451: PetscFree(agrid->edge_cell);
452: PetscFree(agrid->cell_cell);
453: PetscFree(agrid->vertex_boundary);
454: PetscFree(agrid);
455: return(0);
456: }
460: /*
461:
462: */
463: PetscErrorCode AOData2dGridCreate(AOData2dGrid *agrid)
464: {
467: PetscNew(struct _p_AOData2dGrid,agrid);
468: return(0);
469: }