Проведенные исследования и выводы

Так как вместо решения бесконечномерной задачи ищется приближённое решение, полученное как линейная комбинация финитных кусочно-полиномиальных функций, то мы получаем приближённое решение. В данной работе искомая функция и правая часть представлены в виде билинейных интерполянтов, соответственно полученные решения вычисляются точно для полиномов первой степени, что подтверждается результатами тестов. Для полиномов выше первой степени решение вычисляется уже с погрешностью.

 

Тексты основных модулей программ

Листинг программы

#include "solver.h" //решение СЛАУ

#include "paint.h" //визуализация решения

#include "task.h" //постановка задач

//глобальная матрицы в разреженном строчном формате и вектор

int *ig, *jg, *ia, kk;

double *di, *ggl, *ggu, *gB;

double *gr, *gphi, *hr, *hphi, *q; //сетка

int **xyk, **coord, **cnd1, **cnd2, **cnd3;

int nr, nphi, L, N, K, size, n1, n2, n3;

void AddElemenit(int i, int j, double a);

void nforming(int);

double numIn(double r1, double phi1, double r2, double phi2, int i, int j, int k);

//считывание/формирование сетки

void grid()

{

FILE *fi;

fopen_s(&fi, "g.txt", "r");

fscanf_s(fi, "%d", &nr);

gr = new double[nr];

for(int i = 0; i < nr; ++i)

fscanf_s(fi, "%lf", &gr[i]);

fscanf_s(fi, "%d", &nphi);

gphi = new double[nphi];

for(int i = 0; i < nphi; ++i)

fscanf_s(fi, "%lf", &gphi[i]);

fscanf_s(fi, "%d", &L);

hr = new double[L];

hphi = new double[L];

xyk = new int*[5];

for(int i = 0; i < L; ++i)

xyk[i] = new int[L];

for(int i = 0; i < L; ++i)

{

fscanf_s(fi, "%d %d %d %d %d", &xyk[i][0], &xyk[i][1], &xyk[i][2], &xyk[i][3], &xyk[i][4]);

--xyk[i][0]; --xyk[i][1]; --xyk[i][2]; --xyk[i][3]; --xyk[i][4];

}

fscanf_s(fi, "%d", &N);

coord = new int*[N];

for(int i = 0; i < N; ++i)

{

coord[i] = new int[2];

fscanf_s(fi, "%d %d", &coord[i][0], &coord[i][1]);

--coord[i][0];

--coord[i][1];

}

for(int i = 0; i < L; ++i)

{

hr[i] = gr[xyk[i][2]]-gr[xyk[i][1]];

hphi[i] = gphi[xyk[i][4]]-gphi[xyk[i][3]];

}

gB = new double[N];

for(int i = 0; i < N; ++i)

gB[i] = 0;

di = new double[N];

q = new double[N];

}

//получение краевых условий

void cond()

{

FILE *fi;

fopen_s(&fi, "cond.txt", "r");

fscanf_s(fi, "%d", &n1);

cnd1 = new int*[n1];

for(int i = 0; i < n1; ++i)

cnd1[i] = new int[6];

for(int i = 0; i < n1; ++i)

{

fscanf_s(fi, "%d %d %d %d %d %d", &cnd1[i][0], &cnd1[i][1], &cnd1[i][2], &cnd1[i][3], &cnd1[i][4], &cnd1[i][5]);

--cnd1[i][0]; --cnd1[i][1]; --cnd1[i][2]; --cnd1[i][3]; --cnd1[i][4]; --cnd1[i][5];

}

fscanf_s(fi, "%d", &n2);

cnd2 = new int*[n2];

for(int i = 0; i < n2; ++i)

cnd2[i] = new int[6];

for(int i = 0; i < n2; ++i)

{

fscanf_s(fi, "%d %d %d %d %d %d", &cnd2[i][0], &cnd2[i][1], &cnd2[i][2], &cnd2[i][3], &cnd2[i][4], &cnd2[i][5]);

--cnd2[i][0]; --cnd2[i][1]; --cnd2[i][2]; --cnd2[i][3]; --cnd2[i][4]; --cnd2[i][5];

}

fscanf_s(fi, "%d", &n3);

cnd3 = new int*[n3];

for(int i = 0; i < n3; ++i)

cnd3[i] = new int[6];

for(int i = 0; i < n3; ++i)

{

fscanf_s(fi, "%d %d %d %d %d %d", &cnd3[i][0], &cnd3[i][1], &cnd3[i][2], &cnd3[i][3], &cnd3[i][4], &cnd3[i][5]);

--cnd3[i][0]; --cnd3[i][1]; --cnd3[i][2]; --cnd3[i][3]; --cnd3[i][4]; --cnd3[i][5];

}

fclose(fi);

}

