Modelowanie numeryczne w fizyce atmosfery Sylwester Arabas (ćwiczenia do wykładu dr. hab. inż. Lecha Łobockiego) Instytut Geofizyki, Wydział Fizyki Uniwersytetu Warszawskiego 3. listopada 2011 r.
Schemat całkowania leapfrog 1 #ifndef ADV_LEAPFROG_HPP 2 # define ADV_LEAPFROG_HPP 3 schematy całkowania numerycznego leapfrog 4 # include "adv.hpp" 5 6 template <class unit, typename real_t> ψi n+1 = ψi n 1 C (ψi+1 n ψn i 1 ) 7 class adv_leapfrog : public adv<unit, real_t> 8 { 9 public: const int stencil_extent() { return 3; } 10 public: const int time_levels() { return 3; } 11 public: const int num_steps() { return 1; } przykładowa implementacja 12 13 public: void op(array<quantity<unit, real_t>,1>* psi[], const Range &i, 14 const int n, const quantity<si::dimensionless, real_t> &courant, const int step) 15 { 16 assert(step == 1); 17 (*psi[n+1])(i) -= courant * ( (*psi[n])(i+1) - (*psi[n])(i-1) ); 18 } 19 }; 20 #endif
(dla schematu leapfrog) 45 (*psi[0])(range(nx/4, nx/2)) = 1; 46 47 // integration loop 48 for (int t = 0; t < nt; ++t) 49 { 50 assert(advsch->time_levels() <= 3); // FIXME: support for other values 51 bool fallback = (t == 0 && advsch->time_levels() == 3); 52 adv<si::dimensionless, real_t> *a = fallback? fllbck : advsch; 53 int n = a->time_levels() - 2; 54 55 // output 56 cout << *psi[n] << endl << endl; 57 58 for (int s = 1; s <= a->num_steps(); ++s) 59 { 60 // periodic boundary 61 (*psi[n])(range(-1)) = (*psi[n])(range(nx-1)); 62 (*psi[n])(range(nx)) = (*psi[n])(range(0)); 63 64 // copying data from psi[0] -> psi[n+1] 65 *psi[n+1] = *psi[0]; 66 67 // advection operator 68 a->op(psi, Range(0, nx-1), n, C, s); 69 70 // swapping arrays 71 if (!fallback) switch (advsch->time_levels()) 72 { 73 case 2: cyclearrays(*psi[n], *psi[n+1]); break; 74 case 3: cyclearrays(*psi[n-1], *psi[n], *psi[n+1]); break; 75 default: assert(false); 76 } 77 } 78 } 79 }
przykładowe wykresy: upstream (C = 0,3)
przykładowe wykresy: leapfrog (C = 0,3)
przykładowe wykresy: MPDATA (C = 0,3)
1 # include <boost/units/systems/si.hpp> Boost.program 2 using namespace boost::units; options: obsługa arg. linii komend 3 # include <blitz/array.h> 4 using namespace blitz; 5 #include <boost/program_options.hpp> 6 namespace po = boost::program_options; 7 #include <boost/lexical_cast.hpp> 8 9 /// error reporting dokumentacja: http://www.boost.org/doc/libs/release/libs/program options/ odpowiedniki w innych językach (ale bez obsługi plików konf.): Fortran: np. biblioteka KRACKEN a Python: np. moduł argparse (wbudowany w Pythona >= 2.7) b 10 #define error_macro(msg) { cerr << "-- error: " << msg << endl; throw exception(); } 11 #define warning_macro(msg) { cerr << "-- warning: " << msg << endl; } 12 131 ##include "model.hpp" <boost/units/systems/si.hpp> 142 using namespace boost::units; 153 # int include main(int <blitz/array.h> ac, char* av[]) 164 using { namespace blitz; 175 #include try <boost/program_options.hpp> 186 namespace { po = boost::program_options;... 197 #include /// options <boost/lexical_cast.hpp> list 208 po::options_description desc("options"); 219 /// error desc.add_options() reporting 10 22 #define("help", error_macro(msg) "print this { message") cerr << "-- error: " << msg << endl; throw exception(); } 11 23 #define("bits", warning_macro(msg) po::value<int>(), { cerr "floating << "-- warning: point bits: " << msg 32, << 64, endl; 80, 128, }...") 12 24 ("adv", po::value<string>(), "advection scheme: upstream, leapfrog, mpdata") 13 25 #include ("nx", "model.hpp" po::value<int>(), "number of grid points") 14 26 ("nt", po::value<int>(), "number of timesteps") 15 27 int main(int ("dt", ac, po::value<string>(), char* av[]) "timestep length [s]") 16 28 { ("dx", po::value<string>(), "gridbox length [m]") 17 29 try ("u", po::value<string>(), "velocity [m/s]") 18 30 { ; 19 31 /// po::variables_map options list vm; 20 32 po::options_description po::store(po::parse_command_line(ac, desc("options"); av, desc), vm); 21 33 desc.add_options() po::notify(vm); 22 34 ("help", "print this message") 23 35 ///("bits", --help po::value<int>(), or no argument case "floating point bits: 32, 64, 80, 128,...") 24 36 if ("adv", (vm.count("help") po::value<string>(), ac == 1) "advection scheme: upstream, leapfrog, mpdata") 25 37 { ("nx", po::value<int>(), "number of grid points") 26 38 ("nt", cerr << po::value<int>(), desc << endl; "number of timesteps") 27 39 ("dt", exit(exit_failure); po::value<string>(), "timestep length [s]") 28 40 } ("dx", po::value<string>(), "gridbox length [m]") 29 41 ("u", po::value<string>(), "velocity [m/s]") 30 42 /// ; --bits (floating point precision choice) 31 43 if po::variables_map (!vm.count("bits")) vm; error_macro("floating point precision not specified (--bits option)") 32 44 int po::store(po::parse_command_line(ac, bits = vm["bits"].as<int>(); av, desc), vm); 33 po::notify(vm); 34 35 /// --help or no argument case 36 if (vm.count("help") ac == 1) 37 b { 38 http://docs.python.org/library/argparse.html cerr << desc << endl; 39 exit(exit_failure); a http://home.comcast.net/ urbanjost/clone/kracken/krackenhelp.html
17 try 18 { 19 /// options list 20 po::options_description desc("options"); 21 desc.add_options() : wozrce fukcji/metod i klas 22 ("help", "print this message") 23 ("bits", po::value<int>(), "floating point bits: 32, 64, 80, 128,...") 24 ("adv", po::value<string>(), "advection scheme: upstream, leapfrog, mpdata") 25 ("nx", po::value<int>(), "number of grid points") 261 #ifndef("nt", MODEL_HPP po::value<int>(), "number of timesteps") 272 # define ("dt", MODEL_HPP po::value<string>(), "timestep length [s]") 283 ("dx", po::value<string>(), "gridbox length [m]") 294 # include ("u","blitz-gnuplot.hpp" po::value<string>(), "velocity [m/s]") 305 # include ; "adv_upstream.hpp" Fortran >= 2003: parametrised derived types (nie obsługiwane jeszcze przez GCC/GFortrana) Python: n.d. z racji kaczego typizowania 1 (w tym kontekście) 316 # include po::variables_map "adv_mpdata.hpp" vm; przykład: 32 precyzja zmiennoprzecinkowa jako parametr programu 7 # include po::store(po::parse_command_line(ac, "adv_leapfrog.hpp" av, desc), vm); 338 po::notify(vm); 349 # include <boost/lexical_cast.hpp> 35 10 /// --help or no argument case 36 11 template if (vm.count("help") <typename real_t> ac == 1) 37 12 int model(const { po::variables_map& vm) 38 13 { cerr << desc << endl; 39 14 // parameters exit(exit_failure); 40 15 if } (!vm.count("nx")!vm.count("nt")!vm.count("dx")!vm.count("dt")!vm.count("u")) 41 16 error_macro("nx, nt, dx, dt and u options are mandatory") 17 quantity<si::length, real_t> dx = boost::lexical_cast<real_t>(vm["dx"].as<string>()) * si::metres; 42 /// --bits (floating point precision choice) 18 quantity<si::time, real_t> dt = boost::lexical_cast<real_t>(vm["dt"].as<string>()) * si::seconds;... 43 19 (wewnątrz if (!vm.count("bits")) quantity<si::velocity, main(), pojedyncza, error_macro("floating real_t> podwójna u = boost::lexical_cast<real_t>(vm["u"].as<string>()) lub poczwórna point precyzja) precision not specified (--bits option)") * si::metres / si:: 44 201 #ifndef int bits quantity<si::dimensionless, ADV_HPP = vm["bits"].as<int>(); real_t> C = u * dt / dx; 45 212 # if int define (sizeof(float) nx = vm["nx"].as<int>(); ADV_HPP * 8 == bits) model<float>(vm); 46 else if (sizeof(double) * 8 == bits) model<double>(vm); 223 int nt = vm["nt"].as<int>(); 47 23 else if (sizeof(long double) * 8 == bits) model<long double>(vm); 484 # 24 // else include advection error_macro("unsupported <boost/units/systems/si.hpp> sheme "allocation" number of bits (" << bits << ")") 495 using 25 string } namespace boost::units; advscheme = vm["adv"].as<string>(); 50 266 adv<si::dimensionless, catch (exception &e) real_t> *advsch, *fllbck = NULL; 51 277 # if { include (advscheme <blitz/array.h> == "upstream") 52 28 advsch cerr << = "-- new exception adv_upstream<si::dimensionless, cought: " << e.what() real_t>(); << endl; przykład: 8 using namespace 53 29 else exit(exit_failure); wzorzec blitz; klasy if (advscheme == "leapfrog") 549 30 {} 55 10 31 } template <class unit, typename real_t> advsch = new adv_leapfrog<si::dimensionless, real_t>(); 32 11 class fllbck adv= new adv_upstream<si::dimensionless, real_t>(); 33 12 {} 34 13 else public: if (advscheme virtual == const "mpdata") int stencil_extent() = 0; 35 14 public: advsch = virtual new adv_mpdata<si::dimensionless, const int time_levels() real_t>(); = 0; 36 else error_macro("unsupported advection scheme: " << advscheme); 37 15 public: virtual const int num_steps() = 0; 38 16 // public: memory allocation virtual void op(array<quantity<unit, real_t>, 1> *psi[], const Range &i, 39 17 assert(advsch->stencil_extent() const int n, const quantity<si::dimensionless, == 3); // FIXME: support for real_t> other values &C, int step) = 0; 40 18 }; Array<quantity<si::dimensionless, real_t>, 1> **psi; 41 psi = new Array<quantity<si::dimensionless, real_t>, 1>*[advsch->time_levels()]; // FIXME: no deallocati 19 #endif 42 for (int n=0; n < advsch->time_levels(); ++n) 43 1 jeśli psi[n] chodzi = new Array<quantity<si::dimensionless, jak kaczka i kwacze jak real_t>, kaczka, 1>(Range(-1,nx)); to musi być // FIXME: kaczką ditto 44
18 { 19 /// options list 20 po::options_description desc("options"); : 21 desc.add_options() obsługa poprzez wyjątki 22 ("help", "print this message") 23 ("bits", po::value<int>(), "floating point bits: 32, 64, 80, 128,...") 24 ("adv", po::value<string>(), "advection scheme: upstream, leapfrog, mpdata") 25 ("nx", po::value<int>(), "number of grid points") odpowiedniki w innych językach: Fortran: brak 2 Python: analogicznie jak w 26 ("nt", po::value<int>(), "number of timesteps") 27 ("dt", po::value<string>(), "timestep length [s]") 28 ("dx", po::value<string>(), "gridbox length [m]") 29 ("u", po::value<string>(), "velocity [m/s]") 301 # include ; <boost/units/systems/si.hpp> 312 using po::variables_map namespace boost::units; vm; 323 # include po::store(po::parse_command_line(ac, <blitz/array.h> av, desc), vm); 334 using po::notify(vm); namespace blitz; 345 #include <boost/program_options.hpp> 356 namespace /// --help po = boost::program_options; or no argument case przykład 367 #include if (vm.count("help") <boost/lexical_cast.hpp> (najprostszy!) ac == 1) 378 { 389 /// error cerr reporting << desc << endl; 10 39 #define exit(exit_failure); error_macro(msg) { cerr << "-- error: " << msg << endl; throw exception(); } 11 40 #define } warning_macro(msg) { cerr << "-- warning: " << msg << endl; } 12 41 13 42 #include /// --bits "model.hpp" (floating point precision choice) 14 43 if (!vm.count("bits")) error_macro("floating point precision not specified (--bits option) 15 44 int int main(int bits ac, = vm["bits"].as<int>(); char* av[]) 16 45 { if (sizeof(float) * 8 == bits) model<float>(vm); 17 46 try else if (sizeof(double) * 8 == bits) model<double>(vm); 18 47 { else if (sizeof(long double) * 8 == bits) model<long double>(vm);... 19 48 /// else options error_macro("unsupported list number of bits (" << bits << ")") 20 49 } po::options_description desc("options"); 21 50 catch desc.add_options() (exception &e) 22 51 { ("help", "print this message") 23 52 cerr ("bits", << "-- po::value<int>(), exception cought: "floating " << e.what() point << bits: endl; 32, 64, 80, 128,...") 24 53 exit(exit_failure); ("adv", po::value<string>(), "advection scheme: upstream, leapfrog, mpdata") 25 54 } ("nx", po::value<int>(), "number of grid points") 26 55 } ("nt", po::value<int>(), "number of timesteps") 27 ("dt", po::value<string>(), "timestep length [s]") 28 ("dx", po::value<string>(), "gridbox length [m]") 29 ("u", po::value<string>(), "velocity [m/s]") 30 ; 31 po::variables_map vm; 32 2 Numercial po::store(po::parse_command_line(ac, Recipes in F90 2nd ed. av,... desc), Fortran s vm); lack of in-built exception 33 po::notify(vm); handling 34... much requested by the numerical community...
: pola, konstruktory i metod 1 #ifndef ADV_MPDATA_HPP 2 # define ADV_MPDATA_HPP 3 przykład: 4 # include pole "adv.hpp" eps, konstruktor, domyślna wartość eps 5 6 template <class unit, typename real_t> 7 class adv_mpdata : public adv<unit, real_t> 8 { 9 public: const int stencil_extent() { return 3; } 10 public: const int time_levels() { return 2; } 11 public: const int num_steps() { return 2; } 12 13 protected: real_t eps; 14 public: adv_mpdata(real_t eps_ = 1e-6) { eps = eps_; } 15 16 public: void op(array<quantity<unit, real_t>,1>* psi[], const 17 const int n, const quantity<si::dimensionless, real_t> &cour const int step) 18 { 19 # ifdef F 20 assert(false); 21 # else 22 # define F(psi_l,psi_r,U) (.5 * (U + sqrt(u*u)) * psi_l +.5