Search code examples
cfloating-pointnumerical-methods

Why is the numerical solution coming same as analytical solution in C language?


I have coded a 1 dimension cfd problem but my numerical solution is coming same as to the analytical solution (up to 6 decimal places).

I am using TDMA method for numerical solution and for the analytical solution I am directly substituting the x value in the function T(x).

Analytical solution T(x) comes out to be T(x) = -(x^2)/2 +11/21(x);

E. g. 4 grid points then ;

  x0  = 0.000000,    x1  = 0.333333 ,   x2  = 0.666666 ,   x3  = 0.999999 .
T(x0) = 0.000000 , T(x1) = 0.119048 , T(x2) = 0.126984 , T(x3) = 0.023810.

And for numerical solution I have used TDMA technique, please refer the code below.

Enter n = 4 for the results.

#include<stdio.h>

void temp_matrix(int n, double *a, double *b, double *c, double *d, double *T);

int main() {
  int Bi = 20.0;
  int n;
  printf("%s ", "Enter the Number of total Grid Points");
  scanf("%d", &n);
  float t = (n - 1);
  double dx = 1.0 / t;
  int i;
  printf("\n");

  double q; // analytical solution below
  double z[n];
  for (i = 0; i <= n - 1; i++) {
    q = (dx) * i;
    z[i] = -(q * q) / 2 + q * (11.0 / 21);
    printf("\nT analytical %lf ", z[i]);
  }

  double b[n - 1];
  b[n - 2] = -2.0 * Bi * dx - 2.0;
  for (i = 0; i <= n - 3; i++) {
    b[i] = -2.0;
  }

  double a[n - 1];
  a[n - 2] = 2.0;
  a[0] = 0;
  for (i = 1; i < n - 2; i++) {
    a[i] = 1.0;
  }

  double c[n - 1];
  for (i = 0; i <= n - 2; i++) {
    c[i] = 1.0;
  }

  double d[n - 1];
  for (i = 0; i <= n - 2; i++) {
    d[i] = -(dx * dx);
  }

  double T[n];
  temp_matrix(n, a, b, c, d, T);

  return 0;
}

void temp_matrix(int n, double *a, double *b, double *c, double *d, double *T) {
  int i;
  double beta[n - 1];
  double gama[n - 1];
  beta[0] = b[0];
  gama[0] = d[0] / beta[0];
  for (i = 1; i <= n - 2; i++) {
    beta[i] = b[i] - a[i] * (c[i - 1] / beta[i - 1]);
    gama[i] = (d[i] - a[i] * gama[i - 1]) / beta[i];
  }
  int loop;
  for (loop = 0; loop < n - 1; loop++)
    for (loop = 0; loop < n - 1; loop++)

      T[0] = 0;
  T[n - 1] = gama[n - 2];

  for (i = n - 2; i >= 1; i--) {
    T[i] = gama[i - 1] - (c[i - 1] * (T[i + 1])) / beta[i - 1];
  }
  printf("\n");
  for (i = 0; i < n; i++) {
    printf("\nT numerical %lf", T[i]);

  }
}

Solution

  • Why is the numerical solution coming same as analytical solution in C language?

    They differ, by about 3 bits.

    Print with enough precision to see the difference.

    Using the below, we see a a difference in the last hexdigit of the significand of x620 vs x619 of T[3]. This is only 1 part in 1015 difference.

    #include<float.h>
    printf("T analytical %.*e\t%a\n", DBL_DECIMAL_DIG - 1, z[i], z[i]);
    printf("T numerical  %.*e\t%a\n", DBL_DECIMAL_DIG - 1, T[i], T[i]);
    

    C allows double math to be performed at long double math when FLT_EVAL_METHOD == 2 and then the same analytical/numerical results. Your results may differ from mine due to that as well as other subtle FP nuances.

    printf("FLT_EVAL_METHOD %d\n", FLT_EVAL_METHOD);
    

    Output

    T analytical 0.0000000000000000e+00 0x0p+0
    T analytical 1.1904761904761907e-01 0x1.e79e79e79e7ap-4
    T analytical 1.2698412698412700e-01 0x1.0410410410411p-3
    T analytical 2.3809523809523836e-02 0x1.861861861862p-6
    
    T numerical  0.0000000000000000e+00 0x0p+0
    T numerical  1.1904761904761904e-01 0x1.e79e79e79e79ep-4
    T numerical  1.2698412698412698e-01 0x1.041041041041p-3
    T numerical  2.3809523809523812e-02 0x1.8618618618619p-6
    
    FLT_EVAL_METHOD 0