//поиск номера узла

int search(int r, int phi)

{

for(int i = 0; i < N; ++i)

if(coord[i][0] == r)

if(coord[i][1] == phi)

return i;

return -1;

}

//возвращает глобальный номер l-конечного элемента i-локального узла

int GlobalNum(int l, int i)

{

switch(i)

{

case 0 : return search(xyk[l][1], xyk[l][3]);

case 1 : return search(xyk[l][2], xyk[l][3]);

case 2 : return search(xyk[l][1], xyk[l][4]);

case 3 : return search(xyk[l][2], xyk[l][4]);

}

return -1;

}

//теперь генерация портрета матрицы

void GeneratePortrait()

{

int i = 0, j = 0, k = 0, ver[2][6];

int **vx;

vx = new int*[2];

vx[0] = new int[6*L];

vx[1] = new int[6*L];

ig = new int[N+1];

int *flags;//массив флагов для всех узлов

flags = new int[6*L];

for(; i < L*6; ++i)

flags[i] = 0; //вначале мы ещё не заносили узлы

for(i = 0; i < N + 1; ++i)

ig[i] = 0;

for(i = 0; i < N; ++i)

di[i] = 0;

//проходим по каждой области

for(i = 0; i < L; ++i)

{

ver[0][0] = GlobalNum(i, 0);

ver[1][0] = GlobalNum(i, 1);

ver[0][1] = GlobalNum(i, 0);

ver[1][1] = GlobalNum(i, 2);

ver[0][2] = GlobalNum(i, 1);

ver[1][2] = GlobalNum(i, 2);

ver[0][3] = GlobalNum(i, 0);

ver[1][3] = GlobalNum(i, 3);

ver[0][4] = GlobalNum(i, 1);

ver[1][4] = GlobalNum(i, 3);

ver[0][5] = GlobalNum(i, 2);

ver[1][5] = GlobalNum(i, 3);

for(int j = 0; j < 6; ++j)

{

int kk = i*6 + j;

vx[0][kk] = ver[0][j];

vx[1][kk] = ver[1][j];

}

}

for(i = 0; i < L*6; ++i)

for(j = i; j < L*6; ++j)

if(vx[0][i] == vx[0][j])

if(vx[1][i] == vx[1][j])

++flags[j];

for(k = 0; k < L*6; ++k)

if(1 == flags[k])

++ig[vx[1][k]+1];

for(i = 1; i < N + 1; ++i)

ig[i] = ig[i-1] + ig[i];

size = ig[N];

jg = new int[size];

int jj = 0;

sort(vx, flags, L);

for(i = 0; i < L*6; ++i)

{

if(2 == flags[i])

++jj;

jg[i-jj] = vx[0][i];

}

ggu = new double[size];

ggl = new double[size];

for(i = 0; i < size; ++i)

ggu[i] = ggl[i] = 0;

}

//теперь занесение элеменита в глобальную матрицу

void AddElemenit(int i, int j, double a)

{

int ind;

if(i == j)

{

di[i] += a;

return;

}

if(i < j)

{

for(ind = ig[j]; ind < ig[j+1]; ++ind)

if(jg[ind] == i)

break;

ggu[ind] += a;

}

else

{

for(ind = ig[i]; ind < ig[i+1]-1; ++ind)

if(jg[ind] == j)

break;

ggl[ind] += a;

}

}

//теперь формирование глобальной матрицы, ухх, наконец-то я до этого дошёл =D

void BuildGlobal()

{

int i;

for(i = 0; i < L; ++i)

//в каждой области формируем матрицу

nforming(i);

}

//теперь мы учимся применять вторые краевые условия

void second()

{

double lb[2], h, lM[2][2], s = 0;

for(int i = 0; i < n2; ++i)

{

kk = i;

if(cnd2[i][2] == cnd2[i][3])

//вдоль ребра по phi

for(int k = 0; k < 2; ++k)

lb[k] = numIn(gr[cnd2[i][2]], gphi[cnd2[i][4]], gr[cnd2[i][3]], gphi[cnd2[i][5]], k, k, 3);

else

//вдоль ребра по r

for(int k = 0; k < 2; ++k)

lb[k] = numIn(gr[cnd2[i][2]], gphi[cnd2[i][4]], gr[cnd2[i][3]], gphi[cnd2[i][5]], k, k, 4);

gB[search(cnd2[i][2], cnd2[i][4])] += lb[0];

gB[search(cnd2[i][3], cnd2[i][5])] += lb[1];

}

}

