Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
8
Добавлен:
14.03.2016
Размер:
10.94 Кб
Скачать
// Приложение к разделу 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"); // Сравнение с точным аналитическим решением
  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];  } 
  }
 }
 
}

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) );
       }
     }
     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] не используется
//   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");
	fprintf(out,"xlabel('x'), ylabel('u,  y');\n");
	fprintf(out,"epsilon= (u-sol)./u");
  fclose(out);
}
Соседние файлы в папке Приложение к разделу 3 Однородный стержень