/* tetra_int.c integrate a function over a tetrahedron */ /* basically compute 4D volume under volume function */ /* over a tetrahedron given by four points */ /* first the hard way, element by element, int f(x,y,z) dx dy dz */ /* then using approximations from FEM handbook */ #include #include #undef abs #define abs(x) ((x)<0.0?(-(x)):(x)) #undef min #define min(a,b) ((a)<(b)?(a):(b)) #undef max #define max(a,b) ((a)>(b)?(a):(b)) static double f1(double x, double y, double z) { return x+2.0*y+3.0*z+4.0; /* linear, first order */ } static double f2(double x, double y, double z) { return x*x+2.0*y*y+3.0*z*z+4.0*x*y+5.0*x*z+6.0*y*z+ 7.0*x+8.0*y+9.0*z+10.0; /* quadratic, second order */ } static double f3(double x, double y, double z) { return x*x*x + 2.0*y*y*y + 3.0*z*z*z + 4.0*x*x*y + 5.0*x*x*z + 6.0*x*y*y + 7.0*x*y*z + 8.0*x*z*z + 9.0*y*y*z + 10.0*y*z*z + 11.0*x*x+12.0*y*y+13.0*z*z+14.0*x*y+15.0*x*z+16.0*y*z+ 17.0*x+18.0*y+19.0*z+20.0; /* cubic, third order */ } static double fe(double x, double y, double z) { return exp(x)*exp(y)*exp(z); } static double volume(double P1x, double P1y, double P1z, double P2x, double P2y, double P2z, double P3x, double P3y, double P3z, double P4x, double P4y, double P4z); static double dist(double a1x, double a1y, double a1z, double a2x, double a2y, double a2z, double a3x, double a3y, double a3z, double a4x, double a4y, double a4z); static double determinant(int n, double A[]); static void init_tetra(double P1x, double P1y, double P1z, double P2x, double P2y, double P2z, double P3x, double P3y, double P3z, double P4x, double P4y, double P4z); static void next_tetra(); static double vert[4097][3] = {{0.0, 0.0, 0.0}}; /* unused, start with [1]*/ static int ivert[4097][4] = {{1,2,3,4}}; static int nvert = 4; /* increment before inserting, count not including zero*/ static int npoly = 1; int main(int argc, char *argv[]) { /* simple four point tetrahedron P1, P2, P3, P4 of x,y,z */ double P1x = 1.0; double P1y = 1.0; double P1z = 1.0; double P2x = 3.0; double P2y = 2.5; double P2z = 2.0; double P3x = 2.0; double P3y = 0.5; double P3z = 1.5; double P4x = 0.5; double P4y = 1.5; double P4z = 3.5; double v, a, h; double vol4d, sum; double x, y, z, hx, hy, hz; double xmin; double xmax; double ymin; double ymax; double zmin; double zmax; double f1exact = 16.4713541666666; double f2exact = 127.946615; double f3exact = 719.9307; double feexact = 229.5346; int i, j, k, np; int p1, p2, p3, p4; printf("tetra_int.c running \n"); printf("Tetrahedron P1(%g,%g,%g) P2(%g,%g,%g) \n", P1x, P1y, P1z, P2x, P2y, P2z); printf(" P3(%g,%g,%g) P4(%g,%g,%g) \n", P3x, P3y, P3z, P4x, P4y, P4z); printf("f(x,y,z)=x^3+2y^2+x*y*z \n"); /* old experiment a = area(P1x, P1y, P1z, P2x, P2y, P2z, P3x, P3y, P3z); printf("area123=%g \n", a); h = dist(P4x, P4y, P4z, P1x, P1y, P1z, P2x, P2y, P2z, P3x, P3y, P3z); printf("height4=%g, volume=%g \n", h, a*h/3.0); a = area(P1x, P1y, P1z, P2x, P2y, P2z, P4x, P4y, P4z); printf("area124=%g \n", a); h = dist(P3x, P3y, P3z, P1x, P1y, P1z, P2x, P2y, P2z, P4x, P4y, P4z); printf("height3=%g, volume=%g \n", h, a*h/3.0); a = area(P1x, P1y, P1z, P3x, P3y, P3z, P4x, P4y, P4z); printf("area134=%g \n", a); h = dist(P2x, P2y, P2z, P1x, P1y, P1z, P3x, P3y, P3z, P4x, P4y, P4z); printf("height2=%g, volume=%g \n", h, a*h/3.0); a = area(P2x, P2y, P2z, P3x, P3y, P3z, P4x, P4y, P4z); printf("area234=%g \n", a); h = dist(P1x, P1y, P1z, P2x, P2y, P2z, P3x, P3y, P3z, P4x, P4y, P4z); printf("height1=%g, volume=%g \n", h, a*h/3.0); printf("\n"); v = volume2(P1x, P1y, P1z, P2x, P2y, P2z, P3x, P3y, P3z, P4x, P4y, P4z); printf("Volume by 1/3 area height = %g \n", v); printf("\n"); */ xmin = min(min(P1x,P2x),min(P3x,P4x)); xmax = max(max(P1x,P2x),max(P3x,P4x)); ymin = min(min(P1y,P2y),min(P3y,P4y)); ymax = max(max(P1y,P2y),max(P3y,P4y)); zmin = min(min(P1z,P2z),min(P3z,P4z)); zmax = max(max(P1z,P2z),max(P3z,P4z)); v = volume(P1x, P1y, P1z, P2x, P2y, P2z, P3x, P3y, P3z, P4x, P4y, P4z); printf("Volume by determinant = %g \n", v); printf("bounds xmin=%g, xmax=%g, ymin=%g, ymax=%g, zmin=%g, zmax=%g \n", xmin, xmax, ymin, ymax, zmin, zmax); printf("bound volume = %g \n", (xmax-xmin)*(ymax-ymin)*(zmax-zmin)); np = 1; printf("f1(x,y,z)=x+2*y+3*z+4 np=%d \n", np); x = (P1x+P2x+P3x+P4x)/4.0; y = (P1y+P2y+P3y+P4y)/4.0; z = (P1z+P2z+P3z+P4z)/4.0; sum = f1(x,y,z); vol4d = v*sum/(double)np; printf("computed integral=%g, exact integral=%g, error=%g \n", vol4d, f1exact, vol4d-f1exact); /* np = 8 */ init_tetra(P1x,P1y,P1z,P2x,P2y,P2z,P3x,P3y,P3z,P4x,P4y,P4z); next_tetra(); np = npoly; printf("f1(x,y,z)=x+2*y+3*z+4 np=%d \n", np); sum = 0.0; p1 = ivert[0][0]; p2 = ivert[0][1]; p3 = ivert[0][2]; p4 = ivert[0][3]; v = volume(vert[p1][0], vert[p1][1], vert[p1][2], vert[p2][0], vert[p2][1], vert[p2][2], vert[p3][0], vert[p3][1], vert[p3][2], vert[p4][0], vert[p4][1], vert[p4][2]); for(i=0; i abs_pivot ) { I_pivot = i; pivot = B[row[i]*n+k]; abs_pivot = abs(pivot); } } /* have pivot, interchange row pointers */ if(I_pivot != k) { hold = row[k]; row[k] = row[I_pivot]; row[I_pivot] = hold; D = - D; } /* check for near singular */ if(abs_pivot < 1.0E-10) { free(B); free(row); return 0.0; } else { D = D * pivot; /* reduce about pivot */ for(j=k+1; j