//теперь учитываем третьи магические условия

void third()

{

double h, ub[2], local_b[2], s = 0, s1;

for(int i = 0; i < n3; ++i)

{

kk = i;

if(cnd3[i][2] == cnd3[i][3])

for(int k = 0; k < 2; ++k)

{

for(int m = 0; m < 2; ++m)

{

s1 = beta*numIn(gr[cnd3[i][2]], gphi[cnd3[i][4]], gr[cnd3[i][3]], gphi[cnd3[i][5]], k, m, 6);

AddElemenit(search(cnd3[i][2], cnd3[i][k+4]), search(cnd3[i][3], cnd3[i][m+4]), s1);

}

local_b[k] = beta*numIn(gr[cnd3[i][2]], gphi[cnd3[i][4]], gr[cnd3[i][3]], gphi[cnd3[i][5]], k, k, 8);

}

else

for(int k = 0; k < 2; ++k)

{

for(int m = 0; m < 2; ++m)

{

s1 = beta*numIn(gr[cnd3[i][2]], gphi[cnd3[i][4]], gr[cnd3[i][3]], gphi[cnd3[i][5]], k, m, 7);

AddElemenit(search(cnd3[i][k+2], cnd3[i][4]), search(cnd3[i][m+2], cnd3[i][4]), s1);

}

local_b[k] = beta*numIn(gr[cnd3[i][2]], gphi[cnd3[i][4]], gr[cnd3[i][3]], gphi[cnd3[i][5]], k, k, 9);

}

gB[search(cnd3[i][2], cnd3[i][4])] += local_b[0];

gB[search(cnd3[i][3], cnd3[i][5])] += local_b[1];

}

}

void zeroman(int i, int r1, int phi1, int r2, int phi2)

{

int j = 0;

int z1 = search(r1, phi1);

int z2 = search(r2, phi2);

di[z1] = 1;

di[z2] = 1;

gB[z1] = lordC(i, gr[r1], gphi[phi1]);

gB[z2] = lordC(i, gr[r2], gphi[phi2]);

//обнуление верхней треугольной матрицы

for(; j < size; ++j)

if(jg[j] == z1 || jg[j] == z2)

ggu[j] = 0;

//обнуление нижней треугольной матрицы

for(j = ig[z1]; j < ig[z1+1]; ++j)

ggl[j] = 0;

for(j = ig[z2]; j < ig[z2+1]; ++j)

ggl[j] = 0;

}

//теперь учитываем ГЛАВНЫЕ КРАЕВЫЕ УСЛОВИЯ

void overlord()

{

for(int i = 0; i < n1; ++i)

zeroman(i, cnd1[i][2], cnd1[i][4], cnd1[i][3], cnd1[i][5]);

}

//подынтегральные функции (k - номер пфункции)

double locMatr(double rp, double phis, double r, double phi, double hr, double hphi, int i, int j, int k)

