Итерационные методы решения СЛАУ
Метод итераций (метод последовательных приближений). Приближенные методы решения систем линейных уравнений позволяют получать значения корней системы с заданной точностью в виде предела последовательности некоторых векторов. Процесс построения такой последовательности называется итерационным (повторяющимся). Эффективность применения приближенных методов зависят от выбора начального вектора и быстроты сходимости процесса. Рассмотрим метод итераций (метод последовательных приближений). Пусть дана система n линейных уравнений с n неизвестными: Ах=b, (14) Предполагая, что диагональные элементы aii
Обозначим
Решим систему (16) методом последовательных приближений. За нулевое приближение примем столбец свободных членов. Любое (k+1)-е приближение вычисляют по формуле
Если последовательность приближений x(0),...,x(k) имеет предел Метод Зейделя. Метод Зейделя представляет собой модификацию метода последовательных приближений. В методе Зейделя при вычислении (k+1)-го приближения неизвестного xi (i>1) учитываются уже найденные ранее (k+1)-е приближения неизвестных xi-1. Пусть дана линейная система, приведенная к нормальному виду:
Выбираем произвольно начальные приближения неизвестных и подставляем в первое уравнение системы (17). Полученное первое приближение подставляем во второе уравнение системы и так далее до последнего уравнения. Аналогично строим вторые, третьи и т.д. итерации.
Таким образом, предполагая, что k-е приближения
где k=0,1,...,n
Метод Ланцоша. Для решения СЛАУ высокого порядка (1), матрица, коэффициентов которой хранится в компактном нижеописанном виде, наиболее удобным итерационным методом является метод Ланцоша [4], схема которого имеет вид:
где
Преимуществом данного метода является его высокая скорость сходимости к точному решению. Кроме того, доказано, что он обладает свойством «квадратичного окончания», т.е. для положительно определенной матрицы можно гарантировано получить точное решение при количестве итераций
где
Среднеквадратичную разность необходимо контролировать при выполнении каждых k наперед заданных итераций. Отдельно следует рассмотреть проблему выбора начального приближения
2 МЕТОДЫ КОМПАКТНОГО ХРАНЕНИЯ МАТРИЦЫ ЖЕСТКОСТИ Матрица жесткости, получающаяся при применении МКЭ, обладает симметричной структурой, что позволяет в общем случае хранить только верхнюю треугольную часть матрицы. Однако для задач с большим количеством неизвестных это так же приводит к проблеме нехватки памяти. Предлагаемый в данной работе метод, позволяет хранить только ненулевые члены матрицы жесткости. Суть его заключается в следующем. Первоначально, с целью выявления связей каждого узла с другими, производится анализ структуры дискретизации области на КЭ. Например, для КЭ - сетки, изображенной на рис. 1, соответствующая структура связей будет иметь вид:
Текст подпрограммы, реализующий предложенный алгоритм анализа структуры КЭ-разбиения тела, приведен в Приложении 1. Данный способ компактного хранения матрицы жесткости позволяет легко его использовать совместно с каким-нибудь численным методом. Наиболее удобным для этой цели представляется использование вышеизложенного итерационного метода Ланцоша, так как на каждой итерации требуется только перемножать матрицу коэффициентов СЛАУ и заданный вектор. Следовательно, для использования предложенного метода компактного хранения СЛАУ необходимо построить прямое и обратное преобразование в первоначальную квадратную матрицу. Пусть
где m – количество степеней свободы (m=1,2,3). Для прямого преобразования будут справедливы соотношения, обратные к соотношениям (*). 3 ЧИСЛЕННЫЕ ЭКСПЕРИМЕНТЫ Для проверки предлагаемого метода компактного хранения матрицы жесткости была решена задача о контактном взаимодействии оболочечной конструкции и ложемента [12] (рис. 4).
Данная задача решалась методом конечных элементов при помощи системы FORL [5]. Дискретная модель ложемента (в трехмерной постановке) представлена на Рис. 5.
При построении данной КЭ-модели было использовано 880 узлов и 2016 КЭ в форме тетраэдра. Полный размер матрицы жесткости для такой задачи составляет Данная задача решалась на ЭВМ с процессором Pentium 166 и 32 МБ ОЗУ двумя способами – методом Гаусса и методом Ланцоша. Сопоставление результатов решения приведено в Таблице 1. Таблица 1.
Из Таблицы 1 легко видеть, что результаты решения СЛАУ методом Гаусса и методом Ланцоша хорошо согласуются между собой, при этом время решения вторым способом почти в два раза меньше, чем в случае использования метода Гаусса. ВЫВОДЫ. В данной работе были рассмотрены способы компактного хранения матрицы коэффициентов системы линейных алгебраических уравнений (СЛАУ) и методы ее решения. Разработан алгоритм компактного хранения матрицы жесткости, позволяющий в несколько раз (иногда более чем в десятки раз) сократить объем требуемой памяти для хранения такой матрицы жесткости. Классические методы хранения, учитывающие симметричную и ленточную структуру матриц жесткости, возникающих при применении метода конечных элементов (МКЭ), как правило, не применимы при решении контактных задач, так как при их решении матрицы жесткости нескольких тел объединяются в одну общую матрицу, ширина ленты которой может стремиться к порядку системы.
Предложенная в работе методика компактного хранения матриц коэффициентов СЛАУ и использования метода Ланцоша позволили на примере решения контактных задач добиться существенной экономии процессорного времени и затрат оперативной памяти. ПРИЛОЖЕНИЕ 1 Исходный текст программы, реализующий анализ структуры КЭ-разбиения объекта. #include <math.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <fstream.h> #include "matrix.h" #define BASE3D_4 4 #define BASE3D_8 8 #define BASE3D_10 10 const double Eps = 1.0E-10; DWORD CurrentType = BASE3D_10; void PrintHeader(void) { printf("Command format: AConvert -<switch> <file1.in> <file2.in> <file3.out> [/Options]\n"); printf("Switch: -t10 - Tetraedr(10)\n"); printf(" -c8 - Cube(8)\n"); printf(" -s4 - Shell(4)\n"); printf(" -s8 - Shell(8)\n\n"); printf("Optins: /8 - convert Tetraedr(10)->8*Tetraedr(4)\n"); printf(" /6 - convert Cube(8)->6*Tetraedr(4)\n"); } bool Output(char* fname,Vector<double>& x,Vector<double>& y,Vector<double>& z, Matrix<DWORD>& tr, DWORD n, DWORD NumNewPoints,DWORD ntr,Matrix<DWORD>& Bounds,DWORD CountBn) { char* Label = "NTRout"; int type = CurrentType, type1 = (type==BASE3D_4 || type==BASE3D_10)? 3: 4; DWORD NewSize, i, j; ofstream Out; if (type==BASE3D_4) type1 = 3; else if (type==BASE3D_8) type1 = 4; else if (type==BASE3D_10) type1 = 6; Out.open(fname,ios::out | ios:: binary); if (Out.bad()) return true; Out.write((const char*)Label,6 * sizeof(char)); if (Out.fail()) return true; Out.write((const char*)&type,sizeof(int)); if (Out.fail()) return true; Out.write((const char*)&CountBn,sizeof(DWORD)); if (Out.fail()) { Out.close(); return true; } Out.write((const char*)&(NewSize = n + NumNewPoints),sizeof(DWORD)); if (Out.fail()) return true; Out.write((const char*)&(NumNewPoints),sizeof(DWORD)); if (Out.fail()) { Out.close(); return true; } for (DWORD i = 0; i < n; i++) { Out.write((const char*)&x[i],sizeof(double)); Out.write((const char*)&y[i],sizeof(double)); Out.write((const char*)&z[i],sizeof(double)); if (Out.fail()) { Out.close(); return true; } } for (i = 0; i < NumNewPoints; i++) { Out.write((const char*)&x[n + i],sizeof(double)); Out.write((const char*)&y[n + i],sizeof(double)); if (Out.fail()) { Out.close(); return true; } } Out.write((const char*)&(ntr),sizeof(DWORD)); if (Out.fail()) { Out.close(); return true; } for (i = 0; i < ntr; i++) for (j = 0; j < (DWORD)type; j++) { DWORD out = tr[i][j]; Out.write((const char*)&out,sizeof(DWORD)); if (Out.fail()) { Out.close(); return true; } } for (i = 0; i < CountBn; i++) for (j = 0; j < (DWORD)type1; j++) { DWORD out = Bounds[i][j]; Out.write((const char*)&out,sizeof(DWORD)); if (Out.fail()) { Out.close(); return true; } } { //********************* // Create Links printf("Create links...\r"); Vector<DWORD> Link(n), Size(n); Matrix<DWORD> Links(n,n); DWORD Count; int type = CurrentType; for (DWORD i = 0; i < n; i++) { for (DWORD j = 0; j < ntr; j++) for (DWORD k = 0; k < (DWORD)type; k++) if (tr[j][k] == i) for (DWORD m = 0; m < (DWORD)type; m++) Link[tr[j][m]] = 1; Count = 0; for (DWORD m = 0; m < n; m++) if (Link[m]) Count++; Size[i] = Count; Count = 0; for (DWORD m = 0; m < n; m++) if (Link[m]) Links[i][Count++] = m; //Set zero Link.ReSize(n); } // Output //********************* for (DWORD i = 0; i < n; i++) { DWORD Sz = Size[i]; Out.write((const char*)&Sz,sizeof(DWORD)); for (DWORD j = 0; j < Sz; j++) Out.write((const char*)&(Links[i][j]),sizeof(DWORD));
} //********************* } printf(" \r"); printf("Points: %ld\n",n); printf("FE: %ld\n",ntr); Out.close(); return false; } bool Test(DWORD* a,DWORD* b) { bool result; int NumPoints = 3; if (CurrentType == BASE3D_8) NumPoints = 4; else if (CurrentType == BASE3D_10) NumPoints = 6; for (int i = 0; i < NumPoints; i++) { result = false; for (int j = 0; j < NumPoints; j++) if (b[j] == a[i]) { result = true; break; } if (result == false) return false; } return true; } void Convert(Vector<double>& X,Vector<double>& Y,Vector<double>& Z, Matrix<DWORD>& FE,DWORD NumTr,Matrix<DWORD>& Bounds,DWORD& BnCount) { int cData8[6][5] = {{0,4,5,1,7}, {6,2,3,7,0}, {4,6,7,5,0}, {2,0,1,3,5}, {1,5,7,3,4}, {6,4,0,2,1}}, cData4[4][4] = {{0,1,2,3}, {1,3,2,0}, {3,0,2,1}, {0,3,1,2}}, cData10[4][7] = {{0,1,2,4,5,6,3}, {0,1,3,4,8,7,2}, {1,3,2,8,9,5,0}, {0,2,3,6,9,7,1}}, cData[6][7], Data[6], l, Num1, Num2, m; DWORD i, j, p[6], pp[6], Index; Matrix<DWORD> BoundList(4 * NumTr,6); double cx, cy, cz, x1, y1, z1, x2, y2, z2, x3, y3, z3; Bounds.ReSize(4 * NumTr,6); switch (CurrentType) { case BASE3D_4: Num1 = 4; Num2 = 3; for (l = 0; l < Num1; l++) for (m = 0; m < Num2+1; m++) cData[l][m] = cData4[l][m]; break; case BASE3D_8: Num1 = 6; Num2 = 4; for (l = 0; l < Num1; l++) for (m = 0; m < Num2 + 1; m++) cData[l][m] = cData8[l][m]; break; case BASE3D_10: Num1 = 4; Num2 = 6; for (l = 0; l < Num1; l++) for (m = 0; m < Num2+1; m++) cData[l][m] = cData10[l][m]; } printf("Create bounds...\r"); for (i = 0; i < NumTr - 1; i++) for (int j = 0; j < Num1; j++) if (!BoundList[i][j]) { for (l = 0; l < Num2; l++) p[l] = FE[i][cData[j][l]]; for (DWORD k = i + 1; k < NumTr; k++) for (int m = 0; m < Num1; m++) if (!BoundList[k][m]) { for (int l = 0; l < Num2; l++) pp[l] = FE[k][cData[m][l]]; if (Test(p,pp)) BoundList[i][j] = BoundList[k][m] = 1; } } for (i = 0; i < NumTr; i++) for (j = 0; j < (DWORD)Num1; j++) if (BoundList[i][j] == 0) { if (CurrentType == BASE3D_4) { cx = X[FE[i][cData[j][3]]]; cy = Y[FE[i][cData[j][3]]]; cz = Z[FE[i][cData[j][3]]]; } else if (CurrentType == BASE3D_10) { cx = X[FE[i][cData[j][6]]]; cy = Y[FE[i][cData[j][6]]]; cz = Z[FE[i][cData[j][6]]]; } else { cx = X[FE[i][cData[j][4]]]; cy = Y[FE[i][cData[j][4]]]; cz = Z[FE[i][cData[j][4]]]; } x1 = X[FE[i][cData[j][0]]]; y1 = Y[FE[i][cData[j][0]]]; z1 = Z[FE[i][cData[j][0]]]; x2 = X[FE[i][cData[j][1]]]; y2 = Y[FE[i][cData[j][1]]]; z2 = Z[FE[i][cData[j][1]]]; x3 = X[FE[i][cData[j][2]]]; y3 = Y[FE[i][cData[j][2]]]; z3 = Z[FE[i][cData[j][2]]]; for (l = 0; l < Num2; l++) Data[l] = cData[j][l]; if (((cx-x1)*(y2-y1)*(z3-z1) + (cy-y1)*(z2-z1)*(x3-x1) + (y3-y1)*(cz-z1)*(x2-x1) - (x3-x1)*(y2-y1)*(cz-z1) - (y3-y1)*(z2-z1)*(cx-x1) - (cy-y1)*(z3-z1)*(x2-x1)) > 0) { if (CurrentType == BASE3D_4) { Data[0] = cData[j][0]; Data[1] = cData[j][2]; Data[2] = cData[j][1]; } else if (CurrentType == BASE3D_10) { Data[0] = cData[j][0]; Data[1] = cData[j][2]; Data[2] = cData[j][1]; Data[3] = cData[j][5]; Data[5] = cData[j][3]; } else { Data[0] = cData[j][0]; Data[1] = cData[j][3]; Data[2] = cData[j][2]; Data[3] = cData[j][1]; } } for (l = 0; l < Num2; l++) Bounds[BnCount][l] = FE[i][Data[l]]; BnCount++; } } void main(int argc,char** argv) { char *input1, *input2, *input3, *op = "", *sw; bool CreateFile(char*,char*,char*,char*); printf("ANSYS->FORL file convertor. ZSU(c) 1998.\n\n"); if (argc < 5 || argc > 6) { PrintHeader(); return; } sw = argv[1]; input1 = argv[2]; input2 = argv[3]; input3 = argv[4]; if (!strcmp(sw,"-t10")) CurrentType = BASE3D_10; else if (!strcmp(sw,"-c8")) CurrentType = BASE3D_8; else { printf("Unknown switch %s\n\n",sw); PrintHeader(); return; } if (argc == 6) { op = argv[5]; if (strcmp(op,"/8") && strcmp(op,"/6")) { printf("Unknown options %s\n\n",op); PrintHeader(); return; } } if (CreateFile(input1,input2,input3,op)) printf("OK\n"); } bool CreateFile(char* fn1,char* fn2,char* fn3,char* Op) { FILE *in1, *in2, *in3; Vector<double> X(1000), Y(1000), Z(1000); DWORD NumPoints, NumFE, NumBounds = 0, tmp; Matrix<DWORD> FE(1000,10), Bounds; bool ReadTetraedrData(char*,char*,FILE*,FILE*,Vector<double>&,Vector<double>&,Vector<double>&, Matrix<DWORD>&,DWORD&,DWORD&), ReadCubeData(char*,char*,FILE*,FILE*,Vector<double>&,Vector<double>&,Vector<double>&, Matrix<DWORD>&,DWORD&,DWORD&); void Convert824(Matrix<DWORD>&,DWORD&), Convert1024(Matrix<DWORD>&,DWORD&); if ((in1 = fopen(fn1,"r")) == NULL) { printf("Unable open file %s",fn1); return false; } if ((in2 = fopen(fn2,"r")) == NULL) { printf("Unable open file %s",fn2); return false; } if (CurrentType == BASE3D_10) { if (!ReadTetraedrData(fn1,fn2,in1,in2,X,Y,Z,FE,NumPoints,NumFE)) return false; if (!strcmp(Op,"/8")) { // Create 8*Tetraedr(4) Convert1024(FE,NumFE); } Convert(X,Y,Z,FE,NumFE,Bounds,NumBounds); return!Output(fn3,X,Y,Z,FE,NumPoints,0,NumFE,Bounds,NumBounds); } if (CurrentType == BASE3D_8) { if (!ReadCubeData(fn1,fn2,in1,in2,X,Y,Z,FE,NumPoints,NumFE)) return false; if (!strcmp(Op,"/6")) { // Create 6*Tetraedr(4) Convert824(FE,NumFE); } Convert(X,Y,Z,FE,NumFE,Bounds,NumBounds); return!Output(fn3,X,Y,Z,FE,NumPoints,0,NumFE,Bounds,NumBounds); } return false; } void Convert824(Matrix<DWORD>& FE,DWORD& NumFE) { Matrix<DWORD> nFE(6 * NumFE,4); DWORD data[][4] = { { 0,2,3,6 }, { 4,5,1,7 }, { 0,4,1,3 }, { 6,7,3,4 }, { 1,3,7,4 }, { 0,4,6,3 } }, Current = 0; for (DWORD i = 0; i < NumFE; i++) for (DWORD j = 0; j < 6; j++) { for (DWORD k = 0; k < 4; k++) nFE[Current][k] = FE[i][data[j][k]]; Current++; } CurrentType = BASE3D_4; NumFE = Current; FE = nFE; } void Convert1024(Matrix<DWORD>& FE,DWORD& NumFE) { Matrix<DWORD> nFE(8 * NumFE,4); DWORD data[][4] = { { 3,7,8,9 }, { 0,4,7,6 }, { 2,5,9,6 }, { 7,9,8,6 }, { 4,8,5,1 }, { 4,5,8,6 }, { 7,8,4,6 }, { 8,9,5,6 } }, Current = 0; for (DWORD i = 0; i < NumFE; i++) for (DWORD j = 0; j < 8; j++) { for (DWORD k = 0; k < 4; k++) nFE[Current][k] = FE[i][data[j][k]]; Current++; } CurrentType = BASE3D_4; NumFE = Current; FE = nFE; } bool ReadTetraedrData(char* fn1,char* fn2,FILE* in1,FILE* in2,Vector<double>& X,Vector<double>& Y,Vector<double>& Z, Matrix<DWORD>& FE,DWORD& NumPoints,DWORD& NumFE) { double tx, ty, tz; char TextBuffer[1001]; DWORD Current = 0L, tmp; while (!feof(in1)) { if (fgets(TextBuffer,1000,in1) == NULL) { if (feof(in1)) break; printf("Unable read file %s",fn1); fclose(in1); fclose(in2); return false; } if (sscanf(TextBuffer,"%ld %lf %lf %lf", &NumPoints,&tx,&ty,&tz)!= 4) continue; X[Current] = tx; Y[Current] = ty; Z[Current] = tz; if (++Current == 999) { Vector<double> t1 = X, t2 = Y, t3 = Z; X.ReSize(2 * X.Size()); Y.ReSize(2 * X.Size()); Z.ReSize(2 * X.Size()); for (DWORD i = 0; i < Current; i++) { X[i] = t1[i]; Y[i] = t2[i]; Z[i] = t3[i]; } } if (Current % 100 == 0) printf("Line: %ld\r",Current); } fclose(in1); printf(" \r"); NumPoints = Current; Current = 0L; while (!feof(in2)) { if (fgets(TextBuffer,1000,in2) == NULL) { if (feof(in2)) break; printf("Unable read file %s",fn2); fclose(in2); return false; } if (sscanf(TextBuffer,"%d %d %d %d %d %ld %ld %ld %ld %ld %ld %ld %ld", &tmp,&tmp,&tmp,&tmp,&tmp, &FE[Current][0],&FE[Current][1],&FE[Current][2],&FE[Current][3], &FE[Current][4],&FE[Current][5],&FE[Current][6],&FE[Current][7])!= 13) continue; if (fgets(TextBuffer,1000,in2) == NULL) { printf("Unable read file %s",fn2); fclose(in2); return false; } if (sscanf(TextBuffer,"%ld %ld",&FE[Current][8],&FE[Current][9])!= 2) { printf("Unable read file %s",fn2); fclose(in2); return false; } { if (fabs((tx = 0.5*(X[FE[Current][0] - 1] + X[FE[Current][1] - 1])) - X[FE[Current][4] - 1]) > Eps) X[FE[Current][4] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][0] - 1] + Y[FE[Current][1] - 1])) - Y[FE[Current][4] - 1]) > Eps) Y[FE[Current][4] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][0] - 1] + Z[FE[Current][1] - 1])) - Z[FE[Current][4] - 1]) > Eps) Z[FE[Current][4] - 1] = tz; if (fabs((tx = 0.5*(X[FE[Current][2] - 1] + X[FE[Current][1] - 1])) - X[FE[Current][5] - 1]) > Eps) X[FE[Current][5] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][2] - 1] + Y[FE[Current][1] - 1])) - Y[FE[Current][5] - 1]) > Eps) Y[FE[Current][5] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][2] - 1] + Z[FE[Current][1] - 1])) - Z[FE[Current][5] - 1]) > Eps) Z[FE[Current][5] - 1] = tz; if (fabs((tx = 0.5*(X[FE[Current][0] - 1] + X[FE[Current][2] - 1])) - X[FE[Current][6] - 1]) > Eps) X[FE[Current][6] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][0] - 1] + Y[FE[Current][2] - 1])) - Y[FE[Current][6] - 1]) > Eps) Y[FE[Current][6] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][0] - 1] + Z[FE[Current][2] - 1])) - Z[FE[Current][6] - 1]) > Eps) Z[FE[Current][6] - 1] = tz; if (fabs((tx = 0.5*(X[FE[Current][0] - 1] + X[FE[Current][3] - 1])) - X[FE[Current][7] - 1]) > Eps) X[FE[Current][7] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][0] - 1] + Y[FE[Current][3] - 1])) - Y[FE[Current][7] - 1]) > Eps) Y[FE[Current][7] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][0] - 1] + Z[FE[Current][3] - 1])) - Z[FE[Current][7] - 1]) > Eps) Z[FE[Current][7] - 1] = tz; if (fabs((tx = 0.5*(X[FE[Current][3] - 1] + X[FE[Current][1] - 1])) - X[FE[Current][8] - 1]) > Eps) X[FE[Current][8] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][3] - 1] + Y[FE[Current][1] - 1])) - Y[FE[Current][8] - 1]) > Eps) Y[FE[Current][8] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][3] - 1] + Z[FE[Current][1] - 1])) - Z[FE[Current][8] - 1]) > Eps) Z[FE[Current][8] - 1] = tz; if (fabs((tx = 0.5*(X[FE[Current][3] - 1] + X[FE[Current][2] - 1])) - X[FE[Current][9] - 1]) > Eps) X[FE[Current][9] - 1] = tx; if (fabs((ty = 0.5*(Y[FE[Current][3] - 1] + Y[FE[Current][2] - 1])) - Y[FE[Current][9] - 1]) > Eps) Y[FE[Current][9] - 1] = ty; if (fabs((tz = 0.5*(Z[FE[Current][3] - 1] + Z[FE[Current][2] - 1])) - Z[FE[Current][9] - 1]) > Eps) Z[FE[Current][9] - 1] = tz; } if (++Current == 999) { Matrix<DWORD> t = FE; FE.ReSize(2 * FE.Size1(),10); for (DWORD i = 0; i < Current; i++) for (DWORD j = 0; j < 10; j++) FE[i][j] = t[i][j]; } if (Current % 100 == 0) printf("Line: %ld\r",Current); } NumFE = Current; for (DWORD i = 0; i < NumFE; i++) for (DWORD j = 0; j < 10; j++) FE[i][j]--; printf(" \r"); return true; } bool ReadCubeData(char* fn1,char*fn2,FILE* in1,FILE* in2,Vector<double>& X,Vector<double>& Y,Vector<double>& Z, Matrix<DWORD>& FE,DWORD& NumPoints,DWORD& NumFE) { double tx, ty, tz; char TextBuffer[1001]; DWORD Current = 0L, tmp; while (!feof(in1)) { if (fgets(TextBuffer,1000,in1) == NULL) { if (feof(in1)) break; printf("Unable read file %s",fn1); fclose(in1); fclose(in2); return false; } if (sscanf(TextBuffer,"%ld %lf %lf %lf", &NumPoints,&tx,&ty,&tz)!= 4) continue; X[Current] = tx; Y[Current] = ty; Z[Current] = tz; if (++Current == 999) { Vector<double> t1 = X, t2 = Y, t3 = Z; X.ReSize(2 * X.Size()); Y.ReSize(2 * X.Size()); Z.ReSize(2 * X.Size()); for (DWORD i = 0; i < Current; i++) { X[i] = t1[i]; Y[i] = t2[i]; Z[i] = t3[i]; } } if (Current % 100 == 0) printf("Line: %ld\r",Current); } fclose(in1); printf(" \r"); NumPoints = Current; Current = 0L; while (!feof(in2)) { if (fgets(TextBuffer,1000,in2) == NULL) { if (feof(in2)) break; printf("Unable read file %s",fn2); fclose(in2); return false; } if (sscanf(TextBuffer,"%d %d %d %d %d %ld %ld %ld %ld %ld %ld %ld %ld", &tmp,&tmp,&tmp,&tmp,&tmp, &FE[Current][0],&FE[Current][1],&FE[Current][3],&FE[Current][2], &FE[Current][4],&FE[Current][5],&FE[Current][7],&FE[Current][6])!= 13) continue; if (++Current == 999) { Matrix<DWORD> t = FE; FE.ReSize(2 * FE.Size1(),10); for (DWORD i = 0; i < Current; i++) for (DWORD j = 0; j < 10; j++) FE[i][j] = t[i][j]; } if (Current % 100 == 0) printf("Line: %ld\r",Current);} NumFE = Current; for (DWORD i = 0; i < NumFE; i++) for (DWORD j = 0; j < 10; j++) FE[i][j]--; printf(" \r"); return true;}ПРИЛОЖЕНИЕ 2. Исходный текст программы, реализующей алгоритм компактного хранения и решения СЛАУ высокого порядка. #include "matrix.h" class RVector { private: Vector<double> Buffer; public: RVector(void) {} ~RVector() {} RVector(DWORD Size) { Buffer.ReSize(Size); } RVector(RVector& right) { Buffer = right.Buffer; } RVector(Vector<double>& right) { Buffer = right; } DWORD Size(void) { return Buffer.Size(); } void ReSize(DWORD Size) { Buffer.ReSize(Size); } double& operator [] (DWORD i) { return Buffer[i]; } RVector& operator = (RVector& right) { Buffer = right.Buffer; return *this; } RVector& operator = (Vector<double>& right) { Buffer = right; return *this; } void Sub(RVector&); void Sub(RVector&,double); void Mul(double); void Add(RVector&); friend double Norm(RVector&,RVector&); }; class TSMatrix { private: Vector<double> Right; Vector<double>* Array; Vector<DWORD>* Links; uint Dim; DWORD Size; public: TSMatrix(void) { Size = 0; Dim = 0; Array = NULL; Links = NULL; } TSMatrix(Vector<DWORD>*,DWORD,uint); ~TSMatrix(void) { if (Array) delete [] Array; } Vector<double>& GetRight(void) { return Right; } DWORD GetSize(void) { return Size; } uint GetDim(void) { return Dim; } Vector<double>& GetVector(DWORD i) { return Array[i]; } Vector<DWORD>* GetLinks(void) { return Links; } void SetLinks(Vector<DWORD>* l) { Links = l; } void Add(Matrix<double>&,Vector<DWORD>&); void Add(DWORD I, DWORD L, DWORD J, DWORD K, double v) { DWORD Row = I, Col = L * Links[I].Size() * Dim + Find(I,J) * Dim + K; Array[Row][Col] += v; } void Add(DWORD I, double v) { Right[I] += v; } DWORD Find(DWORD,DWORD); void Restore(Matrix<double>&); void Set(DWORD,DWORD,double,bool); void Set(DWORD Index1,DWORD Index2,double value) { DWORD I = Index1 / Dim, L = Index1 % Dim, J = Index2 / Dim, K = Index2 % Dim, Pos = Find(I,J), Row = I, Col; if (Pos == DWORD(-1)) return; Col = L * Links[I].Size() * Dim + Find(I,J) * Dim + K; Array[Row][Col] = value; } bool Get(DWORD Index1,DWORD Index2,double& value) { DWORD I = Index1 / Dim, L = Index1 % Dim, J = Index2 / Dim, K = Index2 % Dim, Pos = Find(I,J), Row = I, Col; value = 0; if (Pos == DWORD(-1)) return false; Col = L * Links[I].Size() * Dim + Find(I,J) * Dim + K; value = Array[Row][Col]; return true; } void Mul(RVector&,RVector&); double Mul(DWORD,RVector&); void write(ofstream&); void read(ifstream&); }; class RMatrix { private: Vector<double> Buffer; DWORD size; public: RMatrix(DWORD sz) { size = sz; Buffer.ReSize(size*(size + 1)*0.5); } ~RMatrix() {} DWORD Size(void) { return size; } double& Get(DWORD i,DWORD j) { return Buffer[(2*size + 1 - i)*0.5*i + j - i]; } }; //************************ #include "smatrix.h" double Norm(RVector& Left,RVector& Right) { double Ret = 0; for (DWORD i = 0; i < Left.Size(); i++) Ret += Left[i] * Right[i]; return Ret; } void RVector::Sub(RVector& Right) { for (DWORD i = 0; i < Size(); i++) (*this)[i] -= Right[i]; } void RVector::Add(RVector& Right) { for (DWORD i = 0; i < Size(); i++) (*this)[i] += Right[i]; } void RVector::Mul(double koff) { for (DWORD i = 0; i < Size(); i++) (*this)[i] *= koff; } void RVector::Sub(RVector& Right,double koff) { for (DWORD i = 0; i < Size(); i++) (*this)[i] -= Right[i]*koff; } TSMatrix::TSMatrix(Vector<DWORD>* links, DWORD size, uint dim) { Dim = dim; Links = links; Size = size; Right.ReSize(Dim * Size); Array = new Vector<double>[Size]; for (DWORD i = 0; i < Size; i++) Array[i].ReSize(Links[i].Size() * Dim * Dim); } void TSMatrix::Add(Matrix<double>& FEMatr,Vector<DWORD>& FE) { double Res; DWORD RRow; for (DWORD i = 0L; i < FE.Size(); i++) for (DWORD l = 0L; l < Dim; l++) for (DWORD j = 0L; j < FE.Size(); j++) for (DWORD k = 0L; k < Dim; k++) { Res = FEMatr[i * Dim + l][j * Dim + k]; if (Res) Add(FE[i],l,FE[j],k,Res); } for (DWORD i = 0L; i < FE.Size(); i++) for (DWORD l = 0L; l < Dim; l++) { RRow = FE[UINT(i % (FE.Size()))] * Dim + l; Res = FEMatr[i * Dim + l][FEMatr.Size1()]; if (Res) Add(RRow,Res); } } DWORD TSMatrix::Find(DWORD I,DWORD J) { DWORD i; for (i = 0; i < Links[I].Size(); i++) if (Links[I][i] == J) return i; return DWORD(-1); } void TSMatrix::Restore(Matrix<double>& Matr) { DWORD i, j, NRow, NPoint, NLink, Pos; Matr.ReSize(Size * Dim,Size * Dim + 1); for (i = 0; i < Size; i++) for (j = 0; j < Array[i].Size(); j++) { NRow = j / (Array[i].Size() / Dim); // Number of row NPoint = (j - NRow * (Array[i].Size() / Dim)) / Dim; // Number of points NLink = j % Dim; // Number of link Pos = Links[i][NPoint]; Matr[i * Dim + NRow][Pos * Dim + NLink] = Array[i][j]; } for (i = 0; i < Right.Size(); i++) Matr[i][Matr.Size1()] = Right[i]; } void TSMatrix::Set(DWORD Index,DWORD Position,double Value,bool Case) { DWORD Row = Index, Col = Position * Links[Index].Size() * Dim + Find(Index,Index) * Dim + Position, i; double koff = Array[Row][Col], val; if (!Case) Right[Dim * Index + Position] = Value; else { Right[Index * Dim + Position] = Value * koff; for (i = 0L; i < Size * Dim; i++) if (i!= Index * Dim + Position) { Set(Index * Dim + Position,i,0); Set(i,Index * Dim + Position,0); if (Get(i,Index * Dim + Position,val)) Right[i] -= val * Value; } } } void TSMatrix::Mul(RVector& Arr,RVector& Res) { DWORD i, j, NRow, NPoint, NLink, Pos; Res.ReSize(Arr.Size()); for (i = 0; i < Size; i++) for (j = 0; j < Array[i].Size(); j++) { NRow = j / (Array[i].Size() / Dim); NPoint = (j - NRow * (Array[i].Size() / Dim)) / Dim; NLink = j % Dim; Pos = Links[i][NPoint]; Res[i * Dim + NRow] += Arr[Pos * Dim + NLink] * Array[i][j]; } } double TSMatrix::Mul(DWORD Index,RVector& Arr) { DWORD j, I = Index / Dim, L = Index % Dim, Start = L * (Array[I].Size() / Dim), Stop = Start + (Array[I].Size() / Dim), NRow, NPoint, NLink, Pos; double Res = 0; for (j = Start; j < Stop; j++) { NRow = j / (Array[I].Size() / Dim); NPoint = (j - NRow * (Array[I].Size() / Dim)) / Dim; NLink = j % Dim; Pos = Links[I][NPoint]; Res += Arr[Pos * Dim + NLink] * Array[I][j]; } return Res; } void TSMatrix::write(ofstream& Out) { DWORD ColSize; Out.write((char*)&(Dim),sizeof(DWORD)); Out.write((char*)&(Size),sizeof(DWORD)); for (DWORD i = 0; i < Size; i++) { ColSize = Array[i].Size(); Out.write((char*)&(ColSize),sizeof(DWORD)); for (DWORD j = 0; j < ColSize; j++) Out.write((char*)&(Array[i][j]),sizeof(double)); } for (DWORD i = 0; i < Size * Dim; i++) Out.write((char*)&(Right[i]),sizeof(double)); } void TSMatrix::read(ifstream& In) { DWORD ColSize; In.read((char*)&(Dim),sizeof(DWORD)); In.read((char*)&(Size),sizeof(DWORD)); if (Array) delete [] Array; Array = new Vector<double>[Size]; Right.ReSize(Size * Dim); for (DWORD i = 0; i < Size; i++) { In.read((char*)&(ColSize),sizeof(DWORD)); Array[i].ReSize(ColSize); for (DWORD j = 0; j < ColSize; j++) In.read((char*)&(Array[i][j]),sizeof(double)); } for (DWORD i = 0; i < Size * Dim; i++) In.read((char*)&(Right[i]),sizeof(double)); } Список литературы Зенкевич О., Морган К. Конечные методы и аппроксимация // М.: Мир, 1980 Зенкевич О., Метод конечных элементов // М.: Мир., 1975 Стрэнг Г., Фикс Дж. Теория метода конечных элементов // М.: Мир, 1977 Бахвалов Н.С.,Жидков Н.П., Кобельков Г.М. Численные методы // М.: наука, 1987 Воеводин В.В., Кузнецов Ю.А. Матрицы и вычисления // М.:Наука, 1984 Бахвалов Н.С. Численные методы // М.: Наука, 1975 Годунов С.К. Решение систем линейных уравнений // Новосибирск: Наука, 1980 Гоменюк С.И., Толок В.А. Инструментальная система анализа задач механики деформируемого твердого тела // Приднiпровський науковий вiсник – 1997. – №4. F.G. Gustavson, “Some basic techniques for solving sparse matrix algorithms”, // editer by D.J. Rose and R.A.Willoughby, Plenum Press, New York, 1972 А.Джордж, Дж. Лиу, Численное решение больших разреженных систем уравнений // Москва, Мир, 1984 D.J. Rose, “A graph theoretic study of the numerical solution of sparse positive definite system of linear equations” // New York, Academic Press, 1972 Мосаковский В.И., Гудрамович В.С., Макеев Е.М., Контактные задачи теории оболочек и стержней // М.:”Машиностроение”, 1978
Воспользуйтесь поиском по сайту: ![]() ©2015 - 2025 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|