/* equation_nl.c handle reciprocal terms */ /* f1(x1, x2, x3) = x1 + 2 x2^2 + 3/x3 = 10 */ /* f1'(x1) = 1 */ /* f1'(x2) = 4 x2 */ /* f1'(x3) = -3/x3^2 */ /* */ /* f2(x1, x2, x3) = 2 x1 + x2^2 + 1/x3 = 6.333 */ /* f2'(x1) = 2 */ /* f2'(x2) = 2 x2 */ /* f2'(x3) = -1/x3^2 */ /* */ /* f3(x1, x2, x3) = 3 x1 + x2^2 + 4/x3 = 8.333 */ /* f3'(x1) = 3 */ /* f3'(x2) = 2 x2 */ /* f3'(x3) = -4/x3^2 */ /* */ /* in matrix form, the equations are: A * X = Y */ /* | 1 2 3 | | x1 | = | 10.000 | */ /* | 2 1 1 | * | x2^2 | = | 6.333 | */ /* | 3 1 4 | | 1/x3 | = | 8.333 | */ /* A * Xt = Y */ /* */ /* in matrix form, the Jacobian is: */ /* | 1 | | 1 4*x2 -3/x3^2 | */ /* A * | 2*x2 | = | 2 2*x2 -1/x3^2 | = Ja */ /* |-1/x3^2 | | 3 2*x2 -4/x3^2 | */ /* A * D = Ja */ /* deriv of X */ /* wrt x1,x2,x3 */ /* */ /* Newton iteration: */ /* x_next = x-fctr*(A*Xt-Y)/Ja, /Ja is times transpose inverse of Ja */ /* Ja is, in general, dependent on all variables */ /* fctr may need to be reduced for stability */ #include #include "inverse.h" #include #undef abs #define abs(a) ((a)<0.0?(-(a)):(a)) /* three functions representing Y */ double f1(double x1, double x2, double x3) { return x1 + 2.0*x2*x2 + 3.0/x3; /* = 10.0 */ } double f2(double x1, double x2, double x3) { return 2.0*x1 + x2*x2 + 1.0/x3; /* = 6.333 */ } double f3(double x1, double x2, double x3) { return 3.0*x1 + x2*x2 + 4.0/x3; /* = 8.333 */ } int main(int argc, char * argv[]) { int itr, i, j; int nitr = 7; double A[3][3] = {{1.0, 2.0, 3.0}, {2.0, 1.0, 1.0}, {3.0, 1.0, 4.0}}; double Xt[3]; /* X terms, A * Xt = Y with X being nonlinear terms */ double Y[3]; /* RHS of equations */ double D[3]; /* derivative of Xt terms */ double Ja[3][3]; /* Jacobian to be inverted */ double JI[3][3]; /* Jacobian inverted */ double F[3]; /* A*X-Y error to be multiplied by J inverse */ double x1, x2, x3; /* initial guess and solution */ double fctr = 1.0; /* can be unstable, may need to be smaller */ printf("equation_nl.c running \n"); printf("solve x1 + 2 x2^2 + 3/x3 = 10 \n"); printf(" 2 x1 + x2^2 + 1/x3 = 6.333 \n"); printf(" 3 x1 + x2^2 + 4/x3 = 8.333 \n"); printf(" | 1 2 3 | | x1 | = | 10.000 | \n"); printf(" | 2 1 1 | * | x2^2 | = | 6.333 | \n"); printf(" | 3 1 4 | | 1/x3 | = | 8.333 | \n"); printf(" A * X = Y \n"); printf("guess initial x1, x2, x3 \n"); printf("compute Xt = | x1 x2^2 1/x3 | \n"); printf("compute derivative D = | 1 2*x2 -1/x3^2 | \n"); printf("compute the Jacobian J = A * D and invert \n"); printf("iterate x_next = x - fctr*(A*Xt-Y)*Ja^-1 \n"); printf("no guarantee of solution or unique solution \n"); printf("A*Xt-Y should go to zero \n"); Y[0] = f1(1.0, 2.0, 3.0); /* desired solution 1, 2, 3 */ Y[1] = f2(1.0, 2.0, 3.0); /* compute Y accurately */ Y[2] = f3(1.0, 2.0, 3.0); printf("| %8.4f %8.4f %8.4f | | x1 | | %8.4f | \n", A[0][0], A[0][1], A[0][2], Y[0]); printf("| %8.4f %8.4f %8.4f | * |x2*x2 | = | %8.4f | \n", A[1][0], A[1][1], A[1][2], Y[1]); printf("| %8.4f %8.4f %8.4f | | 1/x3 | | %8.4f | \n", A[2][0], A[2][1], A[2][2], Y[2]); x1 = 1.0; /* variable initial guess */ x2 = 1.0; x3 = 1.0; for(itr=0; itr