{

//локаные линейные базис-функции

double psi[4], dpsir[4], dpsphi[4];

double rl[2], phil[2];

rl[0] = (rp+hr-r)/hr;

rl[1] = (r-rp)/hr;

phil[0] = (phis+hphi-phi)/hphi;

phil[1] = (phi-phis)/hphi;

//собрание локальной матрицы массы

if(k == 0)

{

psi[0] = rl[0]*phil[0];

psi[1] = rl[1]*phil[0];

psi[2] = rl[0]*phil[1];

psi[3] = rl[1]*phil[1];

return psi[i]*psi[j]*r;

}

//вектора правой части

if(k == 2)

{

double local_f[4], lf;

local_f[0] = f(gr[xyk[kk][1]], gphi[xyk[kk][3]],kk);

local_f[1] = f(gr[xyk[kk][2]], gphi[xyk[kk][3]],kk);

local_f[2] = f(gr[xyk[kk][1]], gphi[xyk[kk][4]],kk);

local_f[3] = f(gr[xyk[kk][2]], gphi[xyk[kk][4]],kk);

psi[0] = rl[0]*phil[0];

psi[1] = rl[1]*phil[0];

psi[2] = rl[0]*phil[1];

psi[3] = rl[1]*phil[1];

lf = local_f[0] * psi[0] + local_f[1] * psi[1] + local_f[2] * psi[2] + local_f[3] * psi[3];

return lf*psi[i]*r;

}

//краевые условия второго типа по одной координате( phi )

if(k == 3)

{

double local_theta[2];

local_theta[0] = secondC(cnd2[kk][1], gr[cnd2[kk][2]], gphi[cnd2[kk][4]]);

local_theta[1] = secondC(cnd2[kk][1], gr[cnd2[kk][3]], gphi[cnd2[kk][5]]);

psi[0] = rl[0]*phil[0];

psi[1] = rl[0]*phil[1];

return (local_theta[0]*psi[0] + local_theta[1]*psi[1])*psi[i]*r;

}

//краевые условия второго типа по одной координате( r )

if(k == 4)

{

double local_theta[2];

local_theta[0] = secondC(cnd2[kk][1], gr[cnd2[kk][2]], gphi[cnd2[kk][4]]);

local_theta[1] = secondC(cnd2[kk][1], gr[cnd2[kk][3]], gphi[cnd2[kk][5]]);

psi[0] = rl[0]*phil[0];

psi[1] = rl[1]*phil[0];

return (local_theta[0]*psi[0] + local_theta[1]*psi[1])*psi[i]*r;

}

//краевые условия третьего типа по phi для матрицы

if(k == 6)

{

psi[0] = rl[0]*phil[0];

psi[1] = rl[0]*phil[1];

return psi[i]*psi[j]*r;

}

//краевые условия третьего типа по r для матрицы

if(k == 7)

{

psi[0] = rl[0]*phil[0];

psi[1] = rl[1]*phil[0];

return psi[i]*psi[j]*r;

}

//третьи краевые условия для вектора правой части по фи

if(k == 8)

{

double ub1, ub2;

ub1 = thirdC(cnd3[kk][1], gr[cnd3[kk][2]], gphi[cnd3[kk][4]]);

ub2 = thirdC(cnd3[kk][1], gr[cnd3[kk][3]], gphi[cnd3[kk][5]]);

psi[0] = rl[0]*phil[0];

psi[1] = rl[0]*phil[1];

return (ub1*psi[0] + ub2*psi[1])*psi[i]*r;

}

//третьи краевые условия для вектора правой части по r

if(k == 9)

{

double ub1, ub2;

ub1 = thirdC(cnd3[kk][1], gr[cnd3[kk][2]], gphi[cnd3[kk][4]]);

ub2 = thirdC(cnd3[kk][1], gr[cnd3[kk][3]], gphi[cnd3[kk][5]]);

psi[0] = rl[0]*phil[0];

psi[1] = rl[1]*phil[0];

return (ub1*psi[0] + ub2*psi[1])*psi[i]*r;

}

//раскладываем лямбду по биквадратичному базису и

//считаем элементы локальной матрицы жёсткости

double local_lambda[9], lam, rq[3], phiq[3], psix[9];

int l = k - 10;

local_lambda[0] = lambda(gr[xyk[l][1]], gphi[xyk[l][3]], 0);

local_lambda[1] = lambda(gr[xyk[l][1]]+hr/2, gphi[xyk[l][3]], 0);

local_lambda[2] = lambda(gr[xyk[l][2]], gphi[xyk[l][3]], 0);

local_lambda[3] = lambda(gr[xyk[l][1]], gphi[xyk[l][3]]+hphi/2, 0);

local_lambda[4] = lambda(gr[xyk[l][1]]+hr/2, gphi[xyk[l][3]]+hphi/2, 0);

local_lambda[5] = lambda(gr[xyk[l][2]], gphi[xyk[l][3]]+hphi/2, 0);

local_lambda[6] = lambda(gr[xyk[l][1]], gphi[xyk[l][4]], 0);

local_lambda[7] = lambda(gr[xyk[l][1]]+hr/2, gphi[xyk[l][4]], 0);

local_lambda[8] = lambda(gr[xyk[l][2]], gphi[xyk[l][4]], 0);

rq[0] = 2*(rl[1] - 0.5)*(rl[1] - 1);

rq[1] = -4*rl[1]*(rl[1] - 1);

rq[2] = 2*rl[1]*(rl[1] - 0.5);

phiq[0] = 2*(phil[1] - 0.5)*(phil[1] - 1);

phiq[1] = -4*phil[1]*(phil[1] - 1);

phiq[2] = 2*phil[1]*(phil[1] - 0.5);

psix[0] = rq[0]*phiq[0];

psix[1] = rq[1]*phiq[0];

psix[2] = rq[2]*phiq[0];

psix[3] = rq[0]*phiq[1];

psix[4] = rq[1]*phiq[1];

psix[5] = rq[2]*phiq[1];

psix[6] = rq[0]*phiq[2];

psix[7] = rq[1]*phiq[2];

psix[8] = rq[2]*phiq[2];

lam = 0;

for(int z = 0; z < 9; ++z)

lam += local_lambda[z]*psix[z];

//матрица жёсткости

dpsir[0] = -1/hr*phil[0];

dpsir[1] = 1/hr*phil[0];

dpsir[2] = -1/hr*phil[1];

dpsir[3] = phil[1]/hr;

dpsphi[0] = -rl[0]/hphi;

dpsphi[1] = -rl[1]/hphi;

dpsphi[2] = rl[0]/hphi;

dpsphi[3] = rl[1]/hphi;

return lam*r*(dpsir[i]*dpsir[j] + dpsphi[i]*dpsphi[j]/(r*r));

}

