-
Notifications
You must be signed in to change notification settings - Fork 0
/
BvpOde.cpp
101 lines (94 loc) · 3 KB
/
BvpOde.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
#include <string>
#include<fstream>
#include<cassert>
#include<iostream>
#include"Master.hpp"
using namespace std;
BvpOde::BvpOde(SecondOrderOde* pOde, BoundaryConditions* pBcs,int numNodes)
{
mpOde = pOde;
mpBconds = pBcs;
mNumNodes = numNodes;
mpGrid = new FiniteDifferenceGrid (mNumNodes, pOde->mXmin, pOde->mXmax);
mpRhsVec = new Vector(mNumNodes);
mpLhsMat = new Matrix(mNumNodes, mNumNodes);
mpLinearSystem = NULL;
}
BvpOde::~BvpOde()
{
//deletes memory allocated by constructor
delete mpRhsVec;
delete mpLhsMat;
delete mpGrid;
delete mpLinearSystem;
}
void BvpOde::Solve()
{
PopulateMatrix();
PopulateVector();
ApplyBoundaryConditions();
mpLinearSystem = new LinearSystem (*mpLhsMat, *mpRhsVec);
mpLinearSystem->Mumps_input_gen();
}
void BvpOde::PopulateMatrix()
{
for (int i=1; i < mNumNodes-1; i++)
{
//xm, x and xp are x(i-1) ,x(i) and x(i+1)
double xm = mpGrid->mNodes[i-1].coordinate;
double x = mpGrid->mNodes[i].coordinate;
double xp = mpGrid->mNodes[i+1].coordinate;
double alpha = 2.0/(xp-xm)/(x-xm);
double beta = -2.0/(xp-x)/(x-xm);
double gamma = 2.0/(xp-xm)/(xp-x);
(*mpLhsMat)(i+1,i) = (mpOde->mCoeffofUxx)*alpha - (mpOde->mCoeffofUx)/(xp-xm);
(*mpLhsMat)(i+1,i+1) = (mpOde->mCoeffofUxx)*beta + (mpOde->mCoeffofU);
(*mpLhsMat)(i+1,i+2) = (mpOde->mCoeffofUxx)*gamma + (mpOde->mCoeffofUx)/(xp-xm);
}
}
void BvpOde::PopulateVector()
{
for (int i=0; i < mNumNodes-1; i++)
{
double x = mpGrid->mNodes[i].coordinate;
(*mpRhsVec)(i+1) = mpOde->mpRhsFunc(x);
}
}
void BvpOde::ApplyBoundaryConditions()
{
bool left_bc_applied = false;
bool right_bc_applied = false;
if (mpBconds->mLhsBcIsDirichlet)
{
(*mpLhsMat)(1,1) = 1.0;
(*mpRhsVec)(1) = mpBconds->mLhsBcValue;
left_bc_applied = true;
}
if (mpBconds->mRhsBcIsDirichlet)
{
(*mpLhsMat)(mNumNodes,mNumNodes) = 1.0;
(*mpRhsVec)(mNumNodes) = mpBconds->mRhsBcValue;
right_bc_applied = true;
}
if (mpBconds->mLhsBcIsNeumann)
{
assert(left_bc_applied == false);
double h = mpGrid->mNodes[1].coordinate - mpGrid->mNodes[0].coordinate;
(*mpLhsMat)(1,1) = -1.0/h;
(*mpLhsMat)(1,2) = 1.0/h;
(*mpRhsVec)(1) = mpBconds->mLhsBcValue;
left_bc_applied = true;
}
if (mpBconds->mRhsBcIsNeumann)
{
assert(right_bc_applied == false);
double h = mpGrid->mNodes[mNumNodes-1].coordinate - mpGrid->mNodes[mNumNodes-2].coordinate;
(*mpLhsMat)(mNumNodes,mNumNodes-1) = -1.0/h;
(*mpLhsMat)(mNumNodes,mNumNodes) = 1.0/h;
(*mpRhsVec)(mNumNodes) = mpBconds->mRhsBcValue;
right_bc_applied = true;
}
//Check that boundary conditions have been applied on both boundaries
assert(right_bc_applied);
assert(left_bc_applied);
}