Mercurial > hg > kwantix
changeset 17:72412107029b
On the final stretch, implementing the interface in set_bdry_conds
author | Jordi Gutiérrez Hermoso <jordigh@gmail.com> |
---|---|
date | Tue, 26 Aug 2008 10:48:19 -0500 |
parents | 29a7b95c2805 |
children | 382e3b8e3f88 |
files | include/interpolator.hpp include/linalg.hpp interpolator.cpp main.cpp |
diffstat | 4 files changed, 161 insertions(+), 122 deletions(-) [+] |
line wrap: on
line diff
--- a/include/interpolator.hpp +++ b/include/interpolator.hpp @@ -24,7 +24,11 @@ using boost::shared_ptr; class interp_values; + class normals; + class bdry_values; + //FIXME: Break this up into an ansatz class and an interpolator + //class. /*! \brief An interpolator \f$ \displaystyle u(x) = \sum_{\xi \in * \Xi} \lambda_\xi \varphi_\xi(x) \f$, where the \f$ \varphi_\xi * \f$ are RBFs. @@ -151,6 +155,15 @@ void set_g(const map<point, double>& g); //@} + /** @name Reinterpolate again + * + * As above group of functions, but for purely interpolating + * interpolators + */ + //@{ + void set_bdry_values(const bdry_values& b_new); + //@} + /** @name Linear arithmetic operators * * These functions return a new interpolator. They are pointwise @@ -167,6 +180,11 @@ /// Returns a scaled interpolator. interpolator<RBF> operator/(double a) const; //@} + + /** \brief Provide a unit normals object associated to the + * interpolator. + */ + normals get_normals() const; private: ///Once the matrix is defined, this function inverts it. @@ -260,24 +278,30 @@ interp_values operator*(const double a) const; interp_values operator/(const double a) const; //@} - private: - + + protected: /// No construction! interp_values(); /// Interpolator creates interp_values with this - interp_values(const linalg::vector& v_in, size_t rbfs_hash_in) - : v(v_in), rbfs_hash(rbfs_hash_in) {}; + interp_values(const linalg::vector& v_in, size_t rbfs_hash_in, + size_t n_in) + : v(v_in), rbfs_hash(rbfs_hash_in), n(n_in) {}; + ///Exception builder + badArgument different_rbfs(int line, string file) const; + + protected: ///Interpolated values go here linalg::vector v; ///Two interp_values can be added iff these two values matches. size_t rbfs_hash; - ///Exception builder - badArgument different_rbfs(int line, string file) const; + ///Number of interior points + size_t n; template<typename RBF> friend class interpolator; /*! \name Arithmetic operators + * * For comfortable syntax. */ //@{ @@ -287,8 +311,15 @@ friend interp_values operator/(double a, const interp_values& v); //@} }; - - + + /// For referring to values purely on the boundary of an interpolator. + class bdry_values : public interp_values{ + public: + ///Initialise the boundary values with interp_values + bdry_values(const interp_values& v_in); + private: + bdry_values(); + }; /// For comfortable syntax template <typename RBF> @@ -296,6 +327,37 @@ { return u*a; } + + /// A unit normals class associated to an interpolator + class normals{ + public: + /** \brief Return the kth coordinate of all normals along the + * boundary as interp values + */ + interp_values operator()(size_t k) const; + + /*! \name comparisons + * + * Normals are the same if they correspond to the same domain + */ + //@{ + bool operator!=(const normals& M) const; + bool operator==(const normals& M) const; + //@} + private: + template<typename RBF> friend class interpolator; + ///Only constructor available + normals(size_t rbfs_hash_in, map<point, linalg::vector> + normals_in); + ///Exception builder + badArgument not_initted() const; + + ///A hash used to return inter_values objects + size_t rbfs_hash; + + ///Store normals in a matrix + linalg::matrix N; + }; /*! \name Arithmetic operators * For comfortable syntax. @@ -306,6 +368,7 @@ interp_values operator*(double a, const interp_values& v); interp_values operator/(double a, const interp_values& v); //@} + } #endif
--- a/include/linalg.hpp +++ b/include/linalg.hpp @@ -396,7 +396,8 @@ namespace linalg{ //Non-member functions. - /// I/O + /*! @name I/O + */ //@{ ///Stream insertion operator std::ostream& operator<<(std::ostream& os, const vector &v); @@ -408,7 +409,10 @@ matrix operator>>(std::istream& is, matrix& v); //@} - ///Some arithmetic functions for comfortable syntax. + /*! @name Arithmetic + * + * Some arithmetic functions for comfortable syntax. + */ //@{ /// Scale a vector.
--- a/interpolator.cpp +++ b/interpolator.cpp @@ -441,7 +441,7 @@ throw not_precomputed(__LINE__, __FILE__); std::vector<size_t> alpha; - return interp_values(precomp_values_vec[alpha],rbfs_hash); + return interp_values(precomp_values_vec[alpha],rbfs_hash,n); } template<typename RBF> @@ -451,7 +451,7 @@ throw not_precomputed(__LINE__, __FILE__); std::vector<size_t> alpha(k); alpha[k-1]++; - return interp_values(precomp_values_vec[alpha],rbfs_hash); + return interp_values(precomp_values_vec[alpha],rbfs_hash,n); } template<typename RBF> @@ -461,7 +461,7 @@ throw not_precomputed(__LINE__, __FILE__); std::vector<size_t> alpha(k1>k2?k1:k2); alpha[k1-1]++; alpha[k2-1]++; - return interp_values(precomp_values_vec[alpha],rbfs_hash); + return interp_values(precomp_values_vec[alpha],rbfs_hash,n); } //***************** linear operations *************************** @@ -519,6 +519,16 @@ u.coeffs = (this -> coeffs)*(1/a); return u; } + + template<typename RBF> + normals interpolator<RBF>::get_normals() const{ + if(!initted){ + throw badArgument("Interpolator not initialised, so there are " + "no normals!",__FILE__,__LINE__); + } + return normals(rbfs_hash, thebvp -> get_domain() -> + get_normals()); + } //******************* data manipulation ************************** @@ -562,6 +572,30 @@ } template<typename RBF> + void interpolator<RBF>::set_bdry_values(const bdry_values& b_new){ + if(!initted){ + throw not_initted(__LINE__, __FILE__); + } + std::vector<size_t> alpha; //empty, corresponds to evaluation + if(precomp_values_vec.find(alpha) == precomp_values_vec.end()) + at(); + linalg::vector rhs = precomp_values_vec[alpha]; + slice s1(1,n), s2(n+1,n+m); + rhs(s2) = b_new.v; + coeffs = precomp_rbfs[alpha].inv(rhs); + //FIXME: Don't repeat this code + { + typename + map<std::vector<size_t>, matrix>::const_iterator I; + for(I = precomp_rbfs.begin(); I != precomp_rbfs.end(); I++) + precomp_values_vec[I -> first] = (I -> second)*coeffs; + + //Pointwise map evaluations we will not compute again. + precomp_values.clear(); + } + } + + template<typename RBF> error_handling::badArgument interpolator<RBF>::not_initted(int line, string file) const { @@ -576,7 +610,6 @@ template<typename RBF> void interpolator<RBF>::computecoeffs() { - using namespace std; linalg::vector rhs(n+m); //Compute the RBF coefficients @@ -598,7 +631,7 @@ //Precompute the values for the derivatives and evaluations that //have already been computed. - { + { typename map<std::vector<size_t>, matrix>::const_iterator I; for(I = precomp_rbfs.begin(); I != precomp_rbfs.end(); I++){ @@ -645,7 +678,7 @@ if(rbfs_hash != w.rbfs_hash) throw different_rbfs(__LINE__, __FILE__); - return interp_values(v + w.v,rbfs_hash); + return interp_values(v + w.v,rbfs_hash,n); } interp_values @@ -654,7 +687,7 @@ if(rbfs_hash != w.rbfs_hash) throw different_rbfs(__LINE__, __FILE__); - return interp_values(v - w.v,rbfs_hash); + return interp_values(v - w.v,rbfs_hash,n); } interp_values @@ -662,7 +695,7 @@ { if(rbfs_hash != w.rbfs_hash) throw different_rbfs(__LINE__, __FILE__); - return interp_values(v * w.v,rbfs_hash); + return interp_values(v * w.v,rbfs_hash,n); } interp_values @@ -671,33 +704,41 @@ if(rbfs_hash != w.rbfs_hash) throw different_rbfs(__LINE__, __FILE__); - return interp_values(v / w.v,rbfs_hash); + return interp_values(v / w.v,rbfs_hash,n); } interp_values interp_values::operator+(const double a) const { vector w(v.size(),a); - return interp_values(v+w,rbfs_hash); + return interp_values(v+w,rbfs_hash,n); } interp_values interp_values::operator-(const double a) const { vector w(v.size(),a); - return interp_values(v-w, rbfs_hash); + return interp_values(v-w, rbfs_hash,n); } interp_values interp_values::operator*(const double a) const { - return interp_values(v*a,rbfs_hash); + return interp_values(v*a,rbfs_hash,n); } interp_values interp_values::operator/(const double a) const { - return interp_values(v/a, rbfs_hash); + return interp_values(v/a, rbfs_hash,n); + } + + //*************** bdry_vals stuff ************************************ + + bdry_values::bdry_values(const interp_values& v_in) : interp_values(v_in){ + //Lower part of the vector contains the boundary + linalg::slice s(n+1,v.size()); + v = v(s); } //*************** Non-member global friend functions ****************** @@ -710,7 +751,7 @@ interp_values operator-(double a, const interp_values& v) { linalg::vector w(v.v.size(),a); - return interp_values(w-v.v, v.rbfs_hash); + return interp_values(w-v.v, v.rbfs_hash,v.n); } interp_values operator*(double a, const interp_values& v) @@ -721,7 +762,7 @@ interp_values operator/(double a, const interp_values& v) { linalg::vector w(v.v.size(),a); - return interp_values(w/v.v, v.rbfs_hash); + return interp_values(w/v.v, v.rbfs_hash,v.n); } //Instantiations
--- a/main.cpp +++ b/main.cpp @@ -82,32 +82,6 @@ bvp::interp_values at() const; }; -//FIXME: This iteration must work on interpolators without boundary -class iter_neumann : public bdry_diff_op{ -public: - //If this is u's, set 1, for v, set 2. - iter_neumann(size_t u_or_v_in); - double at(const realfunc &f, const point &p, const vector &n) const; -private: - size_t u_or_v; - double at(const realfunc &f, const point &p) const {return f(p);}; -}; - -template<typename RBF> -class Gu_or_v : public realfunc{ -public: - //specify the OTHER, whether u or v. - Gu_or_v(size_t u_or_v_in, - const shared_ptr<domain> Omega_in) : u_or_v(u_or_v_in), - Omega(Omega_in) {}; - double at(const point& p) const; - void set_other(const interpolator<RBF>& other_in){other = other_in;}; -private: - size_t u_or_v; - const shared_ptr<domain> Omega; - interpolator<RBF> other; -}; - class zero_func : public realfunc{ public: double at(const point& p) const{p.size(); return 0;}; @@ -121,8 +95,7 @@ size_t n, string which_interp); template<typename RBF> -void set_bdry_conds(interpolator<RBF> &u, interpolator<RBF> &v, - const boost::shared_ptr<domain> Omega); +void set_bdry_conds(interpolator<RBF> &u, interpolator<RBF> &v); //********************** Main ****************************************** @@ -141,13 +114,13 @@ "data/circ_nrml.matrix")); shared_ptr<Id_op> I(new Id_op); - shared_ptr<iter_neumann> - u_bdry_op(new iter_neumann(1)), - v_bdry_op(new iter_neumann(2)); + shared_ptr<dirichlet_op> D(new dirichlet_op); zero_func Z; + //FIXME: Turns this into a purely interpolating interpolator, + //without a BVP. shared_ptr<linear_BVP2> - u_bvp_init(new linear_BVP2(Omega, I, u_bdry_op, Z, Z)), - v_bvp_init(new linear_BVP2(Omega, I, v_bdry_op, Z, Z)); + u_bvp_init(new linear_BVP2(Omega, I, D, Z, Z)), + v_bvp_init(new linear_BVP2(Omega, I, D, Z, Z)); double dt = 1e-2; @@ -185,7 +158,7 @@ f_v.set_dt(dt); f_h.set_dt(dt); - //main loop + //main loop, timestepping with RK4. size_t maxiter = 1000; for(size_t i = 1; i <= maxiter; i++){ cout << "Now on iteration #" << i << endl; @@ -202,14 +175,14 @@ cout << "k1 done!" << endl; - set_bdry_conds(k1[0],k1[1],Omega); + set_bdry_conds(k1[0],k1[1]); //k2 f_u.set_interps(u0+(k1[0]/2), v0+(k1[1]/2), h0+(k1[2]/2)); f_v.set_interps(u0+(k1[0]/2), v0+(k1[1]/2), h0+(k1[2]/2)); f_h.set_interps(u0+(k1[0]/2), v0+(k1[1]/2), h0+(k1[2]/2)); - set_bdry_conds(k2[0],k2[1],Omega); + set_bdry_conds(k2[0],k2[1]); cout << "k2 done!" << endl; @@ -218,7 +191,7 @@ f_v.set_interps(u0+(k2[0]/2), v0+(k2[1]/2), h0+(k2[2]/2)); f_h.set_interps(u0+(k2[0]/2), v0+(k2[1]/2), h0+(k2[2]/2)); - set_bdry_conds(k3[0],k3[1],Omega); + set_bdry_conds(k3[0],k3[1]); cout << "k3 done!" << endl; @@ -227,7 +200,7 @@ f_v.set_interps(u0+k3[0], v0+k3[1], h0+k3[2]); f_h.set_interps(u0+k3[0], v0+k3[1], h0+k3[2]); - set_bdry_conds(k4[0],k4[1],Omega); + set_bdry_conds(k4[0],k4[1]); cout << "k4 done!" << endl; @@ -235,9 +208,8 @@ u1.set_f(u0 + (k1[0] + 2*k2[0] + 2*k3[0] + k4[0])/6); v1.set_f(v0 + (k1[1] + 2*k2[1] + 2*k3[1] + k4[1])/6); h1.set_f(h0 + (k1[2] + 2*k2[2] + 2*k3[2] + k4[2])/6); - - //Enforce boundary conditions iteratively - set_bdry_conds(u1,v1,Omega); + + set_bdry_conds(u1,v1); u0 = u1; v0 = v1; @@ -307,32 +279,6 @@ return dt*(u()*h.d(1) + h()*u.d(1) + v()*h.d(2) + h()*v.d(2)); } -iter_neumann::iter_neumann(size_t u_or_v_in) -{ - if(u_or_v_in < 1 or u_or_v_in > 2){ - error_handling::badArgument exc; - exc.reason = "Argument to iter_neumann constructor must be 1 or 2"; - exc.line = __LINE__; - exc.file = __FILE__; - throw exc; - } - u_or_v = u_or_v_in; -} - -double iter_neumann::at(const realfunc &f, const point &p, - const vector &n) const -{ - return n(u_or_v)*f(p); -} - -template<typename RBF> -double Gu_or_v<RBF>::at(const point& p) const -{ - point n = Omega -> get_normals().at(p); - return -n(u_or_v)*other(p); -} - - template<typename RBF> void save_interp(const shared_ptr<domain> Omega, const interpolator<RBF>& u, @@ -374,38 +320,23 @@ ofs << M; } -template<typename RBF> -linalg::vector at_bdry(const interpolator<RBF>& u, - const boost::shared_ptr<domain> Omega) -{ - using namespace linalg; - - vector out(Omega -> get_boundary().size()); - std::set<point>::const_iterator I = Omega -> get_boundary().begin(); - - for(size_t i = 1; i <= out.size(); i++){ - out(i) = u(*I); - I++; - } - - return out; -} template<typename RBF> -void set_bdry_conds(interpolator<RBF> & u, interpolator<RBF> & v, - const boost::shared_ptr<domain> Omega) +void set_bdry_conds(interpolator<RBF> & u, interpolator<RBF> & v) { - size_t m = Omega -> get_boundary().size(); - linalg::vector u_new(m), v_new(m); - { - set<point>::const_iterator I; - for(I = Omega -> get_boundary().begin(); - I != Omega->get_boundary().end(); - I++) - { - - } + bvp::bdry_values u_bdry = u.at(), v_bdry = v.at(); + bvp::normals N=u.get_normals(), M=v.get_normals(); + if(N != M){ + failure exc; + exc.reason="u and v have incompatible domains. This should never" + " happen."; + exc.line=__LINE__; exc.file=__FILE__; throw exc; } - - + + //Project the vector (u,v) onto the perp of (N(1),N(2)) = (-N(2),N(1)). + bvp::bdry_values u_bdry_new = u_bdry*N(2)*N(2) - v_bdry*N(1)*N(2); + bvp::bdry_values v_bdry_new = v_bdry*N(1)*N(1) - u_bdry*N(1)*N(2); + + u.set_bdry_values(u_bdry_new); + v.set_bdry_values(v_bdry_new); }