KM2016 / Loaded_rod / fem3
.pdf//Приложение к разделу 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 |
|
*/ |
|
|
|