-
Notifications
You must be signed in to change notification settings - Fork 2
/
fem1D.cpp
136 lines (129 loc) · 5.06 KB
/
fem1D.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#define _USE_MATH_DEFINES
#include <math.h>
#include<deal.II\lac\vector.h>
#include<boost\archive\binary_oarchive.hpp>
#include<deal.II\lac\sparse_matrix.h>
#include <deal.II/lac/solver_gmres.h>
#include <deal.II/lac/identity_matrix.h>
/** namespace mySolverClass contains the parameter to solve the BC value probelm
* \f$ -\epsilon f''(x)+\epsilon \pi^2 f(x) +f'(x)=\sin \pi x \f$
* This equation appears when solving practice5, and has analytical solution.
* For more info, see <a href="../PDE_Numerical_Five.pdf">PDE_Numerical_Five.pdf</a>
*/
namespace mySolverClass{
const int library_offset = 1;
double epsilon = 0.1;
int n = 10;
const int version = 1;
int iteratitionTime = 1000;
double errorLimit = 1.e-5;
typedef dealii::Vector<double> myVector;
typedef dealii::SparseMatrix<double> myMatrix;
typedef dealii::SparsityPattern mySparsityPattern;
typedef dealii::SolverGMRES<> mySolver;
typedef dealii::SolverControl mySolverControl;
}
int main(int argc,char** argv) {
//step 0: given x_0,x_1,...x_n
if (argc > 1) {//second argument is epsilon
mySolverClass::epsilon = atof(argv[1]);
}
if (argc > 2) {//third argument, refinement
mySolverClass::n = atoi(argv[2]);
}
if (argc > 3) {
mySolverClass::iteratitionTime = atoi(argv[3]);
}
double* x= new double[mySolverClass::n+1];
for (int i = 0; i <= (mySolverClass::n/2); i++) {
x[i] = i*(1.0-5*mySolverClass::epsilon) / (mySolverClass::n / 2);
}
for (int i = (mySolverClass::n / 2)+1; i <= (mySolverClass::n); i++) {
x[i] = x[(mySolverClass::n / 2)]+ 5*mySolverClass::epsilon*(i- (mySolverClass::n / 2))*
1.0 / (mySolverClass::n/2);
}
//first we decleare RHS
double* b_array = new double[mySolverClass::n];
for (int i = 1; i < mySolverClass::n; i++) {
b_array[i]=((x[i]-x[i+1])*std::sin(M_PI*x[i-1])+(x[i+1]-x[i-1])*std::sin(M_PI*x[i])
+(x[i-1]-x[i])*std::sin(M_PI*x[i+1]))/(x[i-1]-x[i])/(x[i]-x[i+1])/pow(M_PI,2);
}
mySolverClass::myVector b(b_array+1,b_array+mySolverClass::n);
//print the right hand side info
std::cout << "b size:" << b.size() << std::endl;
//b.print(std::cout,3,false);
//then we initialize the sparse matrix
std::vector<std::map<int, double>> vector_for_sparse_matrix;
std::vector<std::vector<unsigned int> > column_indices(mySolverClass::n-1);
for (int j = 1; j < mySolverClass::n; j++) {
std::map<int, double> tmp_map;
tmp_map.insert(std::pair<int, double>(j - mySolverClass::library_offset, mySolverClass::epsilon*(1 / (x[j] - x[j - 1]) + 1 / (x[j + 1] - x[j]) +
pow(M_PI, 2) / 3 * (x[j + 1] - x[j - 1])
)
));
column_indices[j - mySolverClass::library_offset].push_back(j - mySolverClass::library_offset);
if (j < mySolverClass::n - 1) {
tmp_map.insert(std::pair<int, double>(j + 1 - mySolverClass::library_offset, mySolverClass::epsilon*(-1 / (x[j + 1] - x[j]) +
pow(M_PI, 2) / 6 * (x[j + 1] - x[j])
) + 0.5
));
column_indices[j - mySolverClass::library_offset].push_back(j+1 - mySolverClass::library_offset);
}
if (j > 1) {
tmp_map.insert(std::pair<int, double>(j - 1 - mySolverClass::library_offset, mySolverClass::epsilon*(-1 / (x[j] - x[j - 1]) +
pow(M_PI, 2) / 6 * (x[j] - x[j - 1])
) - 0.5
));
column_indices[j - mySolverClass::library_offset].push_back(j- 1 - mySolverClass::library_offset);
}
vector_for_sparse_matrix.push_back(tmp_map);
}
mySolverClass::myMatrix* A = new mySolverClass::myMatrix;
mySolverClass::mySparsityPattern As = mySolverClass::mySparsityPattern();
As.copy_from(mySolverClass::n - 1, mySolverClass::n - 1, column_indices.begin(), column_indices.end());//create entry
A->reinit(As);//tri-diagnal;
A->copy_from(vector_for_sparse_matrix.begin(), vector_for_sparse_matrix.end());//add value
//print the matrix info
std::cout << "matrix info\n";
std::cout << "num of rows: " << A->m() << std::endl;
std::cout << "num of columns: " << A->n() << std::endl;
std::cout << "non-zero element counts: " << A->n_nonzero_elements() << std::endl;
//A->print(std::cout);
//save data
//std::ofstream ofs("matrixData.dat");
//boost::archive::binary_oarchive oa(ofs);
//b.save(oa, mySolverClass::version);
//std::cout << "b is serialized."<< std::endl;
//initialize the solution vector
mySolverClass::myVector y(mySolverClass::n-1);
//initialize the solver class
mySolverClass::mySolverControl* control = new mySolverClass::mySolverControl(
mySolverClass::iteratitionTime,mySolverClass::errorLimit);
//mySolverClass::myAdditionalData solver_param = mySolverClass::myAdditionalData();
mySolverClass::mySolver solver(*control);
solver.solve(*A,y,b,dealii::IdentityMatrix(y.size()));
//output the solution
//save data
std::ofstream ofs("vector.csv");
ofs.precision(4);
for (int i = 0; i < y.size(); i++) {
ofs << x[i+1] << ',' << y[i] << '\n';
}
//boost::archive::binary_oarchive oa(ofs);
//y.print(ofs,4,false,false);
ofs.close();
//std::cout << "b is serialized."<< std::endl;
std::cout << "The solution is saved to vector.csv\n";
//y.print(std::cout);
delete[] x;
delete[] b_array;
delete A;
delete control;
//Matrix
//SolverGMRES
return 0;
}