まずmain()ですね.
#include <iostream>
#include "heat.hpp"
int main(int argc, const char * argv[]) {
int N=50,nt=0;
double dt=0.1;
Heat Solver(N,dt);
Solver.vtk(nt);
double errmax=1e-5,err;
while (errmax<(err=Solver.Step(nt++)))
{
Solver.vtk(nt);
std::cout << "nt= " << nt << " err= " << err << std::endl;
}
return 0;
}Heatクラスの仕様は上で完全に決定しているので,あとは実装するだけですわ.
#include <sstream>
#include <boost/filesystem.hpp>
#include "libSPARSE.hpp"
#include "myArray.hpp"
class Heat
{
double xmax=1.;
double u_x0=0.,u_x1=0.,u_y0=1.,u_y1=0.; //境界条件
double dx,dt,cfl;
myArray<double> mySOL;
SPARSE::Coef myMAT;
public:
Heat(int N,double dt):mySOL(N-1,N-1)
{
dx=xmax/N;
cfl=dt/dx/dx;
for(int i=0; i<mySOL.size(0);i++)
for(int j=0; j<mySOL.size(1);j++)
{
double x=(i+1)*dx,y=(j+1)*dx;
mySOL(i,j)=(1+y-2*y*y)*(1-4*(x-0.5)*(x-0.5));
}
//行列サイズは mySOL.size()xmySOL.size()になる
for(int k=0;k<mySOL.size();k++) myMAT.New(k,1.0+4*cfl);//対角成分は 1+4*cfl
for(int k=0;k<mySOL.size();k++) myMAT[k][myMAT.Dimension()]=0.;
for(int k=0;k<mySOL.size();k++)//他の要素を入れる
{
int i=mySOL.index(0,k); //k番目の未知数のi
int j=mySOL.index(1,k); //k番目の未知数のj
if (i==0) myMAT[k][myMAT.Dimension()]+=cfl*u_x0;
else myMAT[k][mySOL.serial(i-1,j)]=-cfl;
if (i==mySOL.size(0)-1) myMAT[k][myMAT.Dimension()]+=cfl*u_x1;
else myMAT[k][mySOL.serial(i+1,j)]=-cfl;
if (j==0) myMAT[k][myMAT.Dimension()]+=cfl*u_y0;
else myMAT[k][mySOL.serial(i,j-1)]=-cfl;
if (j==mySOL.size(1)-1) myMAT[k][myMAT.Dimension()]+=cfl*u_y1;
else myMAT[k][mySOL.serial(i,j+1)]=-cfl;
}
boost::filesystem::path folder=getenv("HOME");
boost::filesystem::current_path(folder/"tes_test");
}
double Step(int nt)
{
auto thisMAT=myMAT;
for(int k=0;k<mySOL.size();k++)
thisMAT[k][thisMAT.Dimension()]+=mySOL[k];
thisMAT.MakeIndex();
thisMAT.EraseUp();
thisMAT.EraseDown();
thisMAT.ClearIndex();
double err=0.0;
for(int k=0;k<mySOL.size();k++)
{
err=std::max(std::abs(thisMAT[k][thisMAT.Dimension()]-mySOL[k]),err);
mySOL[k]=thisMAT[k][thisMAT.Dimension()];
}
return err;
}
void vtk(int nt)
{
std::ostringstream oss;
oss << "vtk_" << std::setfill('0') << std::right << std::setw(6) << nt << ".vtk";
std::ofstream vout(oss.str());
vout << "# vtk DataFile Version 2.0" << std::endl << "ひゃっほう" << std::endl << "ASCII" << std::endl;
//Geometry指定
vout << "DATASET STRUCTURED_POINTS" << std::endl;
vout << "DIMENSIONS " << mySOL.size(0)+2 << " " << mySOL.size(1)+2 << " " << 1 << std::endl;
vout << "ORIGIN 0 0 0" << std::endl;
vout << "SPACING " << 1.0/(mySOL.size(0)+1) << " " << 1.0/(mySOL.size(1)+1) << " " << 1.0 << std::endl;
//DataSet指定
vout << "POINT_DATA " << (mySOL.size(0)+2)*(mySOL.size(1)+2) << std::endl;
vout << "SCALARS U double" << std::endl;
vout << "LOOKUP_TABLE default" << std::endl;
for(int j=0;j<mySOL.size(1)+2;j++)
for(int i=0;i<mySOL.size(0)+2;i++)
{
if (i==0) vout << u_x0 <<std::endl;
else if (i==mySOL.size(0)+1) vout << u_x1 <<std::endl;
else
{
if (j==0) vout << u_y0 <<std::endl;
else if (j==mySOL.size(1)+1) vout << u_y1 <<std::endl;
else vout << mySOL(i-1,j-1) <<std::endl;
}
}
}
};
#endif /* heat_hpp */新しい文法要素はありませんね.念のためmyArray.hppも示しておきます:
#ifndef myArray_hpp
#define myArray_hpp
#include <iostream>
#include <vector>
template <class T> class myArray
{
std::vector<int> _sizes;
std::vector<int> _upto;
std::vector<T> _data;
public:
T* data() {return _data.data();}
const int size(){return _upto.back();}
const int size(const int index){return _sizes.at(index);}
T& operator[](const int k){return _data[k];}
typename std::vector<T>::iterator begin(){return _data.begin();}
typename std::vector<T>::iterator end(){return _data.end();}
const int index(const int dim,const int k)
{
int _index=k;
for(int i=0;i<dim;i++) _index/=_sizes[i];
if (dim==_sizes.size()-1) return _index;
return _index%_sizes[dim];
}
myArray(const int n0,const int n1)
{
_sizes.resize(2); //2次元配列である
_upto.resize(2);
_sizes[0]=n0; _sizes[1]=n1;_upto[0]=n0; _upto[1]=_upto[0]*n1;
_data.resize(size());
}
const int serial(const int i0,const int i1){return i0+_upto[0]*i1;}
T& operator()(const int i0,const int i1){return _data[serial(i0,i1)];}
myArray(const int n0,const int n1,const int n2)
{
_sizes.resize(3); //3次元配列である
_upto.resize(3);
_sizes[0]=n0; _sizes[1]=n1; _sizes[2]=n2;_upto[0]=n0; _upto[1]=_upto[0]*n1; _upto[2]=_upto[1]*n2;
_data.resize(size());
}
const int serial(const int i0,const int i1,const int i2){return i0+_upto[0]*i1+_upto[1]*i2;}
T& operator()(const int i0,const int i1,const int i2){return _data[serial(i0,i1,i2)];}
};
#endif /* myArray_hpp */以上