Страница 2 из 3 Алгоритм Томаса Поиск решения производится в виде: ui-1=beti*ui+gami В этом случае для bet и gam получаются рекуррентные формулы: beti+1=ci*fi, gami+1=(fi+ai*gami)*fi, fi=1/(bi-ai*beti); bet0=gam0=0. По этим формулам вспомогательные массивы вычисляются для i от 1 до N, затем находится uN-1=gamN, а затем при известных вспомогательных массивах вычисляются все значения u. Алгоритм принципиально не может иметь ведущего элемента, и есть вероятность того, что он не сойдется даже для несингулярной матрицы. Для этого в программе, реализующей прогонку, необходимо контролировать значения fi. Еще два замечания: длины рекуррентных цепочек порядка N, поэтому при экспоненциальном накоплении погрешностей (что происходит при преобладании значений |beti|>1) прогонка практически обязательно разойдется. Второе: алгоритм сохраняет исходные значения коэффициентов. Доказано, что для устойчивой работы алгоритма Томаса достаточно диагонального преобладания, однако, во многих случаях он сходится и при отсутствии такового. /* Алгоритм Томаса, решающий трехдиагональную линейную систему. Описание: int Sweep(double *u,double *a,double *b,double *c,double *f, int n,double *bet,double *gam); Параметры: u - разрешение (размера n), на выходе; a,b,c,f - массивы коэффициентов (как в алгоритмах, описанных выше, размера n) n - размер разрешения и массива коэффициентов; bet, gam - дополнительные массивы (размера n+1). Результат: 0 - сбой алгоритма, 1 - положительный результат. */
/* Алгоритм Томаса */ int Sweep(double *u,double *a,double *b,double *c,double *f,int n, double *bet,double *gam) { register int n; double fi; /* Вычисление дополнительных массивов (умножение системы) */ bet[0]=gam[0]=0.; for(i=0;i<n;i++) { fi=b[i]; if(i>0) fi-=a[i]*bet[i]; if(fi==0.) return(0); fi=1./fi; if(i<n-1) bet[i+1]=c[i]*fi; gam[i+1]=(f[i]+a[i]*gam[i])*fi; } /* обратная замена */ u[n-1]=gam[n]; for(i=n-1;i>0;i--) u[i-1]=bet[i]*u[i]+gam[i]; return(1); } |