changeset 14:e6d2cd3b6e77

Intermediate whole domain evaluation work
author Jordi Gutiérrez Hermoso <jordigh@gmail.com>
date Sun, 03 Aug 2008 10:59:37 -0500
parents 0531194a431d
children 5144dd3c5468
files Makefile diff_op.cpp include/interpolator.hpp include/linalg.hpp interpolator.cpp linalg.cpp main.cpp
diffstat 7 files changed, 219 insertions(+), 186 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CPP = g++
-LINKING = -lgsl -lgslcblas  -pg
-CFLAGS = -pg
+LINKING = -lgsl -lgslcblas  
+CFLAGS = -g
 OPTIONS = -Wall -pedantic  -W -Werror -Wconversion -Wshadow \
 	  -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings  \
 	  -fshort-enums -fno-common -Wfatal-errors 
--- a/diff_op.cpp
+++ b/diff_op.cpp
@@ -47,7 +47,7 @@
     vector grad(dim);
     for(size_t i = 1; i <= dim; i++)
       grad(i) =f.d(p,i);
-    return grad*n/norm(n);
+    return grad%n/norm(n);
   }
 
   double Id_op::at(const realfunc &f, const point &p) const{
--- a/include/interpolator.hpp
+++ b/include/interpolator.hpp
@@ -52,7 +52,7 @@
     void interpolate(const map<point, double>& Xi); 
     void interpolate(shared_ptr<linear_BVP2> bvp);
     
-    /** Interpolate given values on the domain
+    /** \short Interpolate given values on the domain
      * 
      * The given values must match the values returned by other
      * interpolators on compatible domains.
@@ -60,31 +60,34 @@
     void interpolate(const interp_values& values); 
     //@}
     
-    /** @name Evaluations and derivatives
-     * 
-     * Full domain evaluations and derivatives are 
+
+    /** @name Pointwise evaluation and derivatives
      */
     //@{
     ///Point evaluation
     double operator()(const point& p) const;
     ///Point evaluation
     double at(const point& p) const;
-
+    /// Pointwise first derivative
+    double d(const point& p, size_t k) const;
+    /// Pointwise second derivatives
+    double d2(const point &p, size_t k1, size_t k2) const;
+    //@}
+    
+    /** @name Full domain evaluation and derivatives
+     */
+    //@{
     ///Full domain evaluation
     interp_values operator()() const; 
     ///Full domain evaluation
     interp_values at() const; 
-
-    /// Pointwise first derivative
-    double d(const point& p, size_t k) const;
     /// Full domain first erivative
     interp_values d(size_t k) const; 
-    /// Pointwise second derivatives
-    double d2(const point &p, size_t k1, size_t k2) const;
     /// Full domain second derivatives
     interp_values d2(size_t k1, size_t k2) const; 
     //@}
 
+
     /** @name Precomputation of RBFs
      *
      * The following functions will precompute upon request all the
@@ -94,9 +97,9 @@
      */
     //@{
     ///Precompute all the function evaluation of the RBFs.
-    void precompute_at();
+    void precompute_ev();
     ///Precompute all relevant first derivatives.
-    void precompute_d() ;
+    void precompute_d1() ;
     ///Precompute all relevant second derivatives.
     void precompute_d2();
     //@}
@@ -198,8 +201,8 @@
     /// Same, but storing the vectors.
     mutable map<std::vector<size_t>, linalg::vector >
     precomp_values_vec;
-    /// Invert phis\coeffs and return result vector in a map.
-    map<point, double> precompute_values(const matrix& phis) const;
+    /// Convert vector of values to a map
+    map<point, double> valsvec2map(const linalg::vector& values) const;
   };
 
   /// Interpolated values manipulated by the interpolator class.
@@ -217,6 +220,8 @@
     interp_values operator-(const interp_values& w) const;
     interp_values operator*(const interp_values& w) const;
     interp_values operator/(const interp_values& w) const;
+    interp_values operator*(const double a) const;
+    interp_values operator/(const double a) const;
     //@}
   private:
     
@@ -234,14 +239,13 @@
     void different_rbfs(int line, string file) const;
 
     template<typename RBF> friend class interpolator;
+    friend interp_values operator*(const interp_values& v, const
+				   interp_values& w); 
   };
 
   ///For comfortable syntax
   template <typename RBF>
-  interpolator<RBF> operator*(double a, const interpolator<RBF>& u)
-  {
-    return u*a;
-  }
+  interpolator<RBF> operator*(double a, const interpolator<RBF>& u);
 }
 
 #endif
