Mercurial > hg > kwantix
changeset 11:d0076d9b2ef1
Conclude precomputation revision
author | Jordi Guitérrez Hermoso <jordigh@gmail.com> |
---|---|
date | Tue, 01 Jul 2008 22:10:00 -0500 |
parents | a2613b85f4ae |
children | 6e06eb6ec448 |
files | Makefile include/interpolator.hpp include/linalg.hpp interpolator.cpp main.cpp |
diffstat | 5 files changed, 157 insertions(+), 82 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile +++ b/Makefile @@ -39,4 +39,8 @@ main.o: main.cpp $(HEADERFILES) clean: - rm -f *.o foo \ No newline at end of file + rm -f *.o foo + +cleandata: + rm -f data/*.matrix data/*.map data/*.vector \ + results/*.matrix results/*.map results/*.png results/*.vector \ No newline at end of file
--- a/include/interpolator.hpp +++ b/include/interpolator.hpp @@ -65,11 +65,27 @@ double d2(const point &p, size_t k1, size_t k2) const; //@} + /** @name Precomputation of RBFs + * + * The following functions will precompute upon request all the + * interpolator's RBFs at all points of the domain. This may speed + * up some computations at the expense of increasing memory + * usage. + */ + //@{ + ///Precompute all the function evaluation of the RBFs. + void precompute_at(); + ///Precompute all relevant first derivatives. + void precompute_d() ; + ///Precompute all relevant second derivatives. + void precompute_d2(); + //@} + /** @name Partial redefinitions * * These functions allow for partial redefinition of the BVP as * equired for the additive Schwartz domain decomposition method, - * a nd for other methods. They do not factor a matrix again. + * and for other methods. They do not factor a matrix again. */ //@{ void set_f(const realfunc &f); @@ -81,7 +97,8 @@ /** @name Linear arithmetic operators * * These functions return a new interpolator. They are pointwise - * linear operations. + * linear operations and work by manipulating interpolator + * coefficients. */ //@{ /// Needs two operators on the same domain. @@ -94,36 +111,35 @@ interpolator<RBF> operator/(double a) const; //@} - //debug - mutable map<std::vector<size_t>, matrix> precomp_rbfs; private: - //Once the matrix is defined, this function inverts it. + ///Once the matrix is defined, this function inverts it. void computecoeffs(); - //Perform the actual interpolation. + ///Perform the actual interpolation. void init(shared_ptr<linear_BVP2> bvp); shared_ptr<linear_BVP2> thebvp; - //Number of interior points. + ///Number of interior points. size_t n; - //Number of boundary points. + ///Number of boundary points. size_t m; - //The matrix to invert. + ///The matrix to invert. matrix M; - //Is the interpolator ready for use? + ///Is the interpolator ready for use? bool initted; void not_initted(int line, string file) const; //Exception thrower - //Coefficients of the RBFs + ///Coefficients of the RBFs linalg::vector coeffs; - //The RBFS + ///The RBFS std::vector<RBF> rbfs; - //Their hash + ///Their hash size_t rbfs_hash; + ///An RBF hasher size_t hash_value(const std::vector<RBF>& rbfs_in); /** \short Precomputed RBFs @@ -139,10 +155,17 @@ * the vector represents zeros. Thus, an empty vector represents * evaluation instead of derivatives. */ - + mutable map<std::vector<size_t>, matrix> precomp_rbfs; + + /// Have the RBFs or their derivatives been precomputed? + bool ev_precomp; + bool d1_precomp; + bool d2_precomp; /// Precomputed values using precomp_rbfs - mutable map<std::vector<size_t>, map<point, double> > precomp_values; + mutable map<std::vector<size_t>, map<point, double> > + precomp_values; + /// Invert phis\coeffs and return result vector in a map. map<point, double> precompute_values(const matrix& phis) const; };
--- a/include/linalg.hpp +++ b/include/linalg.hpp @@ -266,7 +266,7 @@ vector operator+(const vector& w) const; ///Vector subtration. vector operator-(const vector& w) const; - ///xDot product. + ///Dot product. double operator*(const vector& w) const; ///Computes vM where v is treated as a row vector. vector operator*(const matrix& M) const;
--- a/interpolator.cpp +++ b/interpolator.cpp @@ -12,9 +12,6 @@ #include <boost/functional/hash.hpp> #include <boost/shared_ptr.hpp> -//debug -#include <iostream> - namespace bvp{ using boost::shared_ptr; @@ -191,8 +188,14 @@ } computecoeffs(); + + ev_precomp = false; + d1_precomp = false; + d2_precomp = false; + + rbfs_hash = hash_value(rbfs); + initted = true; - rbfs_hash = hash_value(rbfs); } template<typename RBF> @@ -234,17 +237,17 @@ } return out; } - + template<typename RBF> - double interpolator<RBF>::at(const point& p) const{ + void interpolator<RBF>::precompute_at(){ if(!initted){ not_initted(__LINE__, __FILE__); } - std::vector<size_t> alpha; //empty vector - - //Have the RBFs been precomputed yet? - if(precomp_rbfs.find(alpha) == precomp_rbfs.end()){ - //No, so precompute the RBFs at all points of the domain + + if(!ev_precomp){ + std::vector<size_t> alpha; //empty vector + + //Precompute the RBFs at all points of the domain matrix phis(n+m,n+m); set<point>::iterator I; size_t i; @@ -262,19 +265,65 @@ precomp_values[alpha] = precompute_values(phis); } - + ev_precomp = true; + } + + template<typename RBF> + double interpolator<RBF>::at(const point& p) const{ + if(!initted){ + not_initted(__LINE__, __FILE__); + } + std::vector<size_t> alpha; //empty vector + //Are we evaluating at a precomputed point in the domain? - if(precomp_values[alpha].find(p) != precomp_values[alpha].end()) + if(ev_precomp and + precomp_values[alpha].find(p) != precomp_values[alpha].end()) return precomp_values[alpha][p]; + //Else, must compute the value double result = 0; for(size_t i = 1; i <= coeffs.size(); i++) result += coeffs(i)*rbfs[i-1].at(p); - - + return result; } + + template<typename RBF> + void interpolator<RBF>::precompute_d() + { + if(!initted){ + not_initted(__LINE__, __FILE__); + } + + //Have the RBFs been precomputed yet? + if(!d1_precomp){ + //No, so precompute the RBFs first derivatives at all points of + //the domain. + for(size_t k = 1; k <= thebvp -> get_domain() -> get_dimension(); + k++){ + std::vector<size_t> alpha(k); alpha[k-1]++; + matrix phis(n+m,n+m); + { + set<point>::iterator I; + size_t i; + for(I = thebvp -> get_domain() -> get_interior().begin(), + i = 1; i <= n; i++, I++) + for(size_t j = 0; j < n+m; j++) + phis(i,j+1) = rbfs[j].d(*I,k); + + for(I = thebvp -> get_domain() -> get_boundary().begin(), + i=n+1; i <= n+m; i++, I++) + for(size_t j = 0; j < n+m; j++) + phis(i,j+1) = rbfs[j].d(*I,k); + } + + precomp_rbfs[alpha] = phis; + precomp_values[alpha] = precompute_values(phis); + } + } + d1_precomp = true; + } template<typename RBF> double interpolator<RBF>::d(const point& p, size_t k) const{ @@ -282,31 +331,10 @@ not_initted(__LINE__, __FILE__); } std::vector<size_t> alpha(k); alpha[k-1]++; - - //Have the RBFs been precomputed yet? - if( precomp_rbfs.find(alpha) == precomp_rbfs.end()){ - //No, so precompute the RBFs at all points of the domain - matrix phis(n+m,n+m); - { - set<point>::iterator I; - size_t i; - for(I = thebvp -> get_domain () -> get_interior().begin(), i = 1; - i <= n; i++, I++) - for(size_t j = 0; j < n+m; j++) - phis(i,j+1) = rbfs[j].d(*I,k); - - for(I = thebvp -> get_domain() -> get_boundary().begin(), i=n+1; - i <= n+m; i++, I++) - for(size_t j = 0; j < n+m; j++) - phis(i,j+1) = rbfs[j].d(*I,k); - } - - precomp_rbfs[alpha] = phis; - precomp_values[alpha] = precompute_values(phis); - } //Are we evaluating at a precomputed point in the domain? - if(precomp_values[alpha].find(p) != precomp_values[alpha].end()) + if(d1_precomp and + precomp_values[alpha].find(p) != precomp_values[alpha].end()) return precomp_values[alpha][p]; //Else, must compute the value @@ -319,34 +347,48 @@ } template<typename RBF> + void interpolator<RBF>::precompute_d2() + { + if(!initted) + not_initted(__LINE__, __FILE__); + if(!d2_precomp){ + size_t dim = thebvp -> get_domain() -> get_dimension(); + //precompute all second derivatives of t + for(size_t k1 = 1; k1 <= dim; k1++){ + for(size_t k2 = k1; k2 <= dim; k2++){ + std::vector<size_t> alpha(k1>k2?k1:k2); alpha[k1-1]++; alpha[k2-1]++; + matrix phis(n+m,n+m); + set<point>::iterator I; + size_t i; + for(I = thebvp -> get_domain () -> get_interior().begin(), i = 1; + i <= n; i++, I++) + for(size_t j = 0; j < n+m; j++) + phis(i,j+1) = rbfs[j].d2(*I,k1,k2); + + for(I = thebvp -> get_domain() -> get_boundary().begin(), i=n+1; + i <= n+m; i++, I++) + for(size_t j = 0; j < n+m; j++) + phis(i,j+1) = rbfs[j].d2(*I,k1,k2); + + precomp_rbfs[alpha] = phis; + precomp_values[alpha] = precompute_values(phis); + + } + } + } + d2_precomp = true; + } + + template<typename RBF> double interpolator<RBF>::d2(const point& p, size_t k1, size_t k2) const{ if(!initted){ not_initted(__LINE__, __FILE__); } std::vector<size_t> alpha(k1>k2?k1:k2); alpha[k1-1]++; alpha[k2-1]++; - - //Have the RBFs been precomputed yet? - if( precomp_rbfs.find(alpha) == precomp_rbfs.end()){ - //No, so precompute the RBFs at all points of the domain - matrix phis(n+m,n+m); - set<point>::iterator I; - size_t i; - for(I = thebvp -> get_domain () -> get_interior().begin(), i = 1; - i <= n; i++, I++) - for(size_t j = 0; j < n+m; j++) - phis(i,j+1) = rbfs[j].d2(*I,k1,k2); - - for(I = thebvp -> get_domain() -> get_boundary().begin(), i=n+1; - i <= n+m; i++, I++) - for(size_t j = 0; j < n+m; j++) - phis(i,j+1) = rbfs[j].d2(*I,k1,k2); - - precomp_rbfs[alpha] = phis; - precomp_values[alpha] = precompute_values(phis); - } //Are we evaluating at a precomputed point in the domain? - if(precomp_values[alpha].find(p) != precomp_values[alpha].end()) + if(d2_precomp and + precomp_values[alpha].find(p) != precomp_values[alpha].end()) return precomp_values[alpha][p]; //Else, must compute the value
--- a/main.cpp +++ b/main.cpp @@ -163,11 +163,10 @@ v1, v0(v_bvp_init), h1, h0(Omega, h_init); - //FIXME: put proper precomp function here. - point p = *(Omega -> get_interior().begin()); - u0(p); v0(p); h0(p); - u0.d(p,1); v0.d(p,1); h0.d(p,1); - u0.d(p,2); v0.d(p,2); h0.d(p,2); + //Precompute some RBFs + u0.precompute_at(); v0.precompute_at(), h0.precompute_at(); + u0.precompute_d(); v0.precompute_d(), h0.precompute_d(); + u1 = u0; v1 = v0; h1 = h0; @@ -186,7 +185,7 @@ //main loop - size_t maxiter = 10; + size_t maxiter = 1000; for(size_t i = 1; i <= maxiter; i++){ cout << "Now on iteration #" << i << endl; if(i % 1 == 0){ @@ -203,6 +202,7 @@ k1[0].set_f(f_u); k1[1].set_f(f_v); k1[2].set_f(f_h); + cout << "k1 done!" << endl; bdry_iter(k1[0],k1[1],Omega); @@ -217,6 +217,8 @@ bdry_iter(k2[0],k2[1],Omega); + cout << "k2 done!" << endl; + //k3 f_u.set_interps(u0+(k2[0]/2), v0+(k2[1]/2), h0+(k2[2]/2)); f_v.set_interps(u0+(k2[0]/2), v0+(k2[1]/2), h0+(k2[2]/2)); @@ -227,6 +229,8 @@ k3[2].set_f(f_h); bdry_iter(k3[0],k3[1],Omega); + + cout << "k3 done!" << endl; //k4 f_u.set_interps(u0+k3[0], v0+k3[1], h0+k3[2]); @@ -238,6 +242,8 @@ k4[2].set_f(f_h); bdry_iter(k4[0],k4[1],Omega); + + cout << "k4 done!" << endl; //Grand finale u1.set_f(u0 + (k1[0] + 2*k2[0] + 2*k3[0] + k4[0])/6);