Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

KM2016 / FEM2_1 / fem3 / fem3_1

.pdf
Скачиваний:
12
Добавлен:
14.03.2016
Размер:
62.13 Кб
Скачать

2010-03-01

fem3_1.cpp

1

//Приложение к разделу 3 Однородный стержень

//Коэффициенты D=C=A=1,

//Граничные условия третьего рода: u0-D_coeff*DuDx =0, u1+D-coeff*DuDx=0.

//Тест на совпадение с заранее заданным аналитическим решением

//fem3.h

/*

#include <ctype.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h>

int knots_N, test, result;

double *q, *qq, *x, *solution, *up, *down, *diag ; double h, x_max;

double K[500][500];

int output(int); void K_ij(void);

void q_i(int , double [], double [], double (*)( double)); double intg_q(int i, int fb, double *x,

double (*fun)(double),

double (*domik)(double, int, double *)); double intg_q_analityc(int i, int fb, double *x); double domik_f(double x, int j, double *xx);

double domik_b(double x, int j, double *xx);

void progon(int, double down[], double diag[], double up[], double q[]); int i_max(int N, int p, double V[]);

void SaveToFile(int knots_N, double* x, const char* filename);

void SaveToFile_Kqx(int knots_N, double* q, double* x,const char* filename); */

//fem3_1.cpp

#include "fem3_1.h"

static double fun_q(double x) { // правая часть дифференциального уравнения return -2;

}

int main(int argc,char *argv[]) { x_max = 1; // задаём длину стержня

knots_N = 11; // задаём число узлов, включая узлы на границах

x = new double[knots_N]; // Выделение памяти для координат узлов

q = new double[knots_N]; // Выделение памяти для правой части матичногшо уравнения

qq = new double[knots_N]; // Ещё раз выделение памяти для правой части матричного уравнения h = x_max/(knots_N-1);

for (int i = 0; i < knots_N; i++) { x[i] = h*i; } SaveToFile(knots_N, x,"x.dat" );

solution = new double[knots_N]; // Выделение памяти для решения

K_ij(); // Вычисление матричных коэффициентов

q_i(knots_N, x, q, fun_q); // Вычисление правой части матричного уравнения SaveToFile(knots_N, q,"qa.dat" ); // Запись в файл правой части матричного уравнения

progon(knots_N, down, diag, up, q); // Решение матричного уравнения методом прогонки SaveToFile(knots_N, q,"q_post.dat" ); // Запись в файл решения матричного уравнения

SaveToFile_Kqx(knots_N, qq, x,"Kqx.sce" ); // Запись в файл матричного уравнения для решения в SCIELAB test = 1;

result = output(test, knots_N, x, solution, "result.txt"); // Сравнение с точным аналитическим решением

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

2010-03-01

fem3_1.cpp

2

return result;

}

//Вывод решения в файл

int output(int test, int N, double *x, double *solution, const char *filename) { FILE *out;

out = fopen(filename, "wt");; double u_i, x_i, sol_i, q_i;

if (test == 1) {

fprintf(out,"\n x u(x) solution\n"); for (int i=0;i<N;i++) {

x_i = x[i];

u_i = -2 + x_i - x_i*x_i; sol_i = solution[i];

fprintf(out,"%-12.3g%-12.7g%-12.7g\n",x_i, u_i, sol_i);

}

result = 1;

}

else if (test == 0) {

fprintf(out,"\n x q(x) solution\n"); for (int i=0;i<N;i++) {

x_i = x[i];

sol_i = solution[i]; q_i = fun_q(x_i);

fprintf(out,"%-12.3g%-12.7g%-12.7g\n",x_i, q_i, sol_i);

}

result = 1;

}

else {

fprintf(out,"\n Sorry, no solution!\n"); result = 0;

}

fclose(out); return result;

}

// Вычисление матричных элементов void K_ij(void) {

//построение матрицы К

for (int i=0; i < knots_N; i++) { for (int j=0; j < knots_N;j++) { if (i==j) {

if (i==0){ K[i][i] = 1./h+1; }

else if (i==knots_N-1) { K[i][i] = 1./h-1; } else{ K[i][i] = 2./h; }

}

if ((i-j)==1) { K[i][j] = -1./h; } if ((i-j)==-1) { K[i][j] = -1./h; } if (abs((i-j))>1) { K[i][j] = 0.; }

}

}

down = new double[knots_N]; diag = new double[knots_N]; up = new double[knots_N];

for (int i=0; i < knots_N; i++) { for (int j=0; j < knots_N;j++) {

if (i==j) { diag[i] = K[i][i]; }

if ((i-j)==1) { down[i] = K[i][j]; } if ((i-j)==-1) { up[i] = K[i][j]; }

}

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

2010-03-01

fem3_1.cpp

3

}

}

void q_i(int knots_N, double x [], double q[], double (*fun_q)( double xi)) {

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

//построение правой части уравнения Кu=q

//knots_N - число узлов

//x[] - координаты узлов

//funq(x) - правая часть диф. уравнения

int n = knots_N - 1; // n - индекс последнего узла for (int i=0; i < knots_N; i++) {

if (i == 0) {

q[0] = intg_q(0, 1, x, fun_q, domik_f);

//q[0] = intg_q_analityc(0, 1, x);

}

else if (i == n) {

q[n] = intg_q(n, 0, x, fun_q, domik_b);

//q[n] = intg_q_analityc(n, 0, x);

}

else {

q[i] = intg_q(i, 0, x, fun_q, domik_b) + intg_q(i, 1, x, fun_q, domik_f);

//q[i] = intg_q_analityc(i, 0, x) + intg_q_analityc(i, 1, x);

}

qq[i] = q[i];

}

}