--- a/include/linalg.hpp
+++ b/include/linalg.hpp
@@ -261,7 +261,9 @@
 
     //Arithmetic operations:
     ///Scale the vector.
-    vector operator*(const double a)  const; 
+    vector operator*(const double a)  const;
+    ///Scale the vector.
+    vector operator/(const double a)  const;
     ///Vector addition.
     vector operator+(const vector& w) const;
     ///Vector subtration.
--- a/interpolator.cpp
+++ b/interpolator.cpp
@@ -159,6 +159,9 @@
 	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();
     }
   }
 
@@ -239,37 +242,12 @@
     return seed;
   }
   
-
-  //***** Evaluations, derivatives *************
-
-  template<typename RBF>
-  double interpolator<RBF>::operator()(const point& p) const
-  {
-    return at(p);
-  }
-
-  template<typename RBF>
-  map<point, double> interpolator<RBF>::precompute_values(const matrix& phis) 
-    const
-  {
-    linalg::vector values = phis*coeffs;
-    map<point, double> out;
-    {
-      set<point>::const_iterator I;
-      size_t i;
-      for(I = thebvp -> get_domain() -> get_interior().begin(), i = 1;
-	  i <= n; I++, i++)
-	out[*I] = values(i);
-      
-      for(I = thebvp -> get_domain() -> get_boundary().begin(), i = n+1;
-	  i <= n+m; I++, i++)
-	out[*I] = values(i);
-    }
-    return out;
-  }
+  // ******************** Evaluations, derivatives ********************
+ 
+  //  ---------- Precomputation ---------------------------
   
   template<typename RBF>
-  void interpolator<RBF>::precompute_at()
+  void interpolator<RBF>::precompute_ev()
   {
     if(!initted){
       not_initted(__LINE__, __FILE__);
@@ -293,65 +271,14 @@
 	  phis(i,j+1) = rbfs[j].at(*I);
       
       precomp_rbfs[alpha] = phis;
-      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__);
+      computecoeffs();
+      
+      ev_precomp = true;
     }
-    std::vector<size_t> alpha; //empty vector
-
-    //Are we evaluating at a precomputed point in the domain?
-    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>::not_precomputed(int line, string file) const
-  {
-    badArgument exc;
-    exc.reason = "Cannot do whole domain evaluations without "
-      "precomputed RBFs.";
-    exc.line = line;
-    exc.file = file;
-    throw exc;
-  }
-
-  template<typename RBF>
-  interp_values interpolator<RBF>::operator()() const
-  {
-    return at();
-  }
-  
-  template<typename RBF>
-  interp_values interpolator<RBF>::at() const
-  {
-    if(!ev_precomp)
-      not_precomputed(__LINE__, __FILE__);
-     
-    std::vector<size_t> alpha;
-    return interp_values(precomp_values_vec[alpha],rbfs_hash);
-  }
-  
-  
-
-  template<typename RBF>
-  void interpolator<RBF>::precompute_d()
+  void interpolator<RBF>::precompute_d1()
   {
     if(!initted){
       not_initted(__LINE__, __FILE__);
@@ -380,13 +307,74 @@
 	}
 
 	precomp_rbfs[alpha] = phis;
-	precomp_values[alpha] = precompute_values(phis);
+	computecoeffs();
       }
     }
     d1_precomp = true;
   }
 
   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
+      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;
+	    computecoeffs();	  
+	}
+      }
+    }
+    d2_precomp = true;
+  }
+
+  // ----------------- Point evaluation ---------------------------
+
+  template<typename RBF>
+  double interpolator<RBF>::operator()(const point& p) const
+  {
+    return at(p);
+  }
+
+  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(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>
   double interpolator<RBF>::d(const point& p, size_t k) const{
     if(!initted){
       not_initted(__LINE__, __FILE__);
@@ -407,49 +395,6 @@
   }
 
   template<typename RBF>
-  interp_values interpolator<RBF>::d(size_t k) const
-  {
-    if(!d1_precomp)
-      not_precomputed(__LINE__, __FILE__);
-    
-    std::vector<size_t> alpha(k); alpha[k-1]++;
-    return interp_values(precomp_values_vec[alpha],rbfs_hash);
-  }
-
-  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__);
@@ -469,6 +414,45 @@
     return result;
   }
 
