KM2016 / Loaded_rod / fem3_1
.pdf2010-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