double intg_q(int j, int fb, double *x, double (*fun)(double),

double (*domik)(double, int, double *)) {

//Интегрируем функцию domik*fun_q

//j - индекс узла

//fb = 1 вперёд из узла i, иначе - назад

//x[] - координаты узлов

//fun_q(x) - интегрируемая функция, x - переменная интегрирования

//domik(x,i,xx[]) - x - переменная интегрирования, i -индекс строки,

double a, b, h, dh, x_k, x_kp, s; int m = 10;

if (fb == 1) { // интегрируем вперёд // x[j] - нижний предел интеграла a = x[j]; b = x[j+1];

h = b - a; dh = h/m; s = 0;

for (int k=0; k<m; k++) { x_k = x[j] + dh*k; x_kp = x_k + dh;

s = s + 0.5*dh*( domik_f(x_k,j,x)*fun(x_k) + domik_f(x_kp,j,x)*fun(x_kp) );

}

}

else { // интегрируем назад

// x[j-1] - нижний предел интеграла a = x[j-1]; b = x[j];

h = b - a; dh = h/m; s = 0;

for (int k=0; k<m; k++) { x_k = a + dh*k;

x_kp = x_k + dh;

s = s + 0.5*dh*( domik_b(x_k,j,x)*fun(x_k) + domik_b(x_kp,j,x)*fun(x_kp) );

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

2010-03-01

fem3_1.cpp

4

}

}

return s;

}

double intg_q_analityc(int i, int fb, double *x) {

//Интегрируем функцию domik*fun_q

//i - индекс строки

//fb = 1 вперёд из узла i, иначе - назад

//x[] - координаты узлов

double a, b, s;

if (fb == 1) { // интегрируем вперёд a = x[i];

b = x[i+1]; h = b-a;

s = -h;

}

else { // интегрируем назад a = x[i-1];

b = x[i]; h = b-a; s = -h;

}

return s;

}

double domik_f(double x, int j, double *xx) {

//Пробная функция для интегрирования из узла j вперёд

//x - переменная интегрирования

//j - индекс узла c коньком крыши

//xx[] - координаты всех узлов

//h - шаг между узлами

double h, value ;

h = xx[j+1] - xx[j];

if ((x >= xx[j]) && (x <= xx[j+1])) { value = -1.0/h*(x - xx[j] - h);

}

else value = 0;

}

double domik_b(double x, int j, double *xx) {

//Пробная функция для интегрирования из узла j назад

//x - переменная интегрирования

//j - индекс узла c коньком крыши

//xx[] - координаты всех узлов

//h - шаг между узлами

double h, value ;

h = xx[j] - xx[j-1];

if ((x >= xx[j-1]) && (x <= xx[j])) { value = 1.0/h*(x - xx[j] + h);

}

else value = 0;

}

void progon(int n,double c[],double a[],double b[],double g[])

//Решение линейной трёхдиагональной матрицы методом прогонки

//int n - порядок марицы

//double c[] - входной вектор длины n - диагональные матричные элементы под главной диагональю

//

c[0] не используется

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

2010-03-01

fem3_1.cpp

5

//double a[] - входной вектор длины n - диагональные матричные элементы в главной диагонали

//

разрушается в процессе вычислений

//double b[] - входной вектор длины n - диагональные матричные элементы над главной диагональю,

//

b[n-1] не используется

//double g[ - входной вектор длины n - правая часть матричного уравнения,

//

при вычислении разрушается и заменяется решением

{

 

int j,i; double r;

for(i=1;i<n;i++) { j=i-1; r=c[i]/a[j]; a[i]-=r*b[j]; g[i]-=r*g[j];

}

j=n-1; g[j]/=a[j];

for(i=n-2 ; i>=0; i--){ g[i]=(g[i]-b[i]*g[i+1])/a[i];

}

for(i=0;i<n;i++) { solution[i] = g[i];}

}

void SaveToFile(int knots_N, double* x, const char* filename)

{

FILE *out;

out = fopen(filename, "wt");;

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

{

fprintf(out,"%g\n",x[i]);

}

fclose(out);

}

void SaveToFile_Kqx(int knots_N, double* q, double* x, const char* filename)

{

FILE *out;

out = fopen(filename, "wt"); fprintf(out,"K = [ \n" );

for (int i=0; i < knots_N; i++) { for (int j=0; j < knots_N; j++) {

fprintf(out,"%g ",K[i][j]);

}

fprintf(out," \n");

}

fprintf(out,"];\n" );

fprintf(out,"q = [ \n" );

for (int i=0; i < knots_N; i++) { fprintf(out,"%g\n ",q[i]);

}

fprintf(out,"]; \n");

fprintf(out,"x = [ \n" );

for (int i=0; i < knots_N; i++) { fprintf(out,"%g\n ",x[i]);

}

fprintf(out,"]; \n"); fprintf(out,"sol = inv(K)*q;\n" ); fprintf(out,"u = 1 + x + x.^2;\n");

fprintf(out,"scf(1), plot(x,sol,'+',x,u),\n");

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

2010-03-01

fem3_1.cpp

6

fprintf(out,"xlabel('x'), ylabel('u, y');\n"); fprintf(out,"epsilon= (u-sol)./u");

fclose(out);

}

file:///home/smolar/FEM/fem3_u/fem3_1.cpp

Соседние файлы в папке fem3