#!/usr/bin/env ruby
# This example solves Lane-Emden equation to calculate white dwarf
# structure, using Chandrasekhar's model, as a polytrope gas sphere
# of self-gravitating body supported by eletron degeneration pressure.
require("rbgsl")
include Math
include GSL::CONST::CGSM
include GSL::Odeiv
# Degenerated electron/neutron gas
# Reference: "Black holes, white dwarfs, and neutron stars"
# S.L. Shapiro & S.A. Teukolsky, Willey, 1983
module Degenerate
hbar = PLANCKS_CONSTANT_HBAR # Planck's constant
me = MASS_ELECTRON # Electron mass
mn = MASS_NEUTRON # Neutron mass
mu = UNIFIED_ATOMIC_MASS
c = SPEED_OF_LIGHT
ELambda = hbar/me/c # Compton length of electron
NLambda = hbar/mn/c
MeC2 = me*c*c # Electron rest mass energy
MnC2 = mn*c*c
Factor_xe = GSL::pow(3.0*PI*PI/mu, 1.0/3.0)*ELambda
Factor_xn = GSL::pow(3.0*PI*PI/mu, 1.0/3.0)*NLambda
# See Shapiro&Teukolsky Chapter 2
def phi(x)
tmp = sqrt(1.0 + x*x)
(x*tmp*(2.0*x*x/3.0 - 1.0) + log(x + tmp))/8/PI/PI
end
def chi(x)
tmp = sqrt(1.0 + x*x)
(x*tmp*(1.0 + 2*x*x) - log(x + tmp))/8/PI/PI
end
def xe_rho_mue(rho, mue)
Factor_xe*GSL::pow(rho/mue, 1.0/3.0)
end
def xn_rho(rho)
Factor_xn*GSL::pow(rho, 1.0/3.0)
end
end
# Polytrope gas sphere
module Polytrope
# Lane-Emden equation
# n: polytrope index
EmdenEq = Proc.new { |x, y, dydx, n|
dydx[0] = y[1]
dydx[1] = -GSL::pow(y[0], n) - 2.0/x*y[1]
}
def emden_xi(n)
dim = 2
y = GSL::Vector[1.0, 0.0]
dydx = GSL::Vector.alloc(dim)
solver = Solver.alloc(Step::RKF45, [1e-6, 0], EmdenEq, dim)
solver.set_params(n)
solver.reset
vx = GSL::Vector.alloc(10000)
vy = GSL::Vector.alloc(10000)
vdy = GSL::Vector.alloc(10000)
x = 0.0001
xend = 10.0
h = 1e-6
file = File.open("polytrope.dat", "w")
i = 0
while x < xend
x, h, status = solver.apply(x, xend, h, y)
break if GSL::isnan?(y[0])
break if GSL::isnan?(y[1])
vx[i] = x
vy[i] = y[0]
vdy[i] = y[1]
file.printf("%e %e %e %e\n", x, y[0], y[1], GSL::pow_3(y[0]))
i += 1
break if status != GSL::SUCCESS
break if y[0] <= -0.1
end
file.close
# p vx.size
# p i
vx2 = vx.subvector(0, i)
vy2 = vy.subvector(0, i)
vdy2 = vdy.subvector(0, i)
spline = GSL::Spline.alloc(GSL::Interp::AKIMA, i)
spline.init(vy2.reverse, vx2.reverse)
# Find star surface:
# Star sufrace is defined as the zero point of density structure function
x1 = spline.eval(0.0)
spline.init(vx2, vdy2)
yx2 = spline.eval(x1).abs
return [x1, yx2*x1*x1]
end
end
# Chandrasekhar white dwarf model:
# * Polytrope gas sphere
# * Support its self gravity by electron degeneration pressure
class WhiteDwarf
include Degenerate
include Polytrope
G = GRAVITATIONAL_CONSTANT
@@x1 = nil
@@x12 = nil
def initialize(n, rhoc, mue)
@n = n
@gam = 1.0 + 1.0/n
@rhoc = rhoc
@mue = mue
x = xe_rho_mue(@rhoc, mue)
phix = phi(x)
@K = MeC2*phix/GSL::pow_3(ELambda)/GSL::pow(@rhoc, @gam)
@a = sqrt((@n + 1)*@K*GSL::pow(@rhoc, 1.0/@n - 1.0)/4/PI/G)
if !@@x1
@@x1, @@x12 = emden_xi(@n)
end
@Pc = MeC2*phix/GSL::pow_3(ELambda)*phix # Electron Fermi pressure
@radius = @a*@@x1 # White dwarf radius
@mass = 4.0*PI*GSL::pow_3(@a)*@rhoc*@@x12 # White dwarf mass
end
attr_accessor :radius
attr_accessor :mass
attr_accessor :rhoc # Central density
attr_accessor :Pc # Central pressure
attr_accessor :gam # Adiabatic index
attr_accessor :n # Polytrope index
attr_accessor :mue # Mean eletron number per barion
attr_accessor :K # Normalization constant
attr_accessor :a
end
file = File.open("whitedwarf.dat", "w")
rho = 1e6 # central density
while rho < 1e11
wd = WhiteDwarf.new(3, rho, 2)
file.printf("%e %e %e %e\n", rho, wd.Pc, wd.radius/1000/100, wd.mass/SOLAR_MASS)
rho *= 1.2
end
file.close
system("gnuplot -persist whitedwarf.gp")
File.delete("polytrope.dat")
File.delete("whitedwarf.dat")
syntax highlighted by Code2HTML, v. 0.9.1