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

KM2016 / fem2 / FEM2 / fem3 / fem3

.cpp
Скачиваний:
9
Добавлен:
14.03.2016
Размер:
6.58 Кб
Скачать
//Приложение к разделу 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         
*/
Соседние файлы в папке fem3