// fem_check21a_tri.c Galerkin FEM on triangular grid // solve 3 ux(x,y) + 2 uy(x,y) + u(x,y) = f(x,y) // boundary conditions computed using u(x,y) // analytic solution may be given by u(x,y) = 1+ 2*x + 3*y // f(x,y)=2.0*x+3.0*y+13.0 // input triangles and coordinates // input geometry, root= 22_t .coord, .tri, .bound // and others // // solve for Uij numerical approximation U(x_i,y_j) of u(x_i,y_j) // K * U = F, solve simultaneous equations for U import java.io.*; class fem_check21a_tri { final int sz = 50; final int sz3 = 150; final int szsz = 2500; final int np = 3; final int szint = np*np; int debug=3; // debug print level static String root; // root name for .tri, .coord, .bound int ntri; // number of triangles int minvert; // minimum vertex number, reduced to zero int t1[] = new int[sz]; // vertex numbers on triangles int t2[] = new int[sz]; // vertex numbers on triangles int t3[] = new int[sz]; // vertex numbers on triangles int ncoord; // number of coordinates, also equals nvert double xc[] = new double[sz]; // coordinates in vertex order double yc[] = new double[sz]; // coordinates in vertex order int b1[] = new int[sz]; // dirichlet boundary edge vertices int b2[] = new int[sz]; // dirichlet boundary edge vertices double xmin, xmax, ymin, ymax; // determined by input double kg[] = new double[szsz]; // global stiffness matrix double fg[] = new double[sz]; // right hand side, forcing function double ug[] = new double[sz]; // solution computed by fem double Ua[] = new double[sz]; // known solution for checking double cm1[] = new double[6]; // coefficients for phi functions double cm2[] = new double[6]; // specific to second order two dimensions double cm3[] = new double[6]; // for three vertices, in order int uniquev[] = new int[sz3]; // all vertices int nvert; // number of unique vertices int uniqueb[] = new int[sz3]; // bound vertices int nbound; // number of boundary vertices int uniquef[] = new int[sz3]; // free vertices, 0 to nfree-1 int nfree; // degrees of freedom ntri-nbound int nuniquev, nuniqueb, nuniquef; // vertices counts double xs[] = new double[szint]; // integration coordinates, this triangle double ys[] = new double[szint]; // integration coordinates, this triangle double ws[] = new double[szint]; // integration coordinates, this triangle double ph1[] = new double[szint]; // phi21(xs,ys) for this triangle cm1 double ph2[] = new double[szint]; // phi21(xs,ys) for this triangle cm2 double ph3[] = new double[szint]; // phi21(xs,ys) for this triangle cm3 double gs1[] = new double[szint]; // galk(cm1,xs,ys) double gs2[] = new double[szint]; // galk(cm2,xs,ys) double gs3[] = new double[szint]; // galk(cm3,xs,ys) double fs[] = new double[szint]; // F(xs,ys) fem_check21a_tri() // main constructor { double x, y; double x1, y1, x2, y2, x3, y3; int i1, i2, i3; double a, b, sum, intg; double c[] = new double[np*np]; // max coefficients double val, err, avgerr, maxerr; int stat, i, j, ii, k, kk, kdebug; int nv; // number of vertices for numerical integration int nuvert; // number of unknown vertices after boundary applied double T1[] = new double[6]; // x1,y1 x2,y2 x3,y3 this triangle System.out.println("fem_check21a_tri.c running "); System.out.println("Given 3 ux + 2 uy + u = 2 x + 3 y + 13 "); System.out.println("Analytic solution u(x,y) = 1 + 2 x + 3 y "); new triquad(); // get verification for tint stat = do_input(); if(stat != 0) System.exit(1); // can not continue // initialize kg, fg and ug first cut, not using sparse matrix for(i=0; i0) { System.out.println("nodes i1="+i1+", i2="+i2+", i3="+i3); System.out.println("coord ("+x1+","+y1+") ("+x2+","+y2+ ") ("+x3+","+y3+") "); } // determine coefficients for the three vertices phi_tri_cm12(x1, y1, x2, y2, x3, y3, kdebug, cm1); phi_tri_cm12(x2, y2, x3, y3, x1, y1, kdebug, cm2); phi_tri_cm12(x3, y3, x1, y1, x2, y2, kdebug, cm3); // build integration points and values nv = tri_int1a(np, T1, kdebug); if(not_in(i1, uniqueb, nbound)) // x1,y1 contributions if not boundary { intg=tri_int2a(nv, gs1, ph1); if(kdebug>0) System.out.println("integral="+intg+", at i="+i1+", j="+i1); kg[i1*nvert+i1] += intg; intg=tri_int2a(nv, fs, ph1); if(kdebug>0) System.out.println("intg fg ="+intg+", at i="+i1); fg[i1] += intg; intg=tri_int2a(nv, gs2, ph1); if(kdebug>0) System.out.println("integral="+intg+", at i="+i2+", j="+i1); kg[i1*nvert+i2] += intg; // if(not_in(i2, uniqueb, nbound)) kg[i2*nvert+i1] += intg; intg=tri_int2a(nv, gs3, ph1); if(kdebug>0) System.out.println("integral="+intg+", at i="+i3+", j="+i1); kg[i1*nvert+i3] += intg; // if(not_in(i3, uniqueb, nbound)) kg[i3*nvert+i1] += intg; } if(not_in(i2, uniqueb, nbound)) // x2,y2 contributions if not boundary { intg=tri_int2a(nv, gs2, ph2); if(kdebug>0) System.out.println("integral="+intg+", at i="+i2+", j="+i2); kg[i2*nvert+i2] += intg; intg=tri_int2a(nv, fs, ph2); if(kdebug>0) System.out.println("intg fg ="+intg+", at i="+i2); fg[i2] += intg; intg=tri_int2a(nv, gs1, ph2); if(kdebug>0) System.out.println("integral="+intg+", at i="+i1+", j="+i2); kg[i2*nvert+i1] += intg; // if(not_in(i1, uniqueb, nbound)) kg[i1*nvert+i2] += intg; intg=tri_int2a(nv, gs3, ph2); if(kdebug>0) System.out.println("integral="+intg+", at i="+i3+", j="+i2); kg[i2*nvert+i3] += intg; // if(not_in(i3, uniqueb, nbound)) kg[i3*nvert+i2] += intg; } if(not_in(i3, uniqueb, nbound)) // x3,y3 contributions if not boundary { intg=tri_int2a(nv, gs3, ph3); if(kdebug>0) System.out.println("integral="+intg+", at i="+i3+", j="+i3); kg[i3*nvert+i3] += intg; intg=tri_int2a(nv, fs, ph3); if(kdebug>0) System.out.println("intg fg ="+intg+", at i="+i3); fg[i3] += intg; intg=tri_int2a(nv, gs1, ph3); if(kdebug>0) System.out.println("integral="+intg+", at i="+i1+", j="+i3); kg[i3*nvert+i1] += intg; // if(not_in(i1, uniqueb, nbound)) kg[i1*nvert+i3] += intg; intg=tri_int2a(nv, gs2, ph3); if(kdebug>0) System.out.println("integral="+intg+", at i="+i2+", j="+i3); kg[i3*nvert+i2] += intg; // if(not_in(i2, uniqueb, nbound)) kg[i2*nvert+i3] += intg; } System.out.println("finished k="+k); } // end k loop making local stifness matrices, inserted into global if(debug>1) for(i=0; i1) { System.out.println("vertices, coordinates and analytic values "); for(i=0; imaxerr) maxerr = err; avgerr = avgerr + err; System.out.println("ug["+i+"]="+ug[i]+", Ua="+Ua[i]+", err="+(ug[i]-Ua[i])); } System.out.println(" maxerr="+maxerr+", avgerr="+ (avgerr/(double)(nvert))); System.out.println(""); } // end fem_check21a_tri constructor // user provided, a specific differential equation double F(double x, double y) // forcing function { return 2.0*x+3.0*y+13.0; } double uana(double x, double y) // analytic solution and boundaries { return 1.0+2.0*x+3.0*y; } // this is the encoding of the differential equation // L(u(x,y))=F(x,y), L(u(x,y)) becomes Galerkin L(phi(x,y)) // u=phi12 ux=phi12x uy=phi12y double galk(double c[], double x, double y) { // Galerkin k stiffness function for this problem return 3.0 * phi12x (c,x,y) + 2.0 * phi12y (c,x,y) + phi12 (c,x,y); } // end galk used for integration, c for phi_i, phi_j separate int tri_int1a(int np, double T[], int debug) { int nv, i; nv = triquad.tint(np, T, xs, ys, ws); if(debug>0) System.out.println("tri_int1a running with np="+np+", nv="+nv); for(i=0; i2) System.out.println("finding unique of nold="+nold); sortint(nold,a); j=0; for(i=1; ia[i-1]) { j++; a[j]=a[i]; } } j++; if(debug>2) System.out.println("found unique of n="+j); return j; } // end uniqueint void sortint(int n, int a[]) { int i, j, temp; for(i=0; ia[j]) {temp=a[i]; a[i]=a[j]; a[j]=temp;} } // end sortint int freevert(int c[], int na, int a[], int nb, int b[]) { // a and b sorted integer arrays, c will be from a, not in b int ia=0; int ib=0; int ic=0; if(debug>2) System.out.println("freevert na="+na+", nb="+nb); while(true) { if(ib>=nb || a[ia]!=b[ib]) {c[ic]=a[ia]; ic++; ia++;} else {ia++; ib++;} if(ia>=na) break; } if(debug>2) System.out.println("freevert nc free = "+ic); return ic; } boolean not_in(int i, int a[], int n) { boolean found = false; int j; for(j=0; j0) { System.out.println("cm matrix of am cm = ym solve for cm "); for(i=0; i<3; i++) System.out.print(" "+cm[i]); System.out.println(""); } // check solution for(i=0; i<3; i++) { sum=0.0; for(j=0; j<3; j++) sum=sum+am[i*3+j]*cm[j]; if(i==0 && Math.abs(sum-1.0)>1.0e-6) System.out.println("BAD cm i="+i+", sum="+sum); if(i!=0 && Math.abs(sum)>1.0e-6) System.out.println("BAD cm i="+i+", sum="+sum); } if(Math.abs(phi12(cm,x1,y1)-1.0)>1.0e-6) System.out.println("BAD cm x1="+x1+", y1="+y1); if(Math.abs(phi12(cm,x2,y2))>1.0e-6) System.out.println("BAD cm x2="+x2+", y2="+y2); if(Math.abs(phi12(cm,x3,y3))>1.0e-6) System.out.println("BAD cm x3="+x3+", y3="+y3); } // end phi_tri_cm12 int do_input() // three files root .tri root.bound root.coord { String fname; int index, last, len; // read in triangles, set ntri fname = root+".tri"; if(debug>2) System.out.println("about to read triangles from "+fname); ntri=0; minvert=999999; nvert=0; try { BufferedReader in = new BufferedReader(new FileReader(fname)); String input_line; input_line = in.readLine(); while(input_line != null) { System.out.println(input_line); // have a line, extract 3 integers len = input_line.length(); if(len<5) // not enough data, ignore blank lines { input_line = in.readLine(); continue; } index = 0; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); System.out.println("index="+index+", last="+last); t1[ntri] = Integer.parseInt(input_line.substring(index,last)); index = last+1; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); System.out.println("index="+index+", last="+last); t2[ntri] = Integer.parseInt(input_line.substring(index,last)); index = last+1; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); if(last<1) last = len; System.out.println("index="+index+", last="+last); t3[ntri] = Integer.parseInt(input_line.substring(index,last)); if(debug>0) System.out.println("tri "+ntri+" has vertices "+t1[ntri]+ " "+t2[ntri]+" "+t3[ntri]); if(t1[ntri]>nvert) nvert=t1[ntri]; if(t2[ntri]>nvert) nvert=t2[ntri]; if(t3[ntri]>nvert) nvert=t3[ntri]; if(t1[ntri]0) System.out.println(ntri+" triangles read from "+fname); System.out.println("subtracting minvert="+minvert+ " from all vertices, using base zero"); nvert=nvert+1-minvert; // still must be dense sequence of numbers nuniquev=0; for(int i=0; i2) System.out.println("about to read boundary from "+fname); nbound=0; try { BufferedReader in = new BufferedReader(new FileReader(fname)); String input_line; input_line = in.readLine(); while(input_line != null) { System.out.println(input_line); // have a line, extract 2 integers len = input_line.length(); if(len<4) // not enough data, ignore blank lines { input_line = in.readLine(); continue; } index = 0; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); System.out.println("index="+index+", last="+last); b1[nbound] = Integer.parseInt(input_line.substring(index,last)); index = last+1; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); if(last<1) last = len; System.out.println("index="+index+", last="+last); b2[nbound] = Integer.parseInt(input_line.substring(index,last)); if(debug>0) System.out.println("boundary segment nbound="+nbound+ " has vertices "+b1[nbound]+", "+b2[nbound]); if(b1[nbound]>nvert) System.out.println("bad boundary vertex "+ b1[nbound]); if(b2[nbound]>nvert) System.out.println("bad boundary vertex "+ b2[nbound]); if(b1[nbound]0) System.out.println("read Dirichlet boundaries from "+fname); System.out.println("subtracting minvert="+minvert+ " from all vertices, using base zero"); nuniqueb=0; for(int i=0; i0) for(int i=0; i0) System.out.println("number of free vertices is "+nuniquef); if(debug>0) for(int i=0; i2) System.out.println("about to read coordinates from "+ fname); ncoord=0; try { BufferedReader in = new BufferedReader(new FileReader(fname)); String input_line; input_line = in.readLine(); while(input_line != null) { System.out.println(input_line); // have a line, extract 2 double len = input_line.length(); if(len<5) // not enough data, ignore blank lines { input_line = in.readLine(); continue; } index = 0; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); System.out.println("index="+index+", last="+last); xc[ncoord] = Double.parseDouble(input_line.substring(index,last)); index = last+1; while(input_line.substring(index,index+1).equals(" ")){index++;} last = input_line.indexOf(' ',index+1); if(last<1) last = len; System.out.println("index="+index+", last="+last); yc[ncoord] = Double.parseDouble(input_line.substring(index,last)); if(debug>0) System.out.println("coordinate "+ncoord+" at "+ xc[ncoord]+", "+yc[ncoord]); if(ncoord==0) { xmax=xc[ncoord]; xmin=xc[ncoord]; ymax=yc[ncoord]; ymin=yc[ncoord]; } if(xc[ncoord]>xmax) xmax=xc[ncoord]; if(xc[ncoord]ymax) ymax=yc[ncoord]; if(yc[ncoord]0) System.out.println("coordinates read from "+fname); if(ncoord!=nvert) System.out.println("**** wrong number of coordinates="+ncoord+ ", should be"+nvert); nfree=nvert-nuniqueb; System.out.println("xmin="+xmin+", xmax="+xmax+ ", ymin="+ymin+", ymax="+ymax); System.out.println("nvert="+nvert+", nbound="+nbound+", nuniqueb="+ nuniqueb+", nfree="+nfree+", ntri="+ntri); return 0; } // end do_input public static void main (String[] args) { root = "22_t"; if(args.length>0) root=args[0]; new fem_check21a_tri(); } } // end fem_check21a_tri class