+  // ------------------- Whole domain evaluations ----------------
+
+  template<typename RBF>
+  void interpolator<RBF>::not_precomputed(int line, string file) const
+  {
+    badArgument exc;
+    exc.reason = "Cannot do whole domain evaluations without "
+      "precomputed RBFs.";
+    exc.line = line;
+    exc.file = file;
+    throw exc;
+  }
+
+  template<typename RBF>
+  interp_values interpolator<RBF>::operator()() const
+  {
+    return at();
+  }
+  
+  template<typename RBF>
+  interp_values interpolator<RBF>::at() const
+  {
+    if(!ev_precomp)
+      not_precomputed(__LINE__, __FILE__);
+     
+    std::vector<size_t> alpha;
+    return interp_values(precomp_values_vec[alpha],rbfs_hash);
+  }
+   
+  template<typename RBF>
+  interp_values interpolator<RBF>::d(size_t k) const
+  {
+    if(!d1_precomp)
+      not_precomputed(__LINE__, __FILE__);
+    
+    std::vector<size_t> alpha(k); alpha[k-1]++;
+    return interp_values(precomp_values_vec[alpha],rbfs_hash);
+  }
+
   template<typename RBF>
   interp_values interpolator<RBF>::d2(size_t k1, size_t k2) const
   {
@@ -479,7 +463,7 @@
     return interp_values(precomp_values_vec[alpha],rbfs_hash);
   }
 
-  //********** linear operations ***************
+  //***************** linear operations ***************************
 
   template<typename RBF>
   interpolator<RBF> interpolator<RBF>::
@@ -535,7 +519,7 @@
     return u;
   }
   
-  //********** data manipulation ***************
+  //******************* data manipulation **************************
 
   template<typename RBF>
   void interpolator<RBF>::set_f(const realfunc& f){
@@ -611,14 +595,36 @@
     coeffs = M.inv(rhs);
     
     //Precompute the values for the derivatives and evaluations that
-    //have already  been computed.
+    //have already been computed.
     {
       typename map<std::vector<size_t>, matrix>::const_iterator I;
       
-      for(I = precomp_rbfs.begin(); I != precomp_rbfs.end(); I++)
-	precomp_values[I -> first] = precompute_values(I->second);
+      for(I = precomp_rbfs.begin(); I != precomp_rbfs.end(); I++){
+	linalg::vector vals = (I->second)*coeffs;
+	precomp_values_vec[I -> first] = vals;
+	precomp_values[I -> first] = valsvec2map(vals);
+      }
     }
   }
+
+  template<typename RBF>
+  map<point, double> interpolator<RBF>::
+  valsvec2map(const linalg::vector& values) const
+  {
+    map<point, double> out;
+    {
+      set<point>::const_iterator I;
+      size_t i;
+      for(I = thebvp -> get_domain() -> get_interior().begin(), i = 1;
+	  i <= n; I++, i++)
+	out[*I] = values(i);
+      
+      for(I = thebvp -> get_domain() -> get_boundary().begin(), i = n+1;
+	  i <= n+m; I++, i++)
+	out[*I] = values(i);
+    }
+    return out;
+  }
   
   // ************************ interp_values stuff *****************
   void interp_values::different_rbfs(int line, string file) const
@@ -666,6 +672,35 @@
     return interp_values(v / w.v,rbfs_hash);
   }
 
+  interp_values
+  interp_values::operator*(const double a) const
+  {
+    return interp_values(v*a,rbfs_hash);
+  }
+  
+  interp_values
+  interp_values::operator/(const double a) const
+  {
+    return interp_values(v/a, rbfs_hash);
+  }
+
+  //*************** Non-member global friend functions ******************
+
+  template <typename RBF>
+  interpolator<RBF> operator*(double a, const interpolator<RBF>& u)
+  {
+    return u*a;
+  }  
+
+  interp_values operator*(const interp_values& v, const interp_values&
+  w)
+  {
+    if(v.rbfs_hash != w.rbfs_hash)
+      v.different_rbfs(__LINE__, __FILE__);
+    
+    return interp_values(v.v / w.v,v.rbfs_hash);
+  } 
+
   //Instantiations
   using namespace rbf;
   template class interpolator<piecewise_polynomial>;
--- a/linalg.cpp
+++ b/linalg.cpp
@@ -492,6 +492,12 @@
     gsl_vector_scale(v.x, a);
     return v;
   }
