Advertisement
bolverk

supernova near 1e7 solar mass black hole

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