Advertisement
bolverk

rich_v2_offset_supernova

Mar 27th, 2015
479
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.36 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <limits>
  4. #include "tessellation/static_voronoi_mesh.hpp"
  5. #include "newtonian/two_dimensional/hdsim2d.hpp"
  6. #include "newtonian/two_dimensional/interpolations/pcm2d.hpp"
  7. #include "newtonian/two_dimensional/spatial_distributions/uniform2d.hpp"
  8. #include "newtonian/common/ideal_gas.hpp"
  9. #include "newtonian/two_dimensional/geometric_outer_boundaries/SquareBox.hpp"
  10. #include "newtonian/two_dimensional/hydro_boundary_conditions/RigidWallHydro.hpp"
  11. #include "newtonian/common/hllc.hpp"
  12. #include "newtonian/two_dimensional/source_terms/zero_force.hpp"
  13. #include "newtonian/two_dimensional/point_motions/eulerian.hpp"
  14. #include "newtonian/two_dimensional/point_motions/lagrangian.hpp"
  15. #include "newtonian/two_dimensional/point_motions/eulerian.hpp"
  16. #include "newtonian/two_dimensional/point_motions/round_cells.hpp"
  17. #include "newtonian/two_dimensional/diagnostics.hpp"
  18. #include "newtonian/two_dimensional/source_terms/cylindrical_complementary.hpp"
  19. #include "newtonian/two_dimensional/source_terms/CenterGravity.hpp"
  20. #include "newtonian/two_dimensional/source_terms/SeveralSources.hpp"
  21. #include "misc/simple_io.hpp"
  22. #include "newtonian/test_2d/main_loop_2d.hpp"
  23. #include "newtonian/test_2d/kill_switch.hpp"
  24. #include "newtonian/two_dimensional/hdf5_diagnostics.hpp"
  25. #include "misc/mesh_generator.hpp"
  26. #include "tessellation/RoundGrid.hpp"
  27. #include "misc/int2str.hpp"
  28. #include "newtonian/two_dimensional/interpolations/linear_gauss_consistent.hpp"
  29. #include "newtonian/test_2d/consecutive_snapshots.hpp"
  30. #include <boost/foreach.hpp>
  31. #include "newtonian/two_dimensional/hydro_boundary_conditions/FreeFlow.hpp"
  32. #include "misc/utils.hpp"
  33. #include "tessellation/shape_2d.hpp"
  34. #include "newtonian/test_2d/piecewise.hpp"
  35. #include "mpi/MeshPointsMPI.hpp"
  36. #include "mpi/mpi_macro.hpp"
  37. #include "mpi/ConstNumberPerProc.hpp"
  38. #include "misc/hdf5_utils.hpp"
  39. #include "newtonian/test_2d/contour.hpp"
  40. #include "newtonian/two_dimensional/custom_evolutions/Ratchet.cpp"
  41. #include "newtonian/two_dimensional/diagnostics.hpp"
  42. #include "newtonian/two_dimensional/simple_flux_calculator.hpp"
  43. #include "newtonian/two_dimensional/simple_cell_updater.hpp"
  44. #include <fenv.h>
  45.  
  46. using namespace std;
  47. using namespace simulation2d;
  48.  
  49. namespace {
  50.  
  51.   class CellEdgesGetter: public LazyList<Edge>
  52.   {
  53.   public:
  54.     CellEdgesGetter(const Tessellation& tess,
  55.             const int n):
  56.       tess_(tess), edge_indices_(tess_.GetCellEdges(n)) {}
  57.  
  58.     size_t size(void) const
  59.     {
  60.       return edge_indices_.size();
  61.     }
  62.  
  63.     Edge operator[](size_t i) const
  64.     {
  65.       return tess_.GetEdge(edge_indices_[i]);
  66.     }
  67.  
  68.   private:
  69.     const Tessellation& tess_;
  70.     const vector<int> edge_indices_;
  71.   };
  72.  
  73.   class WriteConserved: public DiagnosticFunction
  74.   {
  75.   public:
  76.  
  77.     WriteConserved(const string& fname):
  78.       cons_(), fname_(fname) {}
  79.  
  80.     void operator()(const hdsim& sim)
  81.     {
  82.       cons_.push_back(total_conserved(sim));
  83.       time_.push_back(sim.getTime());
  84.     }
  85.  
  86.     ~WriteConserved(void)
  87.     {
  88.       ofstream f(fname_.c_str());
  89.       for(size_t i=0;i<cons_.size();++i)
  90.     f << time_[i] << " "
  91.       << cons_[i].mass << " "
  92.       << cons_[i].momentum.x << " "
  93.       << cons_[i].momentum.y << " "
  94.       << cons_[i].energy << " "
  95.       << cons_[i].tracers["ejecta"] << "\n";
  96.       f.close();
  97.     }
  98.  
  99.   private:
  100.     mutable vector<Extensive> cons_;
  101.     mutable vector<double> time_;
  102.     const string fname_;
  103.   };
  104.  
  105.   class Constants
  106.   {
  107.   public:
  108.  
  109.     // Metric prefix
  110.     const double kilo;
  111.     const double centi;
  112.  
  113.     // Length / distance
  114.     const double parsec;
  115.     const double meter;
  116.  
  117.     // Time
  118.     const double year;
  119.     const double second;
  120.  
  121.     // Mass
  122.     const double solar_mass;
  123.     const double gram;
  124.  
  125.     // Energy
  126.     const double erg;
  127.  
  128.     // Force
  129.     const double newton;
  130.  
  131.     // Parameters
  132.     const double black_hole_mass;
  133.     const double zeta;
  134.     const double adiabatic_index;
  135.     const double gravitation_constant;
  136.     const double rho_0;
  137.     const double R_0;
  138.     const double omega_in;
  139.     const double inner_density_prefactor;
  140.     const double R_b;
  141.     const double omega_out;
  142.     const double outer_density_prefactor;
  143.     const double offset;
  144.     const double supernova_energy;
  145.     const double supernova_radius;
  146.     const double supernova_volume;
  147.     const double supernova_mass;
  148.     const double supernova_density;
  149.     const double supernova_pressure;
  150.     const Vector2D lower_left;
  151.     const Vector2D upper_right;
  152.  
  153.     Constants(void):
  154.       kilo(1e3),
  155.       centi(1e-2),
  156.       parsec(1),
  157.       meter(3.24e-17*parsec),
  158.       year(1),
  159.       second(year/3.16e7),
  160.       solar_mass(1),
  161.       gram(5.03e-34*solar_mass),
  162.       erg(gram*pow(centi*meter/second,2)),
  163.       newton(kilo*gram*meter/pow(second,2)),
  164.       black_hole_mass(1e6*solar_mass),
  165.       zeta(pow(black_hole_mass/(4.3e6*solar_mass),7./15.)),
  166.       adiabatic_index(5./3.),
  167.       gravitation_constant(6.673e-11*newton*pow(meter/(kilo*gram),2)),
  168.       rho_0(2.2e-22*gram/pow(centi*meter,3)),
  169.       R_0(0.04*parsec*zeta),
  170.       omega_in(1),
  171.       inner_density_prefactor(rho_0*pow(R_0,omega_in)),
  172.       R_b(0.4*parsec*zeta),
  173.       omega_out(3),
  174.       outer_density_prefactor
  175.       (inner_density_prefactor*pow(R_b,omega_out-omega_in)),
  176.       offset(0.24*R_b),
  177.       supernova_energy(1e51*erg),
  178.       supernova_radius(0.2*offset),
  179.       supernova_volume((4.*M_PI/3)*pow(supernova_radius,3)),
  180.       supernova_mass(5*solar_mass),
  181.       supernova_density(supernova_mass/supernova_volume),
  182.       supernova_pressure((adiabatic_index-1)*supernova_energy/supernova_volume),
  183.       lower_left(parsec*Vector2D(0,-2*offset)),
  184.       upper_right(parsec*Vector2D(2*offset,2*offset)) {}
  185.   };
  186.  
  187.   /*
  188.   class Bremsstrahlung: public DiagnosticFunction
  189.   {
  190.   public:
  191.  
  192.     Bremsstrahlung(const string& fname, const Constants& c):
  193.       fname_(fname),
  194.       // Coefficient is taken from Rybicki and Lightman 1979, page 162 equation 5.15b
  195.       boltzmann_constant_(1.38e-16*c.erg),
  196.       coefficient_(1.4e-27*c.erg/pow(c.centi*c.meter,3)/c.second),
  197.       particle_mass_(1.67e-24*c.gram),
  198.       cc_(pow(c.centi*c.meter,3)) {}
  199.  
  200.     void operator()(const hdsim& sim)
  201.     {
  202.       double total_luminosity = 0;
  203.       const PhysicalGeometry& pg = sim.getPhysicalGeometry();
  204.       const Tessellation& tess = sim.getTessellation();
  205.       for(int i=0;i<static_cast<int>(sim.getAllCells().size());++i)
  206.     total_luminosity += pg.calcVolume(serial_generate(CellEdgesGetter(tess,i)))*
  207.       calcEmissivity(sim.getAllCells()[static_cast<size_t>(i)].density,
  208.              sim.getAllCells()[static_cast<size_t>(i)].pressure);
  209.       time_luminosity_.push_back(std::pair<double,double>(sim.getTime(),total_luminosity));
  210.     }
  211.  
  212.     ~Bremsstrahlung(void)
  213.     {
  214.       ofstream f(fname_.c_str());
  215.       for(size_t i=0;i<time_luminosity_.size();++i)
  216.     f << time_luminosity_[i].first << " "
  217.       << time_luminosity_[i].second << endl;
  218.       f.close();
  219.     }
  220.  
  221.   private:
  222.  
  223.     double calcTemperature(double density, double pressure)
  224.     {
  225.       return particle_mass_*(pressure/density)/boltzmann_constant_;
  226.     }
  227.  
  228.     double calcEmissivity(double density, double pressure)
  229.     {
  230.       const double T = calcTemperature(density, pressure);
  231.       const double n = (density/particle_mass_)*cc_;
  232.       return coefficient_*sqrt(T)*pow(n,2);
  233.     }
  234.  
  235.     const string fname_;
  236.     const double boltzmann_constant_;
  237.     const double coefficient_;
  238.     const double particle_mass_;
  239.     const double cc_;
  240.     mutable vector<std::pair<double,double> > time_luminosity_;
  241.   };
  242.   */
  243.  
  244.   class HydrostaticPressure: public SpatialDistribution
  245.   {
  246.   public:
  247.  
  248.     HydrostaticPressure(double gm,
  249.             double r0,
  250.             double rho_0,
  251.             double omega_1,
  252.             double R_b,
  253.             double omega_2):
  254.       gm_(gm), r0_(r0), rho_0_(rho_0),
  255.       omega_1_(omega_1), R_b_(R_b), omega_2_(omega_2) {}
  256.  
  257.     double operator()(const Vector2D& r) const
  258.     {
  259.       if(abs(r)<R_b_)
  260.     return (gm_/r0_)*(rho_0_/(omega_1_+1))*pow(abs(r)/r0_,-omega_1_-1)-
  261.       (gm_/r0_)*(rho_0_/(omega_1_+1))*pow(R_b_/r0_,-omega_1_-1)+
  262.       (gm_/r0_)*(rho_0_/(omega_2_+1))*pow(R_b_/r0_,-omega_1_-1);
  263.       else
  264.     return (gm_/r0_)*(rho_0_/(omega_2_+1))*
  265.       pow(R_b_/r0_,-omega_1_-1)*
  266.       pow(abs(r)/R_b_,-omega_2_-1);
  267.     }
  268.  
  269.   private:
  270.     const double gm_;
  271.     const double r0_;
  272.     const double rho_0_;
  273.     const double omega_1_;
  274.     const double R_b_;
  275.     const double omega_2_;
  276.   };
  277.  
  278.   class BoundedRadialPowerLaw: public SpatialDistribution
  279.   {
  280.   public:
  281.  
  282.     BoundedRadialPowerLaw(const Vector2D& center,
  283.               double index,
  284.               double prefactor,
  285.               double lower_bound,
  286.               double upper_bound):
  287.       center_(center),
  288.       index_(index),
  289.       prefactor_(prefactor),
  290.       lower_bound_(lower_bound),
  291.       upper_bound_(upper_bound) {}
  292.  
  293.     double operator()(const Vector2D& r) const
  294.     {
  295.       const double radius = max(min(abs(r-center_),
  296.                     upper_bound_),
  297.                 lower_bound_);
  298.       return prefactor_*pow(radius,index_);
  299.     }
  300.  
  301.   private:
  302.     const Vector2D center_;
  303.     const double index_;
  304.     const double prefactor_;
  305.     const double lower_bound_;
  306.     const double upper_bound_;
  307.   };
  308.  
  309.   bool is_inside_rectangle(const Vector2D& point,
  310.                const Vector2D& lower_left,
  311.                const Vector2D& upper_right)
  312.   {
  313.     return ((point.x > lower_left.x) &&
  314.         (point.x < upper_right.x) &&
  315.         (point.y > lower_left.y) &&
  316.         (point.y < upper_right.y));
  317.   }
  318.  
  319.   vector<Vector2D> rectangle_clip(const vector<Vector2D>& grid,
  320.                   const Vector2D& lower_left,
  321.                   const Vector2D& upper_right)
  322.   {
  323.     vector<Vector2D> res;
  324.     for(size_t i=0, endp=grid.size();i<endp;++i){
  325.       const Vector2D& point = grid[i];
  326.       if(is_inside_rectangle(point,lower_left,upper_right))
  327.     res.push_back(point);    
  328.     }
  329.     return res;
  330.   }
  331.  
  332.   /*
  333.     vector<double> calc_radius_list(void)
  334.     {
  335.     const double rmin = 1e-4;
  336.     const double q = 1.01;
  337.     const size_t n = 200;
  338.     vector<double> res(n);
  339.     for(size_t i=0;i<n;++i)
  340.     res[i] = rmin*pow(q,i);
  341.     write_number(0,"finished_calc_radius_list.txt");
  342.     return res;
  343.     }
  344.   */
  345.  
  346.   /*
  347.     vector<Vector2D> create_grid(Vector2D const& lower_left,
  348.     Vector2D const& upper_right,
  349.     double dx2x)
  350.     {
  351.     vector<Vector2D> res;
  352.     for(double x = lower_left.x*(1+0.5*dx2x);
  353.     x<upper_right.x; x*=(1+dx2x)){
  354.     const double dx = x*dx2x;
  355.     for(double y=lower_left.y+dx/2;
  356.     y<upper_right.y; y += dx)
  357.     res.push_back(Vector2D(x,y));
  358.     }
  359.     return res;
  360.     }
  361.   */
  362.  
  363.   /*
  364.     vector<Vector2D> centered_hexagonal_grid(double r_min,
  365.     double r_max)
  366.     {
  367.     const vector<double> r_list = arange(0,r_max,r_min);
  368.     vector<Vector2D> res;
  369.     for(size_t i=0;i<r_list.size();++i){
  370.     const size_t angle_num = max<size_t>(6*i,1);
  371.     vector<double> angle_list(angle_num,0);
  372.     for(size_t j=0;j<angle_num;++j)
  373.     angle_list.at(j) = 2*M_PI*(double)j/(double)(angle_num);
  374.     for(size_t j=0;j<angle_num;++j)
  375.     res.push_back(r_list.at(i)*Vector2D(cos(angle_list.at(j)),
  376.     sin(angle_list.at(j))));
  377.     }
  378.     return res;
  379.     }
  380.   */
  381.  
  382.   vector<Vector2D> centered_logarithmic_spiral(double r_min,
  383.                            double r_max,
  384.                            double alpha,
  385.                            const Vector2D& center)
  386.   {
  387.     const double theta_max = log(r_max/r_min)/alpha;
  388.     const vector<double> theta_list =
  389.       arange(0,theta_max,2*M_PI*alpha/(1-0.5*alpha));
  390.  
  391.     vector<double> r_list(theta_list.size(),0);
  392.     for(size_t i=0;i<r_list.size();++i)
  393.       r_list.at(i) = r_min*exp(alpha*theta_list.at(i));
  394.  
  395.     vector<Vector2D> res(r_list.size());
  396.     for(size_t i=0;i<res.size();++i)
  397.       res[i] = center+r_list[i]*Vector2D(cos(theta_list.at(i)),
  398.                      sin(theta_list.at(i)));
  399.     return res;
  400.   }
  401.  
  402.   /*
  403.     vector<Vector2D> complete_grid(double r_inner,
  404.     double r_outer,
  405.     double alpha)
  406.     {
  407.     const vector<Vector2D> inner =
  408.     centered_hexagonal_grid(r_inner*alpha*2*M_PI,
  409.     r_inner);
  410.     const vector<Vector2D> outer =
  411.     centered_logarithmic_spiral(r_inner,
  412.     r_outer,
  413.     alpha);
  414.     return join(inner, outer);
  415.     }
  416.   */
  417.  
  418.   template<class T> class VectorInitializer
  419.   {
  420.   public:
  421.  
  422.     VectorInitializer(const T& t):
  423.       buf_(1,t) {}
  424.  
  425.     VectorInitializer& operator()(const T& t)
  426.     {
  427.       buf_.push_back(t);
  428.       return *this;
  429.     }
  430.  
  431.     vector<T> operator()(void)
  432.     {
  433.       return buf_;
  434.     }
  435.  
  436.   private:
  437.     vector<T> buf_;
  438.   };
  439.  
  440.   vector<ComputationalCell> calc_init_cond(const Tessellation& tess,
  441.                        const Constants& c)
  442.   {
  443.     vector<ComputationalCell> res(static_cast<size_t>(tess.GetPointNo()));
  444.     for(size_t i=0;i<res.size();++i){
  445.       const Vector2D r = tess.GetMeshPoint(static_cast<int>(i));
  446.       res[i].density = Piecewise(Circle(Vector2D(0,-c.offset),c.supernova_radius),
  447.                  Uniform2D(c.supernova_radius),
  448.                  Piecewise(Circle(Vector2D(0,0), c.R_b),
  449.                        BoundedRadialPowerLaw(Vector2D(0,0),
  450.                                  -c.omega_in,
  451.                                  c.inner_density_prefactor,
  452.                                  1e-6, 10),
  453.                        BoundedRadialPowerLaw(Vector2D(0,0),
  454.                                  -c.omega_out,
  455.                                  c.outer_density_prefactor,
  456.                                  1e-6,10)))(r);
  457.       res[i].pressure = Piecewise(Circle(Vector2D(0,-c.offset),c.supernova_radius),
  458.                   Uniform2D(c.supernova_pressure),
  459.                   HydrostaticPressure(c.gravitation_constant*c.black_hole_mass,
  460.                               c.R_0,
  461.                               c.rho_0,
  462.                               c.omega_in,
  463.                               c.R_b,
  464.                               c.omega_out))(r);
  465.       res[i].velocity = Vector2D(0,0);
  466.       res[i].tracers["ejecta"] = Piecewise
  467.     (Circle(Vector2D(0,-c.offset),c.supernova_radius),
  468.      Uniform2D(1), Uniform2D(0))(r);
  469.       res[i].stickers["dummy"] = Circle(Vector2D(0,0),c.supernova_radius)(r);
  470.     }
  471.     return res;
  472.   }
  473.  
  474.   class SinkFlux: public FluxCalculator
  475.   {
  476.   public:
  477.  
  478.     SinkFlux(const RiemannSolver& rs):
  479.       rs_(rs) {}
  480.  
  481.     vector<Extensive> operator()
  482.     (const Tessellation& tess,
  483.      const vector<Vector2D>& point_velocities,
  484.      const vector<ComputationalCell>& cells,
  485.      const EquationOfState& eos,
  486.      const double /*time*/,
  487.      const double /*dt*/) const
  488.     {
  489.       vector<Extensive> res(tess.getAllEdges().size());
  490.       for(size_t i=0;i<tess.getAllEdges().size();++i){
  491.     const Conserved hydro_flux =
  492.       calcHydroFlux(tess, point_velocities,
  493.             cells, eos, i);
  494.     res[i].mass = hydro_flux.Mass;
  495.     res[i].momentum = hydro_flux.Momentum;
  496.     res[i].energy = hydro_flux.Energy;
  497.     for(std::map<std::string,double>::const_iterator it =
  498.           cells.front().tracers.begin();
  499.         it!=cells.front().tracers.end();++it)
  500.       res[i].tracers[it->first] = (it->second)*hydro_flux.Mass;
  501.       }
  502.       return res;
  503.     }
  504.  
  505.   private:
  506.     const RiemannSolver& rs_;
  507.  
  508.     const Conserved calcHydroFlux
  509.     (const Tessellation& tess,
  510.      const vector<Vector2D>& point_velocities,
  511.      const vector<ComputationalCell>& cells,
  512.      const EquationOfState& eos,
  513.      const size_t i) const
  514.     {
  515.       const Edge& edge = tess.GetEdge(static_cast<int>(i));
  516.       const std::pair<bool,bool> flags
  517.     (edge.neighbors.first>=0 && edge.neighbors.first<tess.GetPointNo(),
  518.      edge.neighbors.second>=0 && edge.neighbors.second<tess.GetPointNo());
  519.       assert(flags.first || flags.second);
  520.       if(!flags.first){
  521.     const size_t right_index =
  522.       static_cast<size_t>(edge.neighbors.second);
  523.     const ComputationalCell& right_cell = cells[right_index];
  524.     if(right_cell.stickers.find("dummy")->second)
  525.       return Conserved();
  526.     const Vector2D p = Parallel(edge);
  527.     const Primitive right = convert_to_primitive(right_cell,eos);
  528.     const Primitive left = reflect(right,p);
  529.     const Vector2D n = remove_parallel_component
  530.       (tess.GetMeshPoint(edge.neighbors.second) -
  531.        edge.vertices.first, p);
  532.     return rotate_solve_rotate_back
  533.       (rs_, left, right, 0, n, p);
  534.       }
  535.       if(!flags.second){
  536.     const size_t left_index =
  537.       static_cast<size_t>(edge.neighbors.first);
  538.     const ComputationalCell& left_cell = cells[left_index];
  539.     if(left_cell.stickers.find("dummy")->second)
  540.       return Conserved();
  541.     const Primitive left = convert_to_primitive(left_cell, eos);
  542.     const Vector2D p = Parallel(edge);
  543.     const Primitive right = reflect(left,p);
  544.     const Vector2D n = remove_parallel_component
  545.       (edge.vertices.second -
  546.        tess.GetMeshPoint(edge.neighbors.first), p);
  547.     return rotate_solve_rotate_back
  548.       (rs_, left, right, 0, n, p);
  549.       }
  550.       const size_t left_index =
  551.     static_cast<size_t>(edge.neighbors.first);
  552.       const size_t right_index =
  553.     static_cast<size_t>(edge.neighbors.second);
  554.       const ComputationalCell& left_cell = cells[left_index];
  555.       const ComputationalCell& right_cell = cells[right_index];
  556.       if(left_cell.stickers.find("dummy")->second &&
  557.      right_cell.stickers.find("dummy")->second)
  558.     return Conserved();
  559.       const Vector2D p = Parallel(edge);
  560.       const Vector2D n =
  561.     tess.GetMeshPoint(edge.neighbors.second) -
  562.     tess.GetMeshPoint(edge.neighbors.first);
  563.       const double velocity = Projection
  564.     (tess.CalcFaceVelocity
  565.      (point_velocities[left_index],
  566.       point_velocities[right_index],
  567.       tess.GetCellCM(edge.neighbors.first),
  568.       tess.GetCellCM(edge.neighbors.second),
  569.       calc_centroid(edge)),n);             
  570.       if(left_cell.stickers.find("dummy")->second){
  571.     const Primitive right =
  572.       convert_to_primitive(right_cell, eos);
  573.     const Primitive left =
  574.       ScalarProd(n,right.Velocity) < 0 ? right :
  575.       reflect(right,p);
  576.     return rotate_solve_rotate_back
  577.                      (rs_,left,right,velocity,n,p);
  578.       }
  579.       if(right_cell.stickers.find("dummy")->second){
  580.     const Primitive left =
  581.       convert_to_primitive(left_cell, eos);
  582.     const Primitive right =
  583.       ScalarProd(n,left.Velocity)>0 ?
  584.       left : reflect(left,p);
  585.     return rotate_solve_rotate_back
  586.       (rs_,left,right,velocity,n,p);
  587.       }
  588.       const Primitive left =
  589.     convert_to_primitive(left_cell, eos);
  590.       const Primitive right =
  591.     convert_to_primitive(right_cell, eos);
  592.       return rotate_solve_rotate_back
  593.     (rs_,left,right,velocity,n,p);
  594.     }
  595.   };
  596.  
  597.   class TimeStepCalculator: public LazyList<double>
  598.   {
  599.   public:
  600.  
  601.     TimeStepCalculator(const Tessellation& tess,
  602.                const vector<ComputationalCell>& cells,
  603.                const EquationOfState& eos,
  604.                const vector<Vector2D>& point_velocities):
  605.       tess_(tess), cells_(cells),
  606.       point_velocities_(point_velocities), eos_(eos) {}
  607.  
  608.     size_t size(void) const
  609.     {
  610.       return cells_.size();
  611.     }
  612.  
  613.     double operator[](size_t i) const
  614.     {
  615.       return tess_.GetWidth(static_cast<int>(i))/
  616.     (eos_.dp2c(cells_[i].density, cells_[i].pressure)+
  617.      abs(cells_[i].velocity)+
  618.      abs(point_velocities_[i]));
  619.     }
  620.  
  621.   private:
  622.     const Tessellation& tess_;
  623.     const vector<ComputationalCell>& cells_;
  624.     const vector<Vector2D>& point_velocities_;
  625.     const EquationOfState& eos_;
  626.   };
  627.  
  628.   class LogCFL: public TimeStepFunction
  629.   {
  630.   public:
  631.  
  632.     LogCFL(double cfl, const string& fname):
  633.       cfl_(cfl), fname_(fname) {}
  634.  
  635.     double operator()
  636.     (const Tessellation& tess,
  637.      const vector<ComputationalCell>& cells,
  638.      const EquationOfState& eos,
  639.      const vector<Vector2D>& point_velocities,
  640.      const double /*time*/) const
  641.     {
  642.       const TimeStepCalculator tsc(tess,cells,eos,point_velocities);
  643.       double res = tsc[0];
  644.       size_t argmin = 0;
  645.       for(size_t i=1;i<tsc.size();++i){
  646.     const double candidate = tsc[i];
  647.     if(candidate<res && !cells[i].stickers.find("dummy")->second){
  648.       res = candidate;
  649.       argmin = i;
  650.     }  
  651.       }
  652.       ofstream f(fname_.c_str());
  653.       f << argmin << endl;
  654.       f << tess.GetMeshPoint(static_cast<int>(argmin)).x << ", ";
  655.       f << tess.GetMeshPoint(static_cast<int>(argmin)).y << endl;
  656.       f << tess.GetWidth(static_cast<int>(argmin)) << endl;
  657.       f << eos.dp2c(cells[argmin].density, cells[argmin].pressure) << endl;
  658.       f << cells[argmin].velocity.x << ", ";
  659.       f << cells[argmin].velocity.y << endl;
  660.       f << point_velocities[argmin].x << ", ";
  661.       f << point_velocities[argmin].y << endl;
  662.       f.close();
  663.       return cfl_*res;
  664.     }
  665.  
  666.   private:
  667.     const double cfl_;
  668.     const string fname_;
  669.   };
  670.  
  671.   class EntropyFix: public CellUpdater
  672.   {
  673.   public:
  674.  
  675.     EntropyFix(const double thres=1e-6):
  676.       thres_(thres) {}
  677.  
  678.     vector<ComputationalCell> operator()
  679.     (const Tessellation& tess,
  680.      const PhysicalGeometry& pg,
  681.      const EquationOfState& eos,
  682.      const vector<Extensive>& extensives,
  683.      const vector<ComputationalCell>& old,
  684.      const CacheData& /*cd*/) const
  685.     {
  686.       vector<ComputationalCell> res = old;
  687.       for(size_t i=0;i<extensives.size();++i){
  688.     if(old[i].stickers.find("dummy")->second)
  689.       continue;
  690.     const double volume = pg.calcVolume
  691.       (serial_generate(CellEdgesGetter(tess,static_cast<int>(i))));
  692.     res[i].density = extensives[i].mass/volume;
  693.     res[i].velocity = extensives[i].momentum / extensives[i].mass;
  694.     const double total_energy = extensives[i].energy/extensives[i].mass;
  695.     const double kinetic_energy =
  696.       0.5*ScalarProd(res[i].velocity, res[i].velocity);
  697.     const double energy =
  698.       total_energy - kinetic_energy;
  699.     for(std::map<std::string,double>::const_iterator it =
  700.           extensives[i].tracers.begin();
  701.         it!=extensives[i].tracers.end();++it)
  702.       res[i].tracers[it->first] = it->second/extensives[i].mass;
  703.     if(energy>thres_*kinetic_energy){
  704.       res[i].pressure = eos.de2p(res[i].density, energy);
  705.       res[i].tracers["entropy"] = eos.dp2s
  706.         (res[i].density, res[i].pressure);
  707.     }
  708.     else{
  709.       assert(res[i].tracers.count("entropy")>0);
  710.       res[i].pressure = eos.sd2p(res[i].tracers["entropy"],
  711.                      res[i].density);
  712.     }
  713.       }
  714.       return res;
  715.     }
  716.  
  717.   private:
  718.     const double thres_;
  719.   };
  720.  
  721.   class EdgeLengthCalculator: public LazyList<double>
  722.   {
  723.   public:
  724.  
  725.     EdgeLengthCalculator(const Tessellation& tess,
  726.              const PhysicalGeometry& pg):
  727.       tess_(tess), pg_(pg) {}
  728.  
  729.     size_t size(void) const
  730.     {
  731.       return tess_.getAllEdges().size();
  732.     }
  733.  
  734.     double operator[](size_t i) const
  735.     {
  736.       return pg_.calcArea(tess_.getAllEdges()[i]);
  737.     }
  738.  
  739.   private:
  740.     const Tessellation& tess_;
  741.     const PhysicalGeometry& pg_;
  742.   };
  743.  
  744.   bool bracketed(double low, double arg, double high)
  745.   {
  746.     return arg>=low and high>arg;
  747.   }
  748.  
  749.   class LazyExtensiveUpdater: public ExtensiveUpdater
  750.   {
  751.   public:
  752.  
  753.     LazyExtensiveUpdater(const Tessellation& tess,
  754.              const PhysicalGeometry& pg):
  755.       lengths_(serial_generate(EdgeLengthCalculator(tess,pg))) {}
  756.  
  757.     void operator()
  758.       (const vector<Extensive>& fluxes,
  759.        const PhysicalGeometry& /*pg*/,
  760.        const Tessellation& tess,
  761.        const double dt,
  762.        const CacheData& /*cd*/,
  763.        vector<Extensive>& extensives) const
  764.     {
  765.       const vector<Edge>& edge_list = tess.getAllEdges();
  766.       for(size_t i=0;i<edge_list.size();++i){
  767.     const Edge& edge = edge_list[i];
  768.     const Extensive delta = dt*lengths_[i]*fluxes[i];
  769.     if(bracketed(0,edge.neighbors.first,tess.GetPointNo()))
  770.       extensives[static_cast<size_t>(edge.neighbors.first)] -=
  771.         delta;
  772.     if(bracketed(0,edge.neighbors.second,tess.GetPointNo()))
  773.       extensives[static_cast<size_t>(edge.neighbors.second)] +=
  774.         delta;
  775.       }
  776. }
  777.  
  778.   private:
  779.     const vector<double> lengths_;
  780.   };
  781. }
  782.  
  783. class SimData
  784. {
  785.  
  786. public:
  787.  
  788.   SimData(const Constants& c):
  789.     pg_(Vector2D(0,0), Vector2D(0,1)),
  790.     outer_(c.lower_left, c.upper_right),
  791.     init_points_(rectangle_clip
  792.          (centered_logarithmic_spiral(0.001,
  793.                           abs(c.upper_right-c.lower_left),
  794.                           0.005*2,
  795.                           Vector2D(-0.1*c.offset,0)),
  796.           c.lower_left, c.upper_right)),
  797.     tess_(init_points_, outer_),
  798.     eos_(c.adiabatic_index),
  799.     rs_(),
  800.     //    raw_point_motion_(),
  801.     //    point_motion_(raw_point_motion_,eos_),
  802.     alt_point_motion_(),
  803.     gravity_acc_(c.gravitation_constant*c.black_hole_mass,
  804.          0.01*c.parsec,
  805.          c.parsec*Vector2D(-0.01*c.offset,0)),
  806.     gravity_force_(gravity_acc_),
  807.     geom_force_(pg_.getAxis()),
  808.     force_(VectorInitializer<SourceTerm*>(&gravity_force_)
  809.        (&geom_force_)()),
  810.     tsf_(0.3, "dt_log.txt"),
  811.     fc_(rs_),
  812.     eu_(tess_,pg_),
  813.     cu_(),
  814.     sim_(tess_,
  815.      outer_,
  816.      pg_,
  817.      calc_init_cond(tess_,c),
  818.      eos_,
  819.      alt_point_motion_,
  820.      force_,
  821.      tsf_,
  822.      fc_,
  823.      eu_,
  824.      cu_) {}
  825.  
  826.   hdsim& getSim(void)
  827.   {
  828.     return sim_;
  829.   }
  830.  
  831. private:
  832.   const CylindricalSymmetry pg_;
  833.   const SquareBox outer_;
  834.   const vector<Vector2D> init_points_;
  835.   StaticVoronoiMesh tess_;
  836.   const IdealGas eos_;
  837.   const Hllc rs_;
  838.   //  Lagrangian raw_point_motion_;
  839.   //  RoundCells point_motion_;
  840.   Eulerian alt_point_motion_;
  841.   CenterGravity gravity_acc_;
  842.   ConservativeForce gravity_force_;
  843.   CylindricalComplementary geom_force_;
  844.   SeveralSources force_;
  845.   //  const SimpleCFL tsf_;
  846.   const LogCFL tsf_;
  847.   const SinkFlux fc_;
  848.   //const SimpleCellUpdater cu_;
  849.   const LazyExtensiveUpdater eu_;
  850.   const EntropyFix cu_;
  851.   hdsim sim_;
  852. };
  853.  
  854. class CustomDiagnostic
  855. {
  856. public:
  857.  
  858.   CustomDiagnostic(double dt,
  859.            double t_start):
  860.     dt_(dt),
  861.     t_next_(t_start),
  862.     counter_(0) {}
  863.  
  864.   void operator()(const hdsim& sim)
  865.   {
  866.     if(sim.getTime()>t_next_){
  867.       write_snapshot_to_hdf5(sim, "snapshot_"+int2str(counter_)+".h5");
  868.  
  869.       t_next_ += dt_;
  870.       ++counter_;
  871.     }
  872.   }
  873.  
  874. private:
  875.   const double dt_;
  876.   double t_next_;
  877.   int counter_;
  878. };
  879.  
  880. namespace {
  881.   class MultipleDiagnostics: public DiagnosticFunction
  882.   {
  883.   public:
  884.  
  885.     MultipleDiagnostics(const vector<DiagnosticFunction*>& diag_list):
  886.       diag_list_(diag_list) {}
  887.  
  888.     void operator()(const hdsim& sim)
  889.     {
  890.       BOOST_FOREACH(DiagnosticFunction* df, diag_list_)
  891.     {
  892.       (*df)(sim);
  893.     }
  894.     }
  895.  
  896.   private:
  897.     const vector<DiagnosticFunction*> diag_list_;
  898.   };
  899. }
  900.  
  901. namespace {
  902.  
  903.   class WriteCycle: public DiagnosticFunction
  904.   {
  905.   public:
  906.  
  907.     WriteCycle(const string& fname):
  908.       fname_(fname) {}
  909.  
  910.     void operator()(const hdsim& sim)
  911.     {
  912.       write_number(sim.getCycle(),fname_);
  913.     }
  914.  
  915.   private:
  916.     const string fname_;
  917.   };
  918.  
  919.   void my_main_loop(hdsim& sim, const Constants& c)
  920.   {
  921.     //    const double tf = 400*c.year;
  922.     //    SafeTimeTermination term_cond_raw(tf,1e6);
  923.     SafeTimeTermination term_cond_raw(1*c.year,1e6);
  924.     ConsecutiveSnapshots diag1(new ConstantTimeInterval(1*c.year),
  925.                    new Rubric("snapshot_",".h5"));
  926.     WriteTime diag2("time.txt");
  927.     WriteConserved diag4("conserved.txt");
  928.     //Bremsstrahlung diag5("luminosity_history.txt",c);
  929.     WriteCycle diag6("cycle.txt");
  930.     vector<DiagnosticFunction*> diag_list;
  931.     diag_list.push_back(&diag1);
  932.     diag_list.push_back(&diag2);
  933.     //    diag_list.push_back(&diag3);
  934.     diag_list.push_back(&diag4);
  935.     //    diag_list.push_back(&diag5);
  936.     diag_list.push_back(&diag6);
  937.     MultipleDiagnostics diag(diag_list);
  938.  
  939.     main_loop(sim,
  940.           term_cond_raw,
  941.           &hdsim::TimeAdvance,
  942.           &diag);
  943.   }
  944. }
  945.  
  946. namespace {
  947.   void report_error(UniversalError const& eo)
  948.   {
  949.     cout << eo.GetErrorMessage() << endl;
  950.     cout.precision(14);
  951.     for(size_t i=0;i<eo.GetFields().size();++i)
  952.       cout << eo.GetFields()[i] << " = "
  953.        << eo.GetValues()[i] << endl;
  954.   }
  955. }
  956.  
  957. int main(void)
  958. {
  959.   feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
  960.   //  MPI_Init(NULL, NULL);
  961.  
  962.   try{
  963.  
  964.     Constants c;
  965.  
  966.     SimData sim_data(c);
  967.     hdsim& sim = sim_data.getSim();
  968.  
  969.     write_snapshot_to_hdf5(sim,
  970.                "initial.h5");
  971.  
  972.     my_main_loop(sim,c);
  973.  
  974.     write_snapshot_to_hdf5(sim,
  975.                "final.h5");
  976.  
  977.   }
  978.   catch(const UniversalError& eo){
  979.     report_error(eo);
  980.     throw;
  981.   }
  982.  
  983.   return 0;
  984. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement