Mercurial > hg > kwantix
view main.cpp @ 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 | d0076d9b2ef1 |
children | 5144dd3c5468 |
line wrap: on
line source
#include <iostream> #include <fstream> #include <map> #include <set> #include <sstream> #include <boost/shared_ptr.hpp> #include "include/linalg.hpp" #include "include/rbf.hpp" #include "include/bvp.hpp" #include "include/error.hpp" #include "include/utils.hpp" #include "include/diff_op.hpp" #include "include/interpolator.hpp" #include "include/func.hpp" using namespace linalg; using namespace bvp; #define RBF_TYPE rbf::conical //Will solve the system // // u_t = -u*u_x - v*u_y - g*h_x =: f1(u,v,h) // // v_t = -u*v_x - v*v_y - g*h_y =: f2(u,v,h) // // h_t = -u*h_x - h*u_x - v*h_y - h*v_y =: f3(u,v,h) // //where g is the acceleration due to gravity, u(x,y,0) = v(x,y,0) = 0, //and h starts out as an undisturbed surface high with a small //disturbance. We'll do this by RK4. const double g = 9.8; // m/s^2 template<typename RBF> class Fgen { public: void set_interps(const interpolator<RBF>& u0, const interpolator<RBF>& v0, const interpolator<RBF>& h0); void set_u(const interpolator<RBF>& u0); void set_v(const interpolator<RBF>& v0); void set_h(const interpolator<RBF>& h0); void set_dt(double dt_in); protected: interpolator<RBF> u; interpolator<RBF> v; interpolator<RBF> h; double dt; }; template<typename RBF> class Fu : public Fgen<RBF>{ using Fgen<RBF>::u; using Fgen<RBF>::v; using Fgen<RBF>::h; using Fgen<RBF>::dt; public: bvp::interp_values at() const; }; template<typename RBF> class Fv : public Fgen<RBF>{ using Fgen<RBF>::u; using Fgen<RBF>::v; using Fgen<RBF>::h; using Fgen<RBF>::dt; public: bvp::interp_values at() const; }; template<typename RBF> class Fh : public Fgen<RBF>{ using Fgen<RBF>::u; using Fgen<RBF>::v; using Fgen<RBF>::h; using Fgen<RBF>::dt; public: 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;}; }; //************ Function declarations **************************** template<typename RBF> void save_interp(const shared_ptr<domain> Omega, const interpolator<RBF>& u, size_t n, string which_interp); template<typename RBF> void bdry_iter(interpolator<RBF> &u, interpolator<RBF> &v, const boost::shared_ptr<domain> Omega); //********************** Main ****************************************** int main() { gsl_set_error_handler(&error_handling::errorHandler); try{ using namespace std; using boost::shared_ptr; map<point, double> h_init = utils::read_pd_map("data/h_init.map"); shared_ptr<domain> Omega(new domain("data/circ_intr.matrix", "data/circ_bdry.matrix", "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)); zero_func Z; 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)); double dt = 1e-2; //init the interps. using namespace rbf; conical::set_n(5); thin_plate_spline::set_n(6); c_infty_rbf::set_epsilon(0.01); cout << "Initialising... please wait." << endl; interpolator<RBF_TYPE> u1, u0(u_bvp_init), v1, v0(v_bvp_init), h1, h0(Omega, h_init); //Precompute some RBFs 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> > // 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; Fh<RBF_TYPE> f_h; f_u.set_dt(dt); f_v.set_dt(dt); f_h.set_dt(dt); //main loop size_t maxiter = 1000; for(size_t i = 1; i <= maxiter; i++){ cout << "Now on iteration #" << i << endl; if(i % 1 == 0){ save_interp(Omega,u0,i,"u"); save_interp(Omega,v0,i,"v"); save_interp(Omega,h0,i,"h"); } //k1 f_u.set_interps(u0,v0,h0); f_v.set_interps(u0,v0,h0); f_h.set_interps(u0,v0,h0); cout << "k1 done!" << endl; bdry_iter(k1[0],k1[1],Omega); //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)); 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)); f_h.set_interps(u0+(k2[0]/2), v0+(k2[1]/2), h0+(k2[2]/2)); 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]); 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]); 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); 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 bdry_iter(u1,v1,Omega); u0 = u1; v0 = v1; h0 = h1; } return 0; } catch(error exc){ utils::show_exception(exc); return ; } } //******************* Function definitions *************************** template<typename RBF> void Fgen<RBF>::set_interps(const interpolator<RBF>& u0, const interpolator<RBF>& v0, const interpolator<RBF>& h0){ set_u(u0); set_v(v0); set_h(h0); } template<typename RBF> void Fgen<RBF>::set_u(const interpolator<RBF>& u0) { u = u0; } template<typename RBF> void Fgen<RBF>::set_v(const interpolator<RBF>& v0) { v = v0; } template<typename RBF> void Fgen<RBF>::set_h(const interpolator<RBF>& h0) { h = h0; } template<typename RBF> void Fgen<RBF>::set_dt(double dt_in) { dt = dt_in; } template<typename RBF> interp_values Fu<RBF>::at() const { return dt*(u()*u.d(1) + v()*u.d(2) + g*h.d(1)); } template<typename RBF> interp_values Fv<RBF>::at() const { return dt*(u()*v.d(1) + v()*v.d(2) + g*h.d(2)); } template<typename RBF> interp_values Fh<RBF>::at() const { 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, size_t n, string which_interp) { using namespace std; string filename = "results/" + which_interp; if(n < 10000) filename += "0"; if(n < 1000) filename += "0"; if(n < 100) filename += "0"; if(n < 10) filename += "0"; stringstream ss; string n_string; ss << n; ss >> n_string; filename += n_string + ".map"; ofstream ofs(filename.c_str()); slice s(1,2); matrix M(Omega -> get_interior().size() + Omega -> get_boundary().size(), 3); size_t k = 1; for(set<point>::const_iterator i = Omega -> get_interior().begin(); i != Omega -> get_interior().end(); i++){ M(k,s) = *i; M(k,3) = u(*i); k++; } for(set<point>::const_iterator i = Omega -> get_boundary().begin(); i != Omega -> get_boundary().end(); i++){ M(k,s) = *i; M(k,3) = u(*i); k++; } 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 bdry_iter(interpolator<RBF> &u, interpolator<RBF> &v, const boost::shared_ptr<domain> Omega) { Gu_or_v<RBF_TYPE> gu(2, Omega), gv(1, Omega); double err = 1; do{ linalg::vector u_old, u_new, v_old, v_new; u_old = at_bdry(u,Omega); gu.set_other(v); u.set_g(gu); u_new = at_bdry(u,Omega); v_old = at_bdry(v,Omega); gv.set_other(u); v.set_g(gv); v_new = at_bdry(v,Omega); double err_u = norm(u_new - u_old); double err_v = norm(v_new - v_old); err = (err_u > err_v? err_u : err_v); }while(err > 1e-2); }