Добавил:
Upload
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
//Приложение к разделу 3 Однородный стержень
// fem3.h
/*
#include <ctype.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int knots_N, test, result;
double *q, *x, *solution, *up, *down, *diag ;
double h, x_max;
double K[500][500];
void q_i(void);
int output(int);
void K_ij(void);
double quad_m(double x_1,double x_2);
double quad_p(double x_1,double x_2);
void progon(int, double down[], double diag[], double up[], double q[]);
int i_max(int N, int p, double V[]);
*/
//fem3.cpp
#include "fem3.h"
static double fun_q(double x) { // правая часть дифференциального уравнения
//return (-6*x);
return 3.14159*3.14159*sin(3.14159*x);
// return x*x*x*x;
}
int main(int argc,char *argv[]) {
x_max = 1; // задаём длину стержня
knots_N = 7; // задаём число узлов, включая узлы на границах
int N; // при нулевых граничных условиях следует решать задачу только для внутренних узлов
N = knots_N-2;
x = new double[knots_N]; // выделение памяти для координат узлов
h = x_max/(knots_N-1);
solution = new double[N]; // выделение памяти для решения
K_ij(); // матрица
q_i(); // правая часть матричного уравнения
progon(N, down, diag, up, q); // решение матричного уравнения методом прогонки
test = 1;
result = output(test);
return result;
}
//Вывод решения в файл
int output(int test) {
FILE *out;
double u_i, x_i, sol_i, q_i;
out = fopen("results.dat", "wt");
if (test == 1) {
fprintf(out,"\n x u(x) solution\n");
x_i = 0; u_i = 0; sol_i = 0;
fprintf(out,"%-12.3g%-12.3g%-12.3g\n",x_i, u_i, sol_i);
for (int i=0;i<knots_N-2;i++) {
x_i = x[i]+h;
//u_i = pow(x_i,3.0) - x_i;
u_i = sin(3.14159*x_i);
sol_i = solution[i];
fprintf(out,"%-12.3g%-12.7g%-12.7g\n",x_i, u_i, sol_i);
}
x_i = 1; u_i = 0; sol_i = 0;
fprintf(out,"%-12.3g%-12.3g%-12.3g\n",x_i, u_i, sol_i);
result = 1;
}
else if (test == 0) {
fprintf(out,"\n x q(x) solution\n");
x_i = 0; sol_i = 0; q_i = fun_q(x_i);
fprintf(out,"%-12.3g%-12.3g%-12.7g\n",x_i, q_i, sol_i);
for (int i=0;i<knots_N-2;i++) {
x_i = x[i]+h;
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);
}
x_i = 1; sol_i = 0;
fprintf(out,"%-12.3g%-12.3g%-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-2; i++) {
for (int j=0; j < knots_N-2;j++) {
if (i==j) { 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]; }
}
}
}
// Вычисление вектора правой части матричного уравнения
void q_i(void) {
q = new double[knots_N]; // выделение памяти для правой части матричного уравнения
for (int i = 0; i < knots_N; i++) {
x[i] = h*i;
}
for (int i = 0; i < knots_N-2; i++) {
q[i] = quad_m(x[i],x[i+1]) + quad_p(x[i+1],x[i+2]);
}
}
// Интегрирование назад из i - того узла
double quad_m(double x_1,double x_2) {
double s = 0;
double h, dh, x_i, x_k,x_kp;
h = (x_2 - x_1);
dh = h/5;
x_i = x_2;
for (int k= 0; k<5; k++) {
x_k = x_1 + dh*k;
x_kp = x_k + dh;
s = s + 0.5*dh*( (1/h*(x_k - x_i + h))*fun_q(x_k) + (1/h*(x_kp - x_i + h))*fun_q(x_kp) );
}
return s;
}
// Интегрирование вперёд из i - того узла
double quad_p(double x_1,double x_2) {
double h, dh, x_i, x_k, x_kp, s ;
h = (x_2 - x_1);
dh = h/5;
x_i = x_1;
s = 0;
for (int k= 0; k<5; k++) {
x_k = x_1 + dh*k;
x_kp = x_k + dh;
s = s + 0.5*dh*((-1/h*(x_k - x_i - h))*fun_q(x_k) + (-1/h*(x_kp - x_i - h))*fun_q(x_kp));
}
return s;
}
void progon(int n,double c[],double a[],double b[],double g[])
// Решение линейной трёхдиагональной матрицы методом прогонки
// int n - порядок марицы
// double c[] - входной вектор длины n - диагональные матричные элементы под главной диагональю
// c[0] не используется
// 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];
}
solution = g;
}
// Результаты вычислений
/*
x u(x) solution
0 0 0
0.167 0.4999996 0.5004563
0.333 0.866025 0.8668159
0.5 1 1.000913
0.667 0.8660263 0.8668164
0.833 0.5000019 0.5004569
1 0 0
*/