+  
+  vector vector::operator/(const double a) const{
+    vector v = *this;
+    gsl_vector_scale(v.x, 1.0/a);
+    return v;
+  }
 
   vector vector::operator+(const vector& w) const{
     if(x -> size != w.x->size){
--- a/main.cpp
+++ b/main.cpp
@@ -36,7 +36,7 @@
 const double g = 9.8; // m/s^2
 
 template<typename RBF>
-class Fgen : public realfunc{
+class Fgen {
 public:
   void set_interps(const interpolator<RBF>& u0, 
 		   const interpolator<RBF>& v0,
@@ -59,7 +59,7 @@
   using Fgen<RBF>::h;
   using Fgen<RBF>::dt;
 public:
-  double at(const point& p) const;
+  bvp::interp_values at() const;
 };
 
 template<typename RBF>
@@ -69,7 +69,7 @@
   using Fgen<RBF>::h;
   using Fgen<RBF>::dt;
 public:
-  double at(const point& p) const;
+  bvp::interp_values at() const;
 };
 
 template<typename RBF>
@@ -79,9 +79,10 @@
   using Fgen<RBF>::h;
   using Fgen<RBF>::dt;
 public:
-  double at(const point& p) const;
+  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.
@@ -164,15 +165,17 @@
       h1, h0(Omega, h_init);
 
     //Precompute some RBFs
-    u0.precompute_at(); v0.precompute_at(), h0.precompute_at();
-    u0.precompute_d(); v0.precompute_d(), h0.precompute_d();
+    u0.precompute_ev(); v0.precompute_ev(), h0.precompute_ev();
+    u0.precompute_d1(); v0.precompute_d1(), h0.precompute_d1();
 
 
     u1 = u0; v1 = v0; h1 = h0;
 
     //Intermediate interpolators for RK4
     std::vector<interpolator<RBF_TYPE> >
-      k1(3,h0), k2(3,h0), k3(3,h0), k4(3,h0);
+      // FIXME: make the copy ctor for interps make different copies
+      // of the bvp.
+      k1(3,h0), k2(3,h0), k3(3,h0), k4(3,h0); 
 
     Fu<RBF_TYPE> f_u;
     Fv<RBF_TYPE> f_v;
@@ -182,8 +185,6 @@
     f_v.set_dt(dt);
     f_h.set_dt(dt);
 
-
-
     //main loop
     size_t maxiter = 1000;
     for(size_t i = 1; i <= maxiter; i++){ 
@@ -199,9 +200,6 @@
       f_v.set_interps(u0,v0,h0);
       f_h.set_interps(u0,v0,h0);
       
-      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);
@@ -211,10 +209,6 @@
       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));
  
-      k2[0].set_f(f_u);
-      k2[1].set_f(f_v);
-      k2[2].set_f(f_h);
-
       bdry_iter(k2[0],k2[1],Omega);
 
       cout << "k2 done!" << endl;
@@ -224,10 +218,6 @@
       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));
       
-      k3[0].set_f(f_u);
-      k3[1].set_f(f_v);
-      k3[2].set_f(f_h);
-
       bdry_iter(k3[0],k3[1],Omega);
       
       cout << "k3 done!" << endl;
@@ -237,10 +227,6 @@
       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]);
       
-      k4[0].set_f(f_u);
-      k4[1].set_f(f_v);
-      k4[2].set_f(f_h);
-
       bdry_iter(k4[0],k4[1],Omega);
 
       cout << "k4 done!" << endl;
@@ -262,7 +248,7 @@
   }
   catch(error exc){
     utils::show_exception(exc);
-    return 1;
+    return ;
   }
 
 }
@@ -304,21 +290,21 @@
 
 
 template<typename RBF>
-double Fu<RBF>::at(const point& p) const
+interp_values Fu<RBF>::at() const
 {
-  return   dt*(u(p)*u.d(p,1) +  v(p)*u.d(p,2) +  g*h.d(p,1));
+  return   dt*(u()*u.d(1) +  v()*u.d(2) +  g*h.d(1));
 }
 
 template<typename RBF>
-double Fv<RBF>::at(const point& p) const
+interp_values Fv<RBF>::at() const
 {
-  return   dt*(u(p)*v.d(p,1) +  v(p)*v.d(p,2) +  g*h.d(p,2));
+  return   dt*(u()*v.d(1) +  v()*v.d(2) +  g*h.d(2));
 }
 
 template<typename RBF>
-double Fh<RBF>::at(const point& p) const
+interp_values Fh<RBF>::at() const
 {
-  return   dt*(u(p)*h.d(p,1) + h(p)*u.d(p,1) +   v(p)*h.d(p,2) + h(p)*v.d(p,2));
+  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)