/* $Log: newdata.c,v $ * Revision 1.5 1995/03/20 14:56:04 martenl * Too much to mention... * * Revision 1.4 1995/03/12 14:31:10 martenl * Added new types of boundaries * * Revision 1.3 1995/03/11 13:53:29 martenl * fixed new state stuff for multiple modules * * Revision 1.2 1995/03/10 13:58:21 martenl * minor fixes * * Revision 1.1 1995/03/10 12:12:27 martenl * Initial revision * * * */ #include #include #include #include #include "eq.bm" #include "ns.bm" #include "libsx.h" /* gets us in the door with libsx */ #include "globals.h" #include "geodata.h" #include "crosshair.h" #include "kraftwerk.h" #include "post.h" #include "io.h" #include "graph.h" #include "grid.h" #include "boundary.h" #include "fortran.h" #include "workarea.h" #include "module.h" #define min(x, y) (((x) < (y)) ? (x) : (y)) #define max(x, y) (((x) > (y)) ? (x) : (y)) int evalExpr(char *expr, float xx, float yy, float *value); void getDataType(); void getDefaultValues(); int getValue(int i, int j, float x, float y, float *value); void fill(float *x,float *y, int np); int update; int previousN[NB]; int previousState; BoundaryCondition previousBC[10]; int positionFilePointer(FILE *stream, char *tag); void EQMouseDownByElement(Widget w, int button, int x, int y, void *nulldata); void EQMouseMotion(Widget w, int x, int y, void *data); int getCheck(); float value ; float rubberX1, rubberY1; float rubberX2, rubberY2; int currentItem = 0; EqData *eqdata[15]; EqDataUI *eqUI[15]; EqData *eqbc[15]; EqDataUI *bcUI[15]; EqDataUI equationUI[15]; EqDataUI boundaryUI[15]; int type[15]; typedef struct { char *text; Widget label; Widget butt; } variable; variable ns[10]; Widget window; Widget title; Widget equation; Widget bctext; Widget info; Widget section[2], button[2], text[2], input[2]; Widget doneB, cancelB, eraseB; int bctype; Widget butt[10]; /**** Should be remoced */ char solverNorm[] = "ENE"; float solverTol = 10; int solverLevels = 3; EqData cddata [] = { {0, "CONVECTIVE VELOCITIES", 2, 0}, {1, "CONDUCTIVITY" , 3, 0}, {2, "ABSORTION" , 1, 0}, {3, "RIGHT HAND SIDE" , 1, 0}, }; int numberOfEqData = 3; int numberOfEqBC = 3; int nvar = 1; /*****/ int getValue(int i, int j, float x, float y, float *value) { char expr[80]; int ierr; sprintf(expr,"%s",GetStringEntry(equationUI[i].input[j])); ierr = evalExpr(expr, x, y, value); if(ierr == 1) errorHandler("Your analytical expression contains a syntax error"); return ierr; } int getSolverData() { int ierr; TagList tags[] = { {TAG_WINDOW_LABEL, "Solver", NULL , TAG_INIT}, {TAG_LABEL, "Please specify solver data", NULL, TAG_NOINIT}, {TAG_FLOAT, "Tolerance [%] : ", &solverTol, TAG_INIT}, {TAG_INT, "Levels: ", &solverLevels, TAG_INIT}, {TAG_STRING, "Norm [MAX, RMS, ENE]: ", &solverNorm, TAG_INIT}, {TAG_DONE, NULL , NULL, TAG_NOINIT} }; /* solverTol = 10; solverLevels = 3; */ ierr = GetValues(tags); if( solverLevels > MAXLEVELS){ errorHandler("Too many refinments levels"); ierr = 10; } state = HAVE_SOLVDATA; return ierr; } void getAnalytical() { TagList tags[10]; int item, i; char line[] = "sin(cos(x))"; int ierr; item = currentItem; tags[0].tag = TAG_WINDOW_LABEL; tags[0].label = "Analytical expression"; tags[0].data = NULL; tags[0].init = TAG_INIT; tags[1].tag = TAG_LABEL; tags[1].label = "Give an analytical expression"; tags[1].data = NULL; tags[1].init = TAG_NOINIT; for(i = 0; i < module[currentModule].dataGroup[item].n; i++){ tags[i+2].tag = TAG_STRING; tags[i+2].label = module[currentModule].dataGroup[item].item[i].name; tags[i+2].data = &line; tags[i+2].init = TAG_INIT; } i = module[currentModule].dataGroup[item].n; tags[i+2].tag = TAG_DONE; tags[i+2].label = NULL; tags[i+2].data = NULL; tags[i+2].init = TAG_NOINIT; ierr = GetValues(tags); } /* * * +----------------------------------------------------------+ * | Writes the equation data to file and launches the solver | * +----------------------------------------------------------+ * */ void solve( Widget w, void *data) { FILE *stream; char *ptr; char cmd[100]; int ierr; int i, active[20], oldstate; int hh = 0, ww = 0; ierr = getSolverData(); if( ierr == 0){ pleaseWait(); saveToFile("area.scratch"); currentModule = getCheck(); ptr = NULL; ptr = (char *) getenv("FEMLAB_HOME"); if(ptr == NULL) errorHandler("FEMLAB_HOME environment variable not set"); else{ sprintf(cmd, "%s/bin/%s", ptr, module[currentModule].application); SetWidgetState(drawWindow, FALSE); system(cmd); state = HAVE_SOLUTION; SetWidgetState(drawWindow, TRUE); SetMenuItemChecked(plotMenu.item[0], FALSE); SetMenuItemChecked(plotMenu.item[2], FALSE); SetMenuItemChecked(plotMenu.item[1], TRUE); stream = fopen("solu.scratch", "r"); positionFilePointer(stream, "SOLUTION"); rmSolutionMenus(); for(i = 0; i < 20; i++) active[i] = FALSE; active[1] = TRUE; readSolution2(stream); addSolutionMenus(); for(i = 0; i < mySol[currentSolution].n + 1; i++) SetMenuItemChecked(plotMenu.item[i+5], active[i]); fclose(stream); } redisplay(w, hh, ww, data); } } void doTheInterpolation(int item, float x, float y, float *value) { int i, j, n; float dist; float sumdist; n = data[item].n; for(i = 0; i < data[item].nvalues; i++) value[i] = 0.0; sumdist = 0.0; for(j = 0; j < n; j++){ dist = (float) sqrt((double) (x - data[item].value[j].x)* (x - data[item].value[j].x) + (y - data[item].value[j].y)* (y - data[item].value[j].y) ); for(i = 0; i < data[item].nvalues; i++){ value[i] += data[item].value[j].f[i] / dist; } sumdist += 1./ dist; } for(i = 0; i < data[item].nvalues; i++) value[i] = value[i] / sumdist; } void getEigenVectors(float a11, float a12, float a21, float a22, float *e1, float *e2) { float d; float f1, f2; /* The eigenvalues */ float x1, y1, x2, y2, l; /* * +-------------------------+ * | compute the eigenvalues | * +-------------------------+ */ d = (float) sqrt( (double) ( (a11+a22)*(a11+a22)-4.*(a11*a22-a12*a21))); f1 = ((a11+a22) + d) / 2.0; f2 = ((a11+a22) - d) / 2.0; /* * +------------------------------+ * | Now compute the eigenvectors | * +------------------------------+ */ if( a12 != 0.0){ x1 = 1.0; y1 = (f1 - a11) / a12; } else{ f1 = a11; f2 = a22; x1 = 1.0; y1 = 0.0; } l = (float) sqrt((double) (x1*x1 + y1*y1)); x1 = x1 / l; y1 = y1 / l; x2 = -y1; y2 = x1; e1[0] = f1 * x1; e1[1] = f1 * y1; e2[0] = f2 * x2; e2[1] = f2 * y2; } void plotVectorsofEqData() { float value[4]; float x, y; float xu, xv; float umax, uu; int xpix, ypix; int i, node, n; int item = 100; int ierr; for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)) item = i; } if(item != 100){ if(substate == 0){ ierr = getValue(item, 0, x, y, &xu); if(ierr == 1) return; ierr = getValue(item, 1, x, y, &xv); if(ierr == 1) return; } n = data[item].n; getDrawingScale(); umax = 0.0; for( node = 0; node < mySol[currentSolution].nnode; node++){ x = mySol[currentSolution].coord[node][0]; y = mySol[currentSolution].coord[node][1]; phys2pix(&xpix, &ypix, x, y); if(substate == 0){ ierr = getValue(item, 0, x, y, &xu); ierr = getValue(item, 1, x, y, &xv); } else{ doTheInterpolation(item, xpix, ypix, value); xu = value[0]; xv = value[1]; } uu = (float) sqrt((double)xu*xu+xv*xv) ; /* if(uu <= umax*maxscalarX && uu >= umax*minscalarX){ */ if( substate == 0 || n != 0){ xu = x + maxarrwscl*arrwscl*xu; xv = y + maxarrwscl*arrwscl*xv; arrow(x, y, xu, xv); } } plotPhysBoundary(); } } void plotTensorofEqData() { float value[4]; float x, y; float a11, a12, a21, a22; float e1[2], e2[2]; float xu, xv; float umax, uu; int xpix, ypix; int i, node, n; int item = 100; int ierr; for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)) item = i; } if(item != 100){ n = data[item].n; getDrawingScale(); umax = 0.0; if(substate == 0){ ierr = getValue(item, 0, x, y, &xu); if(ierr == 1) return; ierr = getValue(item, 1, x, y, &xv); if(ierr == 1) return; ierr = getValue(item, 2, x, y, &xv); if(ierr == 1) return; } for( node = 0; node < mySol[currentSolution].nnode; node++){ x = mySol[currentSolution].coord[node][0]; y = mySol[currentSolution].coord[node][1]; phys2pix(&xpix, &ypix, x, y); if(substate == 0){ ierr = getValue(item, 0, x, y, &a11); ierr = getValue(item, 1, x, y, &a12); a21 = a12; ierr = getValue(item, 2, x, y, &a22); } else{ doTheInterpolation(item, xpix, ypix, value); a11 = value[0]; a12 = value[1]; a21 = a12; a22 = value[2]; } getEigenVectors(a11, a12, a21, a22, e1, e2); uu = (float) sqrt((double)(e1[0]*e1[0]+e1[1]*e1[1])) ; uu = max(uu, (float) sqrt((double)(e2[0]*e2[0]+e2[1]*e2[1]))) ; /* if(uu <= umax*maxscalarX && uu >= umax*minscalarX){ */ if( substate == 0 || n != 0){ xu = maxarrwscl*arrwscl*e1[0]; xv = maxarrwscl*arrwscl*e1[1]; arrow(x-.5*xu, y-.5*xv, x +.5*xu, y +.5*xv); xu = maxarrwscl*arrwscl*e2[0]; xv = maxarrwscl*arrwscl*e2[1]; arrow(x-.5*xu, y-.5*xv, x +.5*xu, y +.5*xv); } } plotPhysBoundary(); } } void plotIsolinesofEqData() { float maxscalar, minscalar, scl; int xx[NOBF+1], yy[NOBF+1]; float sc[NOBF+1]; float xu; float value[4]; int xp[10], yp[10]; float level, x, y, val; int xpix, ypix; int el, i, ilev, ii, node, nvalues; int item = 100; int ierr; for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)) item = i; } if(item != 100){ nvalues = data[item].n; getDrawingScale(); maxscalar = -100000.; minscalar = 100000.; if(substate == 0){ ierr = getValue(item, 0, x, y, &xu); if(ierr == 1) return; for( el = 0; el < mySol[currentSolution].elnum; el++){ for(i = 0; i < NOBF; i++){ node = mySol[currentSolution].nodpek[el][i]; x = mySol[currentSolution].coord[node][0]; y = mySol[currentSolution].coord[node][1]; ierr = getValue(item, 0, x, y, &xu); maxscalar = max(maxscalar, xu); minscalar = min(minscalar, xu); } } } else{ if(nvalues > 1){ for(i = 0; i < nvalues; i++){ maxscalar = max(maxscalar, data[item].value[i].f[0]); minscalar = min(minscalar, data[item].value[i].f[0]); } } } scl = maxscalar - minscalar; for( el = 0; el < mySol[currentSolution].elnum; el++){ for(i = 0; i < NOBF; i++){ node = mySol[currentSolution].nodpek[el][i]; x = mySol[currentSolution].coord[node][0]; y = mySol[currentSolution].coord[node][1]; phys2pix(&xpix, &ypix, x, y); if(substate == 0){ ierr = getValue(item, 0, x, y, &val); sc[i] = val; } else{ doTheInterpolation(item, xpix, ypix, value); sc[i] = value[0]; } xx[i] = xpix; yy[i] = ypix; } xx[NOBF] = xx[0]; yy[NOBF] = yy[0]; sc[NOBF] = sc[0]; if( substate == 0 || nvalues != 0){ for(ilev = 1; ilev < nlev; ilev++){ level = minscalar + (float) ilev*scl/nlev; ii = 0; for(i = 0; i < NOBF; i++){ if( (sc[i]-level)*(sc[i+1]-level) <= 0.){ if(sc[i+1]-sc[i] != 0.){ xp[ii] = xx[i] +(int)(xx[i+1]-xx[i])*(level-sc[i])/(sc[i+1]-sc[i]); yp[ii] = yy[i] +(int)(yy[i+1]-yy[i])*(level-sc[i])/(sc[i+1]-sc[i]); ii += 1; } } } for( i = 0; i < ii-1; i++){ myDrawLine(xp[i], yp[i], xp[i+1], yp[i+1]); } } } } /* next element */ } plotPhysBoundary(); } void plotEquationData() { int item; item = currentItem; if(module[currentModule].dataGroup[item].n == 1) plotIsolinesofEqData(); if(module[currentModule].dataGroup[item].n == 2) plotVectorsofEqData(); if(module[currentModule].dataGroup[item].n == 3) plotTensorofEqData(); } void drawEquationData() { int item, i, j, x, y; char text[100]; int h; float xp, yp, xm, ym; float xel[NOBF], yel[NOBF]; int el, nod; h = FontHeight(GetWidgetFont(drawWindow)); item = currentItem; if(data[item].type == 2){ for(i = 0; i < data[item].n; i++){ el = data[item].value[i].el; xp = yp = 0.0; for( j = 0; j < NOBF; j++){ nod = mySol[currentSolution].nodpek[el][j]; xp += mySol[currentSolution].coord[ nod ][0]; yp += mySol[currentSolution].coord[ nod ][1]; } xm = xp / 3.0; ym = yp / 3.0; for( j = 0; j < NOBF; j++){ nod = mySol[currentSolution].nodpek[el][j]; xp = mySol[currentSolution].coord[ nod ][0]; yp = mySol[currentSolution].coord[ nod ][1]; xel[j] = xm + .8*(xp - xm); yel[j] = ym + .8*(yp - ym); /* xel[j] = mySol[currentSolution].coord[ nod ][0]; yel[j] = mySol[currentSolution].coord[ nod ][1]; */ } (void) fill(xel, yel, 3); } } for(i = 0; i < data[item].n; i++){ if(data[item].type < 2){ x = data[item].value[i].x; y = data[item].value[i].y; } else{ xp = 0.0; yp = 0.0; el = data[item].value[i].el; for( j = 0; j < NOBF; j++){ nod = mySol[currentSolution].nodpek[el][j]; xp += mySol[currentSolution].coord[ nod ][0]; yp += mySol[currentSolution].coord[ nod ][1]; } xp = xp / 3.0; yp = yp / 3.0; phys2pix(&x, &y, xp, yp); } for(j = 0; j < data[item].nvalues; j++){ sprintf(text, "%s %f", module[currentModule].dataGroup[item].item[j].name, data[item].value[i].f[j]); if(data[item].type != 2) myDrawText(text, x+2, y-2-h*j); myDrawFilledBox(x-2,y-2,4,4); } } } float triangArea(float x1, float y1, float x2, float y2, float x3, float y3) { float a; a = 0.5 *( x2*y3 - y2*x3 - x1*y3 + y1*x3 + x1*y2 - y1*x2); if(a < 0.0) a = - a; return a; } int isInside(float *xel, float *yel, float x, float y) { float a, a1, a2, a3; float diff; float tol = 0.01; a = triangArea(xel[0], yel[0],xel[1], yel[1],xel[2], yel[2]); a1 = triangArea(xel[0], yel[0],xel[1], yel[1], x, y); a2 = triangArea(xel[1], yel[1], xel[2], yel[2], x, y); a3 = triangArea(xel[0], yel[0], x, y, xel[2], yel[2]); diff = 1.0 - (a1 + a2 + a3) / a; if( diff < 0.0) diff = - diff; if( diff < tol){ return TRUE; } else return FALSE; } /* * * +-----------------------------------------+ * | Checks which element that contains x,y | * +-----------------------------------------+ * */ int clickedInElement(int x, int y, int *thisEl) { int el, i, nod; float xp, yp; float xel[NOBF], yel[NOBF]; pix2phys(x, y, &xp, &yp); for( el = 0; el < mySol[currentSolution].elnum; el++){ for( i = 0; i < NOBF; i++){ nod = mySol[currentSolution].nodpek[el][i]; xel[i] = mySol[currentSolution].coord[ nod ][0]; yel[i] = mySol[currentSolution].coord[ nod ][1]; } if(isInside(xel, yel, xp, yp) == TRUE){ *thisEl = el; return TRUE; } } return FALSE; } int insideRubberBox(float x, float y) { if( x >= min(rubberX1, rubberX2) && x <= max(rubberX1, rubberX2) && y >= min(rubberY1, rubberY2) && y <= max(rubberY1, rubberY2)) return TRUE; else return FALSE; } /* * * +----------------------------------------+ * | Routines to handle Boundary conditions | * +----------------------------------------+ * */ int activeVariable() { int i; int item = 0; if( module[currentModule].nvar == 1) return 0; else{ for( i = 0; i < module[currentModule].nvar; i++){ if( GetToggleState( ns[i].butt)) item = i; } return item; } } /* * * +------------------------------------------------------+ * | Checks if the user has clicked on a boundary segment | * +------------------------------------------------------+ * */ /* * * +------------------------------------------------------+ * | Checks if the user has clicked on a boundary segment | * +------------------------------------------------------+ * */ GEO_NODE *new_clickedOnBoundary(int x, int y) { int nb; int i, j, n; int x1, y1, x2, y2; long int ds[2]; long int alpha; long int length; long int betha; int xl, yl; int ioff; GEO_NODE *g; BND_NODE *s, *pp; PTS_NODE *p; FOR_ALL_BOUNDARIES(g){ FOR_ALL_SEGMENTS(g, s){ x1 = ((s->seg)->pts1)->x; y1 = ((s->seg)->pts1)->y; x2 = ((s->seg)->pts2)->x; y2 = ((s->seg)->pts2)->y; ds[0] = x2 - x1; ds[1] = y2 - y1; length = (int) sqrt((double) (ds[0]*ds[0] + ds[1]*ds[1])) ; if( length == 0){ alpha = 0; xl = x1; yl = y1; } else{ alpha = (ds[0] * (x-x1) + ds[1] * (y-y1))/ length; xl = x1 + (alpha * ds[0]) / length; yl = y1 + (alpha * ds[1]) / length; } betha = (x - xl)*(x - xl) + (y - yl)*(y - yl); /* +----------------------------------+ | OK user has clicked on a segment | +----------------------------------+ */ if(alpha >= 0 && alpha <= length && betha < CLICK_TOL){ return g; } } } return NULL; } BND_NODE *clickedOnSegment(int x, int y) { int nb; int i, j, n; int x1, y1, x2, y2; long int ds[2]; long int alpha; long int length; long int betha; int xl, yl; int ioff; GEO_NODE *g; BND_NODE *s, *pp; PTS_NODE *p; FOR_ALL_BOUNDARIES(g){ FOR_ALL_SEGMENTS(g, s){ x1 = ((s->seg)->pts1)->x; y1 = ((s->seg)->pts1)->y; x2 = ((s->seg)->pts2)->x; y2 = ((s->seg)->pts2)->y; ds[0] = x2 - x1; ds[1] = y2 - y1; length = (int) sqrt((double) (ds[0]*ds[0] + ds[1]*ds[1])) ; if( length == 0){ alpha = 0; xl = x1; yl = y1; } else{ alpha = (ds[0] * (x-x1) + ds[1] * (y-y1))/ length; xl = x1 + (alpha * ds[0]) / length; yl = y1 + (alpha * ds[1]) / length; } betha = (x - xl)*(x - xl) + (y - yl)*(y - yl); /* +----------------------------------+ | OK user has clicked on a segment | +----------------------------------+ */ if(alpha >= 0 && alpha <= length && betha < CLICK_TOL){ return s; } } } return NULL; } /* * * +----------------------------------------------------+ * | Popup a box to get the value associated with a | * | boundary condition | * +----------------------------------------------------+ * */ int getBCValue(int which, float *value) { int i, ierr; char text[100]; int var; TagList tags[4]; var = activeVariable(); sprintf(text, module[currentModule].bc[which].format, module[currentModule].variable[var].name); i = 0; tags[i].tag = TAG_WINDOW_LABEL; tags[i].label = "Boundary Condition"; tags[i].data = NULL; tags[i].init = TAG_INIT; tags[i].tag = TAG_LABEL; tags[i].label = "Please specify the Boundary Condition"; tags[i].data = NULL; tags[i].init = TAG_NOINIT; i++; tags[i].tag = TAG_FLOAT; tags[i].label = text; tags[i].data = value; tags[i].init = TAG_INIT; i++; tags[i].tag = TAG_DONE; tags[i].label = NULL; tags[i].data = NULL; tags[i].init = TAG_NOINIT; i++; ierr = GetValues(tags); return ierr; } int checkInput() { int ierr; int j, nb, nseg; GEO_NODE *g; ierr = 0; nseg = 0; FOR_ALL_BOUNDARIES(g) nseg += number_of_segments(g); for(j = 0; j < nvar; j++){ if( cdbc[j].n != nseg){ ierr = 1; errorHandler("You have not specified enough boundary conditions"); } } return ierr; } /* * * +-------------------------------------------------------------+ * | Marks the segments with boundary conditions, and writes out | * | the values associated with the bc | * +-------------------------------------------------------------+ * */ void drawBC() { int nb, ioff, j, i, k, ibc; int x1, y1, x2, y2; int n, segment, item; int h; char text[100]; char text0[100]; BND_NODE *s; GEO_NODE *g; ioff = 0; h = FontHeight(GetWidgetFont(drawWindow)) + 2; FOR_ALL_BOUNDARIES(g){ FOR_ALL_SEGMENTS(g, s){ segment = s->seg->id; x1 = s->seg->pts1->x; y1 = s->seg->pts1->y; x2 = s->seg->pts2->x; y2 = s->seg->pts2->y; for(k = 0; k < module[currentModule].nvar; k++){ for(ibc = 0; ibc < cdbc[k].n; ibc++){ if(cdbc[k].segment[ibc] == segment){ item = cdbc[k].id[ibc]; sprintf(text0, module[currentModule].bc[item].format, module[currentModule].variable[k].name); sprintf(text, "%s%f", text0, cdbc[k].value[ibc]); myDrawText(text, (x1+x2)/2+4, (y1+y2)/2-h*k); mySetColor(RED); myDrawLine(x1,y1,x2,y2); mySetColor(WHITE); } } } } } } /* * * +-----------------------------------------------------------+ * | Stores the selected boundary condition in the right place | * +-----------------------------------------------------------+ * */ void storeBC(int segment, int item, float value) { int done; int i, j; /* check if the user is changing an existing bc */ done = 0; j = activeVariable(); for(i = 0; i < module[currentModule].nbc; i++){ if( GetToggleState( boundaryUI[i].butt)){ item = i; } } for(i = 0; i < cdbc[j].n; i++){ if(segment == cdbc[j].segment[i]){ cdbc[j].type[i] = module[currentModule].bc[item].tag[j]; cdbc[j].value[i] = value; cdbc[j].id[i] = item; done = 1; } } if(done == 0){ i = cdbc[j].n; cdbc[j].segment[i] = segment; cdbc[j].type[i] = module[currentModule].bc[item].tag[j]; cdbc[j].value[i] = value; cdbc[j].id[i] = item; cdbc[j].n++; } } /* * * +---------------------------------------------------+ * | Handles mouse down events for boundary conditions | * +---------------------------------------------------+ * */ void mouseDown(Widget w, int button, int x, int y, void *data) { int i, j, ii, n, nb; int ioff; int segment, dummy; BND_NODE *s, ss; GEO_NODE *g; for(i = 0; i < module[currentModule].nbc; i++){ if( GetToggleState( boundaryUI[i].butt)){ bctype = i; } } /* +----------------------------------+ | OK user has clicked on a segment | +----------------------------------+ */ g = new_clickedOnBoundary(x, y); if(g != NULL){ if(getBCValue(bctype, &value) == FALSE){ /* +------------------------+ | Mark only this segment | +------------------------+ */ if(button == 1){ s = clickedOnSegment(x, y); storeBC(s->seg->id, bctype, value); } /* +------------------------------------+ | Mark all segments on this boundary | +------------------------------------+ */ else if (button == 2){ FOR_ALL_SEGMENTS(g, s) storeBC(s->seg->id, bctype, value); } /* +-------------------------------------+ | Mark all segments on all boundaries | +-------------------------------------+ */ else { FOR_ALL_BOUNDARIES(g){ FOR_ALL_SEGMENTS(g, s){ storeBC(s->seg->id, bctype, value); } } } state = HAVE_BCDATA; redisplay(w, x, y, data); } } } /* * * +-------------------------------------------+ * | Callback function for boundary conditions | * +-------------------------------------------+ * */ void deleteBCData() { int i, item = 100; for(i = 0; i < module[currentModule].nbc; i++){ if( GetToggleState( boundaryUI[i].butt)){ item = i; } } if(item != 100) cdbc[item].n = 0; } void BCdelete( Widget w, void *data) { int hh = 0, ww = 0; deleteBCData(); redisplay(w, hh, ww, data); } void bcfcn(Widget ww, void *data) { int i; int h = 0, w = 0; state = HAVE_BCDATA; for( i = 0; i < module[currentModule].nbc; i++){ if( GetToggleState( boundaryUI[i].butt)){ bctype = i; SetButtonUpCB(drawWindow, NULL); SetButtonDownCB(drawWindow, mouseDown); SetMouseMotionCB(drawWindow, EQMouseMotion); } } setAction(PICKING); redisplay(ww, h, w, data); } /* * * +----------------------------------+ * | Routines to handle equation data | * +----------------------------------+ * */ void saveByElement(int el, int item) { int n, flag; int i, j; float x=0, y=0; int ierr; float value; n = data[item].n; flag = 0; /* * Check if updating an excisting data */ for(i = 0; i < n; i++){ if(data[item].value[i].el == el){ flag = 1; for(j = 0; j < data[item].nvalues; j++){ ierr = getValue(item, j, x, y, &value); data[item].value[i].f[j] = value; } } } /* * Nope, make a new entry */ if(flag == 0){ data[item].value[n].el = el; for(j = 0; j < data[item].nvalues; j++){ ierr = getValue(item, j, x, y, &value); data[item].value[i].f[j] = value; } data[item].n++; } } void getDefaultValues() { int item, n, j; int ierr; float value; for( item = 0; item < module[currentModule].ngroups; item++){ n = data[item].n; /* This item is not specified by the user */ if(n == 0){ /* Put in a dummy location */ data[item].value[n].x = -10; data[item].value[n].y = -10; for(j = 0; j < data[item].nvalues; j++){ ierr = getValue(item, j, .0, .0, &value); data[item].value[n].f[j] = value; } data[item].n++; } } } void deleteEqData() { int j, item; for(j = 0; j < module[currentModule].nvar; j++) cdbc[j].n = 0; for( item = 0; item < module[currentModule].ngroups; item++) data[item].n = 0; } void deleteEQData() { int i, item = 100; for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)){ item = i; } } if(item != 100) data[currentItem].n = 0; else{ if(module[currentModule].nvar == 1) item = 0; else{ for( i = 0; i < module[currentModule].nvar; i++){ if( GetToggleState( ns[i].butt)) item = i; } } if(item != 100) cdbc[item].n = 0; } } void EQdelete( Widget w, void *data) { int hh = 0, ww = 0; deleteEQData(); redisplay(w, hh, ww, data); } /* * * +-------------------------------------------------------+ * | The done function, checks input and closes the window | * +-------------------------------------------------------+ * */ void EQMouseDown(Widget w, int button, int x, int y, void *nulldata) { int i,j, n; int hh = 0, ww = 0; int item = 0; float xp, yp; int ierr; float value; /* locate which parameter the user is specifying */ for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)){ item = i; currentItem = item; } } /* Now store the data */ n = data[item].n; data[item].value[n].x = x; data[item].value[n].y = y; pix2phys(x, y, &xp, &yp); for(j = 0; j < data[item].nvalues; j++){ ierr = getValue(item, j, xp, yp, &value); data[item].value[n].f[j] = value; } data[item].n++; /* put the data on the screen */ redisplay(w, hh, ww, nulldata); deleteCrossHair(); } void EQMouseUp(Widget w, int button, int x, int y, void *nulldata) { int hh = 0, ww = 0; float x1, y1; int el, i, nod, item; int inside; pix2phys(x, y, &rubberX2, &rubberY2); for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)) item = i; } for( el = 0; el < mySol[currentSolution].elnum; el++){ inside = TRUE; for( i = 0; i < NOBF; i++){ nod = mySol[currentSolution].nodpek[el][i]; x1 = mySol[currentSolution].coord[ nod ][0]; y1 = mySol[currentSolution].coord[ nod ][1]; if( insideRubberBox(x1, y1) != TRUE) inside = FALSE; } if(inside == TRUE) saveByElement(el, item); } SetButtonDownCB(drawWindow, EQMouseDownByElement); SetMouseMotionCB(drawWindow, EQMouseMotion); SetButtonUpCB(drawWindow, NULL); deleteCrossHair(); redisplay(w, hh, ww, nulldata); } void EQMouseDownByElement(Widget w, int button, int x, int y, void *nulldata) { int i; int hh = 0, ww = 0; int item = 0; int el, nod; float xel[NOBF], yel[NOBF]; /* hm, making a rubber box to select a bunch of elements at a time */ if(button == 2){ pix2phys(x, y, &rubberX1, &rubberY1); zoomMouseDown(w, button, x, y, nulldata); SetButtonUpCB(drawWindow, EQMouseUp); } else{ /* locate which parameter the user is specifying */ for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)) item = i; } currentItem = item; if(clickedInElement(x, y, &el) == TRUE){ for(i = 0; i < NOBF; i++){ nod = mySol[currentSolution].nodpek[el][i]; xel[i] = mySol[currentSolution].coord[ nod ][0]; yel[i] = mySol[currentSolution].coord[ nod ][1]; } fill(xel, yel, NOBF); saveByElement(el, item); deleteCrossHair(); redisplay(w, hh, ww, nulldata); } } } void EQMouseMotion(Widget w, int x, int y, void *data) { crossHair(x, y); } void EQdone( Widget w, void *nulldata) { int i, j, k; if(checkInput() == 0){ deleteCrossHair(); SetMouseMotionCB(drawWindow, NULL); SetButtonDownCB(drawWindow, NULL); SetButtonUpCB(drawWindow, NULL); SetCurrentWindow(window); CloseWindow(); state = HAVE_BCDATA; setAction(NORMAL); module[currentModule].state = state; /* * +-----------------------------------------+ * | Store the values for the equationd data | * +-----------------------------------------+ */ for(i = 0; i < module[currentModule].ngroups; i++){ module[currentModule].dataGroup[i].n = data[i].nvalues ; module[currentModule].data[i].n = data[i].n; module[currentModule].dataGroup[i].type = data[i].type; if(data[i].type == 0){ /* We have an analytical expression */ for(k = 0; k < data[i].nvalues; k++) sprintf(module[currentModule].data[i].expr[k].text, "%s", GetStringEntry(equationUI[i].input[k])); } else{ for(j = 0; j < data[i].n; j++){ if(data[i].type == 1){ /* Pointwise spec */ module[currentModule].data[i].value[j].x = data[i].value[j].x; module[currentModule].data[i].value[j].y = data[i].value[j].y; } else{ /* elementwise spec */ module[currentModule].data[i].value[j].el = data[i].value[j].el; } for(k = 0; k < data[i].nvalues; k++) module[currentModule].data[i].value[j].f[k] = data[i].value[j].f[k]; } } } } /* * * +-----------------------------------+ * | Now store the boundary conditions | * +-----------------------------------+ * */ for(j = 0; j < module[currentModule].nvar; j++){ module[currentModule].bc[j].n = cdbc[j].n; for(i = 0; i < cdbc[j].n; i++){ module[currentModule].bc[j].type[i] = cdbc[j].type[i]; module[currentModule].bc[j].id[i] = cdbc[j].id[i]; module[currentModule].bc[j].value[i] = cdbc[j].value[i]; module[currentModule].bc[j].segment[i] = cdbc[j].segment[i]; } } } /* * * +-----------------------------------------------------+ * | The cancel button, restore stuff to old values and | * | popdown the window | * +-----------------------------------------------------+ * */ void EQcancel( Widget w, void *data) { deleteCrossHair(); SetMouseMotionCB(drawWindow, NULL); SetButtonDownCB(drawWindow, NULL); SetButtonUpCB(drawWindow, NULL); SetCurrentWindow(window); CloseWindow(); state = previousState ; setAction(NORMAL); module[currentModule].state = state; } void exprfcn(Widget ww, char *string, void *data) { int h = 0, w = 0; redisplay(ww, h, w, data); } void datafcn(Widget ww, void *nulldata) { int i; int h = 0, w = 0; state = HAVE_EQDATA; for( i = 0; i < module[currentModule].ngroups; i++){ if( GetToggleState( equationUI[i].butt)){ bctype = i; currentItem = i; if(data[i].n == 0){ getDataType(); data[i].type = substate; type[i] = substate; } else{ substate = data[i].type; } SetButtonUpCB(drawWindow, NULL); if(substate == 2) SetButtonDownCB(drawWindow, EQMouseDownByElement); else SetButtonDownCB(drawWindow, EQMouseDown); SetMouseMotionCB(drawWindow, EQMouseMotion); } } setAction(NORMAL); redisplay(ww, h, w, nulldata); } void typeDone( Widget ww, void *data) { int i; int h = 0, w = 0; for( i = 0; i < 3; i++){ if( GetToggleState( butt[i])) substate = i; } CloseWindow(); redisplay(ww, h, w, data); } void getDataType() { Widget window; Widget info; Widget text[10]; Widget done; window = MakeWindow("Input Type", SAME_DISPLAY, EXCLUSIVE_WINDOW); info = MakeLabel("Specify how you would like to give data:"); butt[0] = MakeToggle(" ", TRUE , NULL , NULL, NULL); butt[1] = MakeToggle(" ", FALSE, butt[0], NULL, NULL); butt[2] = MakeToggle(" ", FALSE, butt[0], NULL, NULL); text[0] = MakeLabel("An analytical expression throughout the domain"); text[1] = MakeLabel("A pointwise specification + interpolation"); text[2] = MakeLabel("An element by element specification"); done = MakeButton("Done", typeDone, NULL); SetWidgetPos(butt[0], PLACE_UNDER, info, NO_CARE, NULL); SetWidgetPos(text[0], PLACE_UNDER, info, PLACE_RIGHT, butt[0]); SetWidgetPos(butt[1], PLACE_UNDER, butt[0], NO_CARE, NULL); SetWidgetPos(text[1], PLACE_UNDER, butt[0], PLACE_RIGHT, butt[1]); SetWidgetPos(butt[2], PLACE_UNDER, butt[1], NO_CARE, NULL); SetWidgetPos(text[2], PLACE_UNDER, butt[1], PLACE_RIGHT, butt[2]); SetWidgetPos(done , PLACE_UNDER, butt[2], NO_CARE, NULL); ShowDisplay(); MainLoop(); } /* * * +---------------------------------------+ * | Function to put up a window prompting | * | the user to specify data needed for | * | the equation solver | * +---------------------------------------+ * */ void equationDataWindow(Widget widget, void *nulldata) { int i, j, k, hh = 0, ww = 0; int *ptr, *num[10]; ptr = nulldata; currentModule = getCheck(); nvar = module[currentModule].nvar; /* Show all data on the coarsest mesh */ currentSolution = 0; /* * +----------------------------------------------------+ * | Read in the existing equation data for this module | * +----------------------------------------------------+ */ for(i = 0; i < module[currentModule].ngroups; i++){ data[i].type = 0; data[i].nvalues = module[currentModule].dataGroup[i].n; data[i].n = module[currentModule].data[i].n; for(k = 0; k < data[i].nvalues; k++) sprintf(data[i].expr[k].text,"%s", module[currentModule].data[i].expr[k].text); if(data[i].n > 0) data[i].type = module[currentModule].dataGroup[i].type; data[i].n = module[currentModule].data[i].n; for(j = 0; j < data[i].n; j++){ data[i].value[j].el = module[currentModule].data[i].value[j].el; data[i].value[j].x = module[currentModule].data[i].value[j].x; data[i].value[j].y = module[currentModule].data[i].value[j].y; for(k = 0; k < data[i].nvalues; k++) data[i].value[j].f[k] = module[currentModule].data[i].value[j].f[k]; } } if(state >= HAVE_BCDATA){ for(j = 0; j < module[currentModule].nvar; j++){ cdbc[j].n = module[currentModule].bc[j].n; for(i = 0; i < cdbc[j].n; i++){ cdbc[j].type[i] = module[currentModule].bc[j].type[i]; cdbc[j].id[i] = module[currentModule].bc[j].id[i]; cdbc[j].value[i] = module[currentModule].bc[j].value[i]; cdbc[j].segment[i] = module[currentModule].bc[j].segment[i]; } } } else{ for(i = 0; i < nvar; i++) cdbc[i].n = 0; } previousState = state; ptr = (int *) malloc(sizeof(int)); for(i = 0; i < 10; ++i) { num[i] = (int *) malloc(sizeof(int)); *num[i] = i; } window = MakeWindow("SolverData", SAME_DISPLAY, NONEXCLUSIVE_WINDOW); title = MakeLabel(module[currentModule].name); equation = MakeLabel(""); if(module[currentModule].id == 1) SetWidgetBitmap(equation, ns_bits, ns_width, ns_height); else SetWidgetBitmap(equation, eq_bits, eq_width, eq_height); /* info = MakeTextWidget("equation_text.txt", TRUE, FALSE, 350, 90); */ if(module[currentModule].id == 1) info = MakeTextWidget("To solve this equation you neeed to specify \nthe parameters given below. Select one item \nat a time by clicking in the box to the left\nof each item. \nThen click on the points in the domain where \nyou want this value to be specified. \n \n The solution is marched in time until \n u(n+1) - u(n) < time tolerance", FALSE, FALSE, 350, 120); else info = MakeTextWidget("To solve this equation you neeed to specify \nthe parameters given below. Select one item \nat a time by clicking in the box to the left\nof each item. \nThen click on the points in the domain where \nyou want this value to be specified.", FALSE, FALSE, 350, 120); /* * +-------------------------------+ * | The widgets for equation data | * +-------------------------------+ */ for(i = 0; i < module[currentModule].ngroups; i++){ equationUI[i].header = MakeLabel(module[currentModule].dataGroup[i].groupName); if(i == 0) equationUI[i].butt = MakeToggle(" ", TRUE, NULL, datafcn, NULL); else equationUI[i].butt = MakeToggle(" ", FALSE, equationUI[0].butt, datafcn, NULL); for(j = 0; j < module[currentModule].dataGroup[i].n; j++){ equationUI[i].label[j] = MakeLabel(module[currentModule].dataGroup[i].item[j].name); equationUI[i].input[j] = MakeStringEntry("0.0", 300, exprfcn, NULL); SetStringEntry(equationUI[i].input[j], module[currentModule].data[i].expr[j].text); } } /* * +---------------------------------------------------------+ * | Now fix the widgets associated with boundary conditions | * +---------------------------------------------------------+ */ for(i = 0; i < module[currentModule].nbc; i++){ boundaryUI[i].header = MakeLabel( module[currentModule].bc[i].name); boundaryUI[i].butt = MakeToggle(" ", FALSE, equationUI[0].butt, bcfcn, NULL); } if( module[currentModule].nvar > 1){ for(i = 0; i < module[currentModule].nvar; i++){ ns[i].label = MakeLabel(module[currentModule].variable[i].name); if(i == 0) ns[i].butt = MakeToggle(" ", TRUE, NULL, NULL, NULL); else ns[i].butt = MakeToggle(" ", FALSE, ns[0].butt, NULL, NULL); } } bctext = MakeLabel("Boundary conditions:"); eraseB = MakeButton("Delete selected data", EQdelete, NULL); doneB = MakeButton("Done", EQdone, NULL); cancelB = MakeButton("Cancel", EQcancel, NULL); /*+-----------------------+ | Now place the widgets | +-----------------------+ */ SetWidgetPos(equation, PLACE_UNDER, title, NO_CARE, NULL); SetWidgetPos(info, PLACE_UNDER, equation, NO_CARE, NULL); for(i = 0; i < module[currentModule].ngroups; i++){ if(i == 0) { SetWidgetPos(equationUI[i].butt, PLACE_UNDER, info, NO_CARE, NULL); SetWidgetPos(equationUI[i].header, PLACE_UNDER, info, PLACE_RIGHT, equationUI[i].butt); } else{ j = module[currentModule].dataGroup[i-1].n - 1; SetWidgetPos(equationUI[i].butt, PLACE_UNDER,equationUI[i-1].label[j] , NO_CARE, NULL); SetWidgetPos(equationUI[i].header, PLACE_UNDER,equationUI[i-1].label[j] , PLACE_RIGHT, equationUI[i].butt); } for(j = 0; j < module[currentModule].dataGroup[i].n; j++){ if(j==0){ SetWidgetPos(equationUI[i].label[j], PLACE_UNDER, equationUI[i].header, NO_CARE, NULL); SetWidgetPos(equationUI[i].input[j], PLACE_UNDER, equationUI[i].header, PLACE_RIGHT, equationUI[i].label[j]); } else{ SetWidgetPos(equationUI[i].label[j], PLACE_UNDER,equationUI[i].label[j-1], NO_CARE, NULL); SetWidgetPos(equationUI[i].input[j], PLACE_UNDER,equationUI[i].label[j-1], PLACE_RIGHT, equationUI[i].label[j]); } } } i = module[currentModule].ngroups - 1; j = module[currentModule].dataGroup[i].n - 1; SetWidgetPos(bctext, PLACE_UNDER, equationUI[i].input[j], NO_CARE, NULL); if(module[currentModule].nvar > 1){ for(i = 0; i < module[currentModule].nvar; i++){ if( i == 0) SetWidgetPos(ns[i].butt, PLACE_UNDER, bctext, NO_CARE, NULL); else SetWidgetPos(ns[i].butt, PLACE_UNDER, bctext, PLACE_RIGHT, ns[i-1].label); SetWidgetPos(ns[i].label, PLACE_UNDER, bctext, PLACE_RIGHT, ns[i].butt); } } for(i = 0; i < module[currentModule].nbc; i++){ if(i == 0) { if(module[currentModule].nvar > 1){ SetWidgetPos(boundaryUI[i].butt, PLACE_UNDER, ns[nvar-1].butt, NO_CARE, NULL); SetWidgetPos(boundaryUI[i].header, PLACE_UNDER, ns[nvar-1].butt, PLACE_RIGHT, boundaryUI[i].butt); } else{ SetWidgetPos(boundaryUI[i].butt, PLACE_UNDER, bctext, NO_CARE, NULL); SetWidgetPos(boundaryUI[i].header, PLACE_UNDER, bctext, PLACE_RIGHT, boundaryUI[i].butt); } /* nvar > 1 */ } /* i == 0 */ else{ SetWidgetPos(boundaryUI[i].butt, PLACE_UNDER,boundaryUI[i-1].butt , NO_CARE, NULL); SetWidgetPos(boundaryUI[i].header, PLACE_UNDER,boundaryUI[i-1].butt , PLACE_RIGHT, boundaryUI[i].butt); } } j = module[currentModule].nbc - 1; SetWidgetPos(eraseB, PLACE_UNDER, boundaryUI[j].butt ,NO_CARE, NULL); SetWidgetPos(doneB, PLACE_UNDER, boundaryUI[j].butt, PLACE_RIGHT, eraseB); SetWidgetPos(cancelB, PLACE_UNDER, boundaryUI[j].butt, PLACE_RIGHT, doneB); ShowDisplay(); state = HAVE_EQDATA; currentItem = 0; substate = data[currentItem].type; redisplay(widget, hh, ww, nulldata); }