//численное интегрирование(кубатурная формула Гаусса)

double numIn(double r1, double phi1, double r2, double phi2, int i, int j, int k)

{

double sum = 0.0;

double hr = r2 - r1, hphi = phi2 - phi1;

double xh = r1 + r2, yh = phi1 + phi2;

double rp = (xh/2.0)+hr/(2*sqrt(3.0));

double xm = (xh/2.0)-hr/(2*sqrt(3.0));

double yp = (yh/2.0)+hphi/(2*sqrt(3.0));

double ym = (yh/2.0)-hphi/(2*sqrt(3.0));

//краевые условия второго типа по одной координате( phi )

if(k == 3)

{

sum = hphi/2*(locMatr(r1, phi1, rp, yp, 1, hphi, i, j, k) + locMatr(r1, phi1, xm, ym, 1, hphi, i, j, k));

return sum;

}

//краевые условия второго типа по одной координате( r )

if(k == 4)

{

sum = hr/2*(locMatr(r1, phi1, rp, yp, hr, 1, i, j, k) + locMatr(r1, phi1, xm, ym, hr, 1, i, j, k));

return sum;

}

//краевые условия третьего типа по phi

if(k == 6 || k == 8)

{

sum = hphi/2*(locMatr(r1, phi1, rp, yp, 1, hphi, i, j, k) + locMatr(r1, phi1, xm, ym, 1, hphi, i, j, k));

return sum;

}

//краевые условия третьего типа по r

if(k == 7 || k == 9)

{

sum = hr/2*(locMatr(r1, phi1, rp, yp, hr, 1, i, j, k) + locMatr(r1, phi1, xm, ym, hr, 1, i, j, k));

return sum;

}

sum = hr*hphi/4*(locMatr(r1, phi1, rp, yp, hr, hphi, i, j, k) + locMatr(r1, phi1, xm, yp, hr, hphi, i, j, k) +

locMatr(r1, phi1, xm, ym, hr, hphi, i, j, k) + locMatr(r1, phi1, rp, ym, hr, hphi, i, j, k));

return sum;

}

//теперь формирование локальных матриц численно

void nforming(int l)

{

double lA[4][4], lB[4], G[4][4], M[4][4];

kk = l;

for(int i = 0; i < 4; ++i)

{

for(int j = 0; j < 4; ++j)

{

M[i][j] = numIn(gr[xyk[l][1]], gphi[xyk[l][3]], gr[xyk[l][2]], gphi[xyk[l][4]], i, j, 0);

M[i][j] *= gamma(gr[xyk[l][1]], gphi[xyk[l][3]], l);

G[i][j] = numIn(gr[xyk[l][1]], gphi[xyk[l][3]], gr[xyk[l][2]], gphi[xyk[l][4]], i, j, 10+l);

lA[i][j] = G[i][j] + M[i][j];

AddElemenit(GlobalNum(l, i), GlobalNum(l, j), lA[i][j]);

}

lB[i] = numIn(gr[xyk[l][1]], gphi[xyk[l][3]], gr[xyk[l][2]], gphi[xyk[l][4]], i, i, 2);

gB[GlobalNum(l, i)] += lB[i];

}

}

void main(int argc, char **argv)

{

//считываем сетку

grid();

//считываем краевые условия всех типов

cond();

//формируем портрет матрицы

GeneratePortrait();

//собираем глобальные матрицу и вектор

BuildGlobal();

//учитываем вторые краевые условия

second();

//третьи

third();

//главные(естественные)

overlord();

Matrix *Matr = new Matrix(ig, jg, ggl, ggu, di, gB, N);

//решаем(ЛОС с LU - факторизацией)

Solver(Matr, q);

//рисуем

//pain(argc, argv, q);

Matr->~Matrix();

//ничего

printf_s("\nTo do nothing...\n");

_getch();

}