Mercurial > hg > kwantix
view src/main-sw-euler.cpp @ 30:d22bce6382d7
Finalise removal of all namespaces, one namespace to rule them all.
author | Jordi Gutiérrez Hermoso <jordigh@gmail.com> |
---|---|
date | Wed, 03 Feb 2010 19:30:20 -0600 |
parents | 0af772242000 |
children | 9a2279c9d003 |
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 kwantxi; #define RBF_TYPE kwantxi::conical //Will solve the system // // u_t = -u*u_x - v*u_y - g*h_x =: g1(u,v,h) // // v_t = -u*v_x - v*v_y - g*h_y =: g2(u,v,h) // // h_t = -u*h_x - h*u_x - v*h_y - h*v_y =: g3(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 directly computing the next timestep //by // // u_{t+1} = u_t + /\t*g1(u_t, v_t, h_t) =: f_u(u_t, v_t, h_t, /\t) // // v_{t+1} = v_t + /\t*g2(u_t, v_t, h_t) =: f_v(u_t, v_t, h_t, /\t) // // h_{t+1} = h_t + /\t*g3(u_t, v_t, h_t) =: f_h(u_t, v_t, h_t, /\t) // //Let's hope some waves propagate here. :-) const double g = 9.8; // m/s^2 template<typename RBF> class Fgen : public realfunc{ 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: double dt; interpolator<RBF> u; interpolator<RBF> v; interpolator<RBF> h; }; 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: double at(const point& p) 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: double at(const point& p) 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: double at(const point& p) const; }; 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(&kwantxi::errorHandler); try{ using namespace std; using boost::shared_ptr; map<point, double> h_init = kwantxi::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 = 0.0005; //init the interps. conical::set_n(5); thin_plate_spline::set_n(6); c_infty_kwantxi::set_epsilon(0.01); cout << "Initialising... please wait." << endl; interpolator<RBF_TYPE> u1, u0(u_bvp_init), v1, v0(v_bvp_init), h1, h0(h_init); u1 = u0; v1 = v0; h1 = 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 = 20; for(size_t i = 1; i <= maxiter; i++){ cout << "Now on iteration #" << i << endl; save_interp(Omega,u0,i,"u"); save_interp(Omega,v0,i,"v"); save_interp(Omega,h0,i,"h"); f_h.set_interps(u0,v0,h0); f_u.set_interps(u0,v0,h0); f_v.set_interps(u0,v0,h0); h1.set_f(f_h); u1.set_f(f_u); v1.set_f(f_v); //Enforce boundary conditions iteratively bdry_iter(u1,v1,Omega); u0 = u1; v0 = v1; h0 = h1; } return 0; } catch(error exc){ kwantxi::show_exception(exc); return 1; } } //******************* 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> double Fu<RBF>::at(const point& p) const{ return u(p) - dt*( u(p)*u.d(p,1) + v(p)*u.d(p,2) + g*h.d(p,1) ); } template<typename RBF> double Fv<RBF>::at(const point& p) const{ return v(p) - dt*( u(p)*v.d(p,1) + v(p)*v.d(p,2) + g*h.d(p,2) ); } template<typename RBF> double Fh<RBF>::at(const point& p) const{ return h(p) - 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) ); } iter_neumann::iter_neumann(size_t u_or_v_in) { if(u_or_v_in < 1 or u_or_v_in > 2){ kwantxi::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> kwantxi::vector at_bdry(const interpolator<RBF>& u, const boost::shared_ptr<domain> Omega) { 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{ kwantxi::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); }