I'm solving Laplace's Equation with Gauss-Seidel method, but in some regions, its showing a plateau-like aspect. Formally, ie, by numerical analysis, such regions should not exist, even if the gradient is almost zero.
I'm forced to believe that double precision isn't enough to perform the arithmetic and that a big number library need to be used (killing the performance, since now it will be done by software). Or, that I should do the operations in a different order, aiming to preserve some significance to the decimals.
Example
Cell (13, 14, 0) is being updated by 7-point mesh (in 3D), and its neighbours are:
(12,14,0)= 0.9999999999999936; // (x-)
(14,14,0)= 0.9999999999999969; // (x+)
(13,13,0)= 0.9999999999999938; // (y-)
(13,15,0)= 1.0000000000000000; // (y+)
(13,14,-1)= 1.0000000000000000; // (z-)
(13,14,1)= 0.9999999999999959; // (z+)
So, the new value of cell (13,14,0) would be evaluated as:
p_new = (0.9999999999999936 + 0.9999999999999969 + 0.9999999999999938 + 1.0000000000000000 + 1.0000000000000000 + 0.9999999999999959) / 6.0 ;
which leads to p_new
being 1.0000000000000000, when it should be 0.9999999999999966.
Code
#include <stdio.h>
int main()
{
double ad_neighboor[6] = {0.9999999999999936, 0.9999999999999969,
0.9999999999999938, 1.0000000000000000,
1.0000000000000000, 0.9999999999999959};
double d_denom = 6.0;
unsigned int i_xBackward=0;
unsigned int i_xForward=1;
unsigned int i_yBackward=2;
unsigned int i_yForward=3;
unsigned int i_zBackward=4;
unsigned int i_zForward=5;
double d_newPotential = (ad_neighboor[i_xForward] + ad_neighboor[i_xBackward] +
ad_neighboor[i_yForward] + ad_neighboor[i_yBackward] +
ad_neighboor[i_zForward] + ad_neighboor[i_zBackward] ) / d_denom;
printf("%.16f\n", d_newPotential);
}