def setUp(self):
     self.cfg = cfg
     self.cfg.NZ = 1
     self.cfg.IEOS = 0
     self.ideal = CLIdeal(self.cfg)
     self.ctx = self.ideal.ctx
     self.queue = self.ideal.queue
Beispiel #2
0
def ideal_main():
    '''set default platform and device in opencl'''
    print('start ...')
    t0 = time()
    from config import cfg
    from ideal import CLIdeal
    cfg.NX = 201
    cfg.NY = 201
    cfg.NZ = 61

    cfg.DT = 0.02
    cfg.DX = 0.16
    cfg.DY = 0.16
    cfg.IEOS = 2
    cfg.ntskip = 60

    cfg.TAU0 = 0.2

    cfg.ETAOS = 0.08

    ideal = CLIdeal(cfg)
    #fname_partons = '/data01/hyihp/pang/GammaJet/AuAu200_0_80/P1.txt'
    fname_partons = '/u/lpang/P10.txt'

    Smearing(cfg, ideal.ctx, ideal.queue, ideal.compile_options,
            ideal.d_ev[1], fname_partons, ideal.eos_table)

    ideal.evolve(max_loops=2400)
    t1 = time()
    print('finished. Total time: {dtime}'.format(dtime = t1-t0))
Beispiel #3
0
def glueball(Tmax = 0.6, outdir = '../results/event0', eos_type='pure_gauge'):
    print('start ...')
    t0 = time()
    if not os.path.exists(outdir):
        os.mkdir(outdir)

    cfg.eos_type = eos_type 
    eos = Eos(cfg.eos_type)
    # update the configuration
    #cfg.Edmax = eos.f_ed(Tmax)
    #cfg.Edmax = 166.0
    cfg.Edmax = 55.0

    cfg.fPathOut = outdir

    cfg.NX = 501
    cfg.NY = 501
    cfg.NZ = 1
    cfg.DT = 0.01
    cfg.DX = 0.08
    cfg.DY = 0.08

    #cfg.NumOfNucleons = 208
    #cfg.Ra = 6.62
    #cfg.Eta = 0.546
    #cfg.Si0 = 6.4

    cfg.NumOfNucleons = 197
    cfg.Ra = 6.4
    cfg.Eta = 0.546
    cfg.Si0 = 4.0

    cfg.TAU0 = 0.4
    cfg.ImpactParameter = 7.74

    #cfg.ImpactParameter = 0.0
    cfg.ETAOS = 0.0

    cfg.save_to_hdf5 = False

    if eos_type == 'pure_gauge':
        cfg.TFRZ = 0.2

    #cfg.Edmax = 600.0
    #cfg.Hwn = 1.0
    cfg.Hwn = 0.95
    write_config(cfg)

    ideal = CLIdeal(cfg, gpu_id=2)
    from glauber import Glauber
    Glauber(cfg, ideal.ctx, ideal.queue, ideal.compile_options, ideal.d_ev[1])

    ideal.evolve(max_loops=3000, save_hypersf=False, to_maxloop=True)
    t1 = time()
    print('finished. Total time: {dtime}'.format(dtime = t1-t0 ))

    from subprocess import call
    call(['python', './spec.py', cfg.fPathOut])
Beispiel #4
0
 def setUp(self):
     self.cfg = cfg
     self.cfg.NX = 1
     self.cfg.NY = 1
     self.cfg.NZ = 401
     self.cfg.DT = 0.005
     self.cfg.DZ = 0.075
     self.cfg.IEOS = 0
     self.cfg.ntskip = 100
     self.cfg.nzskip = 4
     self.ideal = CLIdeal(self.cfg)
     self.ctx = self.ideal.ctx
     self.queue = self.ideal.queue
Beispiel #5
0
def eB(eos_type='EOSL', sigma=5.8):
    '''sigma: electric conductivity'''
    if eos_type == 'EOSI':
        cfg.IEOS = 0
    else:
        cfg.IEOS = 1

    fout = '%s_figs_BW_sig%s'%(eos_type, sigma)
    fout = fout.replace('\.', 'p')

    if not os.path.exists(fout):
        os.mkdir(fout)
    cfg.NX = 401
    cfg.NY = 401
    cfg.NZ = 1

    cfg.DT = 0.005
    cfg.DX = 0.08
    cfg.DY = 0.08
    cfg.DZ = 0.08
    cfg.ntskip = 8

    cfg.ImpactParameter = 7.8
    cfg.Edmax = 55.0
    cfg.TAU0 = 0.4
    cfg.ETAOS = 0.08
    cfg.fPathOut = fout

    write_config(cfg)

    ideal = CLIdeal(cfg, gpu_id=2)

    from glauber import Glauber
    ini = Glauber(cfg, ideal.ctx, ideal.queue, ideal.gpu_defines, ideal.d_ev[1])

    ideal.evolve(max_loops=2000, to_maxloop=True, save_bulk=False,
                plot_bulk=True, save_hypersf=False)

    bulk = ideal.bulkinfo

    eB_field = MagneticField(eB0=0.1, sigx=2.4, sigy=4.8, hydro_cfg=cfg, bulkinfo=bulk, sigma=sigma)

    eB_field.evolve(nstep=240)

    eB_field.plot()
Beispiel #6
0
class TestBjorken(unittest.TestCase):
    def setUp(self):
        self.cfg = cfg
        self.cfg.NX = 1
        self.cfg.NY = 1
        self.cfg.NZ = 1
        self.cfg.IEOS = 0
        self.ideal = CLIdeal(self.cfg)
        self.ctx = self.ideal.ctx
        self.queue = self.ideal.queue

    def test_bjorken(self):
        ''' initialize with uniform energy density in (tau, x, y, eta) coordinates
        to test the Bjorken expansion:
           eps/eps0 = (tau/tau0)**(-4.0/3.0)
        '''

        kernel_src = """
        # include "real_type.h"
        __kernel void init_ev(global real4 * d_ev1,
                   const int size) {
          int gid = (int) get_global_id(0);
          if ( gid < size ) {
             d_ev1[gid] = (real4)(30.0f, 0.0f, 0.0f, 0.0f);
          }
        }
        """
        cwd, cwf = os.path.split(__file__)

        compile_options = ['-I %s' % os.path.join(cwd, '..', 'kernel')]
        compile_options.append('-D USE_SINGLE_PRECISION')
        prg = cl.Program(self.ctx, kernel_src).build(compile_options)
        prg.init_ev(self.queue, (self.ideal.size, ), None, self.ideal.d_ev[1],
                    np.int32(self.ideal.size)).wait()

        self.ideal.evolve(max_loops=200, save_bulk=False, save_hypersf=False)

        history = np.array(self.ideal.history)
        tau, edmax = history[:, 0], history[:, 1]
        a = (tau / tau[0])**(-4.0 / 3.0)
        b = edmax / edmax[0]
        np.testing.assert_almost_equal(a, b, 3)
Beispiel #7
0
def ppcollision(eostype='SU3', outdir = '../results/event0'):
    print('start ...')
    t0 = time()
    if not os.path.exists(outdir):
        os.mkdir(outdir)

    if eostype == 'SU3':
        cfg.eos_type = 'pure_gauge'
    elif eostype == 'QCD':
        cfg.eos_type = 'lattice_wb'
    elif eostype == 'EOSI':
        cfg.eos_type == 'ideal_gas'

    eos = Eos(cfg.eos_type)
    # update the configuration
    #cfg.Edmax = eos.f_ed(Tmax)
    cfg.Edmax = 50.0

    cfg.fPathOut = outdir

    cfg.NX = 301
    cfg.NY = 301
    cfg.NZ = 1
    cfg.DT = 0.01
    cfg.DX = 0.08
    cfg.DY = 0.08
    cfg.ntskip = 50
    cfg.NumOfNucleons = 1
    cfg.Ra = 0.8
    cfg.Eta = 0.6
    cfg.Si0 = 6.4
    cfg.TAU0 = 0.6
    cfg.ImpactParameter = 0.0
    cfg.ETAOS = 0.0
    cfg.SQRTS = 2760

    #cfg.Edmax = 600.0
    cfg.Hwn = 1.0
    write_config(cfg)

    xmax = cfg.NX/2*cfg.DX
    ymax = cfg.NY/2*cfg.DY
    x = np.linspace(-xmax, xmax, cfg.NX)
    y = np.linspace(-ymax, ymax, cfg.NY)
    x, y = np.meshgrid(x, y)
    ed = cfg.Edmax * pp_energydensity(x, y, b=cfg.ImpactParameter)
    #plt.imshow(ed)
    #plt.show()

    ideal = CLIdeal(cfg, gpu_id=1)
    edv = np.zeros((ideal.size, 4), ideal.cfg.real)
    print(edv.shape)
    edv[:, 0] = ed.T.flatten()
    ideal.load_ini(edv)

    ideal.evolve(max_loops=1000, save_hypersf=False, to_maxloop=True)
    t1 = time()
    print('finished. Total time: {dtime}'.format(dtime = t1-t0 ))
Beispiel #8
0
import os, sys

cwd, cwf = os.path.split(__file__)
sys.path.append(os.path.join(cwd, '../pyvisc'))

from ideal import CLIdeal
from config import cfg
import pyopencl as cl

cfg.IEOS = 0

cfg.NX = 1
cfg.NY = 1
cfg.NZ = 1

ideal = CLIdeal(cfg)

from glauber import Glauber

ini = Glauber(cfg, ideal.ctx, ideal.queue, ideal.gpu_defines, ideal.d_ev[1])

ideal.evolve(max_loops=100,
             save_bulk=True,
             to_maxloop=True,
             save_hypersf=False)

cl.enqueue_copy(ideal.queue, ideal.h_ev1, ideal.d_ev[1]).wait()

#### start the hydro with -DT
cfg.TAU0 = ideal.tau
cfg.DT = -cfg.DT
class TestGubser(unittest.TestCase):
    def setUp(self):
        self.cfg = cfg
        self.cfg.NZ = 1
        self.cfg.IEOS = 0
        self.ideal = CLIdeal(self.cfg)
        self.ctx = self.ideal.ctx
        self.queue = self.ideal.queue

    def test_gubser(self):
        ''' initialize with gubser energy density in (tau, x, y, eta) coordinates
        to test the gubser expansion:
           eps/eps0 = (tau/tau0)**(-4.0/3.0)
        '''

        kernel_src = """
        # include "real_type.h"
        __kernel void init_ev(global real4 * d_ev1,
                   const real tau,
                   const real q) {
          int i = (int) get_global_id(0);
          int j = (int) get_global_id(1);
          real x = (i-0.5*NX)*DX;
          real y = (j-0.5*NY)*DY;
          real r = sqrt(x*x + y*y);
          real ed = pow(2.0f*q, 8.0f/3.0f) / pow((1.0f + 2.0f*q*q*(tau*tau+r*r) + 
                    q*q*q*q*(tau*tau-r*r)*(tau*tau-r*r))*tau, 4.0f/3.0f);

          real vx = 2.0f*q*q*tau*x/(1.0f + q*q*tau*tau + q*q*r*r);
          real vy = 2.0f*q*q*tau*y/(1.0f + q*q*tau*tau + q*q*r*r);

          for ( int k = 0; k < NZ; k ++ ) {
             int gid = i*NY*NZ + j*NZ + k;
             d_ev1[gid] = (real4)(ed, vx, vy, 0.0);
          }
        }
        """
        cwd, cwf = os.path.split(__file__)

        q = 0.25
        NX, NY, NZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ
        compile_options = list(self.ideal.compile_options)
        compile_options.append('-I %s' % os.path.join(cwd, '..', 'kernel'))
        compile_options.append('-D USE_SINGLE_PRECISION')
        prg = cl.Program(self.ctx, kernel_src).build(compile_options)
        prg.init_ev(self.queue, (self.cfg.NX, self.cfg.NY), None,
                    self.ideal.d_ev[1], self.cfg.real(self.cfg.TAU0),
                    self.cfg.real(q)).wait()

        max_loops = 1000
        for n in range(max_loops):
            self.ideal.stepUpdate(step=1)
            self.ideal.tau = self.cfg.real(self.cfg.TAU0 +
                                           (n + 1) * self.cfg.DT)
            self.ideal.stepUpdate(step=2)
            print('n=', n)
            if n % 100 == 0:
                cl.enqueue_copy(self.queue, self.ideal.h_ev1,
                                self.ideal.d_ev[1]).wait()
                edr = self.ideal.h_ev1[:, 0].reshape(NX, NY, NZ)[:, NY // 2,
                                                                 NZ // 2]
                vr = self.ideal.h_ev1[:, 1].reshape(NX, NY, NZ)[:, NY // 2,
                                                                NZ // 2]

                x = np.linspace(-NX // 2 * self.cfg.DX, NX // 2 * self.cfg.DX,
                                NX)

                a = gubser_ed(self.ideal.tau, x, q)
                b = edr[:]
                c = gubser_vr(self.ideal.tau, x, q)
                d = vr[:]

                plt.semilogy(x, a, 'r-')
                plt.semilogy(x, b, 'b--')
                #plt.plot(x, c, 'r-', label='analy')
                #plt.plot(x, d, 'b--', label='CLVisc')
        plt.xlabel(r'$r\ [fm]$', fontsize=30)
        #plt.ylabel(r'$v_{\perp}$', fontsize=30)
        plt.title(r'Gubser solution test', fontsize=30)
        plt.ylabel('ed', fontsize=30)
        plt.subplots_adjust(left=0.13, bottom=0.13)
        plt.legend(loc='best')
        plt.show()
Beispiel #10
0
 def setUp(self):
     self.ideal = CLIdeal(configs=cfg)
     self.ctx = self.ideal.ctx
     self.queue = self.ideal.queue
Beispiel #11
0
    def __init__(self, configs, handcrafted_eos=None, gpu_id=0):
        self.ideal = CLIdeal(configs, handcrafted_eos, gpu_id)
        self.cfg = configs
        self.ctx = self.ideal.ctx
        self.queue = self.ideal.queue
        self.compile_options = self.ideal.compile_options
        self.__loadAndBuildCLPrg()

        self.eos_table = self.ideal.eos_table

        self.size = self.ideal.size
        self.h_pi0 = np.zeros(10 * self.size, self.cfg.real)

        mf = cl.mem_flags
        # initialize the d_pi^{mu nu} with 0
        self.d_pi = [
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0)
        ]

        self.d_IS_src = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)
        # d_udx, d_udy, d_udz, d_udt are velocity gradients for viscous hydro
        # datatypes are real4

        nbytes_edv = self.ideal.h_ev1.nbytes
        self.d_udx = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)
        self.d_udy = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)
        self.d_udz = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)

        # d_omega thermal vorticity vector omega^{mu nu} = epsilon^{mu nu a b} d_a (beta u_b)
        # anti-symmetric 6 independent components
        self.h_omega = np.zeros(6 * self.size, self.cfg.real)
        self.d_omega = [
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_omega),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_omega)
        ]

        # in case one wants to save omega^{mu} vector
        self.a_omega_mu = cl_array.empty(self.queue, 4 * self.size,
                                         self.cfg.real)

        # get the vorticity on the freeze out hypersurface
        self.d_omega_sf = cl.Buffer(self.ctx,
                                    mf.READ_WRITE,
                                    size=9000000 * self.cfg.sz_real)

        # velocity difference between u_visc and u_ideal* for correction
        self.d_udiff = cl.Buffer(self.ctx,
                                 mf.READ_WRITE,
                                 size=self.ideal.h_ev1.nbytes)

        # traceless and transverse check
        # self.d_checkpi = cl.Buffer(self.ctx, mf.READ_WRITE, size=self.ideal.h_ev1.nbytes)
        self.h_goodcell = np.ones(self.size, self.cfg.real)
        self.d_goodcell = cl.Buffer(self.ctx,
                                    mf.READ_WRITE,
                                    size=self.h_goodcell.nbytes)

        cl.enqueue_copy(self.queue, self.d_pi[1], self.h_pi0).wait()
        cl.enqueue_copy(self.queue, self.d_goodcell, self.h_goodcell).wait()

        # used for freeze out hypersurface calculation
        self.d_pi_old = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)

        # store the pi^{mu nu} on freeze out hyper surface
        self.d_pi_sf = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)
        self.kernel_hypersf = self.ideal.kernel_hypersf
        # initialize pimn, umu[2] such that its value can be changed before
        # self.evolve() is called for bjorken_test and gubser_test
        self.IS_initialize()
        self.ideal_predict_for_first_step()

        self.d_pizz_o_ep = cl.Buffer(self.ctx, mf.READ_WRITE,
                                     self.cfg.NZ * self.cfg.sz_real)
Beispiel #12
0
class CLVisc(object):
    '''The pyopencl version for 3+1D visc hydro dynamic simulation
    one can use handcrafted eos by replacing eos=None with
    handcrafted_eos = EosCraft(kind='eosq_modify') or paramterized eos'''
    def __init__(self, configs, handcrafted_eos=None, gpu_id=0):
        self.ideal = CLIdeal(configs, handcrafted_eos, gpu_id)
        self.cfg = configs
        self.ctx = self.ideal.ctx
        self.queue = self.ideal.queue
        self.compile_options = self.ideal.compile_options
        self.__loadAndBuildCLPrg()

        self.eos_table = self.ideal.eos_table

        self.size = self.ideal.size
        self.h_pi0 = np.zeros(10 * self.size, self.cfg.real)

        mf = cl.mem_flags
        # initialize the d_pi^{mu nu} with 0
        self.d_pi = [
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_pi0)
        ]

        self.d_IS_src = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)
        # d_udx, d_udy, d_udz, d_udt are velocity gradients for viscous hydro
        # datatypes are real4

        nbytes_edv = self.ideal.h_ev1.nbytes
        self.d_udx = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)
        self.d_udy = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)
        self.d_udz = cl.Buffer(self.ctx, mf.READ_WRITE, size=nbytes_edv)

        # d_omega thermal vorticity vector omega^{mu nu} = epsilon^{mu nu a b} d_a (beta u_b)
        # anti-symmetric 6 independent components
        self.h_omega = np.zeros(6 * self.size, self.cfg.real)
        self.d_omega = [
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_omega),
            cl.Buffer(self.ctx,
                      mf.READ_WRITE | mf.COPY_HOST_PTR,
                      hostbuf=self.h_omega)
        ]

        # in case one wants to save omega^{mu} vector
        self.a_omega_mu = cl_array.empty(self.queue, 4 * self.size,
                                         self.cfg.real)

        # get the vorticity on the freeze out hypersurface
        self.d_omega_sf = cl.Buffer(self.ctx,
                                    mf.READ_WRITE,
                                    size=9000000 * self.cfg.sz_real)

        # velocity difference between u_visc and u_ideal* for correction
        self.d_udiff = cl.Buffer(self.ctx,
                                 mf.READ_WRITE,
                                 size=self.ideal.h_ev1.nbytes)

        # traceless and transverse check
        # self.d_checkpi = cl.Buffer(self.ctx, mf.READ_WRITE, size=self.ideal.h_ev1.nbytes)
        self.h_goodcell = np.ones(self.size, self.cfg.real)
        self.d_goodcell = cl.Buffer(self.ctx,
                                    mf.READ_WRITE,
                                    size=self.h_goodcell.nbytes)

        cl.enqueue_copy(self.queue, self.d_pi[1], self.h_pi0).wait()
        cl.enqueue_copy(self.queue, self.d_goodcell, self.h_goodcell).wait()

        # used for freeze out hypersurface calculation
        self.d_pi_old = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)

        # store the pi^{mu nu} on freeze out hyper surface
        self.d_pi_sf = cl.Buffer(self.ctx, mf.READ_WRITE, self.h_pi0.nbytes)
        self.kernel_hypersf = self.ideal.kernel_hypersf
        # initialize pimn, umu[2] such that its value can be changed before
        # self.evolve() is called for bjorken_test and gubser_test
        self.IS_initialize()
        self.ideal_predict_for_first_step()

        self.d_pizz_o_ep = cl.Buffer(self.ctx, mf.READ_WRITE,
                                     self.cfg.NZ * self.cfg.sz_real)

    def __loadAndBuildCLPrg(self):
        self.cwd, cwf = os.path.split(__file__)
        #load and build *.cl programs with compile options
        if self.cfg.gubser_visc_test:
            self.compile_options.append('-D GUBSER_VISC_TEST')

        if self.cfg.riemann_test:
            self.compile_options.append('-D RIEMANN_TEST')

        if self.cfg.pimn_omega_coupling:
            self.compile_options.append('-D PIMUNU_OMEGA_COUPLING')

        if self.cfg.omega_omega_coupling:
            self.compile_options.append('-D OMEGA_OMEGA_COUPLING')

        with open(os.path.join(self.cwd, 'kernel', 'kernel_IS.cl'), 'r') as f:
            src = f.read()
            self.kernel_IS = cl.Program(
                self.ctx, src).build(options=' '.join(self.compile_options))

        with open(os.path.join(self.cwd, 'kernel', 'kernel_visc.cl'),
                  'r') as f:
            src = f.read()
            self.kernel_visc = cl.Program(
                self.ctx, src).build(options=' '.join(self.compile_options))

        with open(os.path.join(self.cwd, 'kernel', 'kernel_checkpi.cl'),
                  'r') as f:
            src = f.read()
            self.kernel_checkpi = cl.Program(
                self.ctx, src).build(options=' '.join(self.compile_options))

        with open(os.path.join(self.cwd, 'kernel', 'kernel_vorticity.cl'),
                  'r') as f:
            src = f.read()
            self.kernel_vorticity = cl.Program(
                self.ctx, src).build(options=' '.join(self.compile_options))

        with open(os.path.join(self.cwd, 'kernel', 'kernel_jet_eloss.cl'),
                  'r') as f:
            src = f.read()
            self.kernel_jet_eloss = cl.Program(
                self.ctx, src).build(options=' '.join(self.compile_options))

    def IS_initialize(self):
        '''initialize pi^{mu nu} tensor'''
        NX, NY, NZ, BSZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ, self.cfg.BSZ

        self.kernel_IS.visc_initialize(self.queue, (NX * NY * NZ, ), None,
                                       self.d_pi[1], self.d_goodcell,
                                       self.d_udiff, self.ideal.d_ev[1],
                                       self.ideal.tau, self.eos_table).wait()

    def optical_glauber_ini(self,
                            system='Au+Au',
                            cent_min=None,
                            cent_max=None,
                            save_binary_collisions=False):
        '''initialize with optical glauber model for Au+Au and Pb+Pb collisions
        Params:
            :param system: type string, Au+Au for Au+Au 200 GeV, Pb+Pb for Pb+Pb 2.76 TeV and 5.02 TeV
            :param cent_min: type int or float,  lower limit for the centrality range
            :param cent_max: type int or float,  upper limit for the centrality range
                   if cent_min and cent_max are None, ImpactParameter is read from self.cfg
                   otherwise, weighted ImpactParameter is given by weight_mean_b()
            :param save_binary_collisions: type bool, true to save num_of_binary_collisions for jet
                 energy loss study (used to sample jet creation position '''
        from glauber import Glauber, weight_mean_b

        if cent_min is not None and cent_max is not None:
            mean_impact_parameter = weight_mean_b(cent_min, cent_max, system)
            # notice the config is changed here, write_to_config() must be called after this
            # to save the correct ImpactParameter
            self.cfg.ImpactParameter = mean_impact_parameter

        glauber = Glauber(self.cfg, self.ctx, self.queue, self.compile_options,
                          self.ideal.d_ev[1])
        if save_binary_collisions:
            glauber.save_nbinary(self.ctx, self.queue, self.cfg)

    def create_ini_from_partons(self, fname, SIGR=0.6, SIGZ=0.6, KFACTOR=1.0):
        '''generate initial condition from a list of partons in fname,
        SIGR: the gaussian smearing width in transverse direction
        SIGZ: the gaussian smearing width along longitudinal direction
        KFACTOR: scale factor to fit dNch/deta in most central collisions'''
        from smearing import Smearing
        Smearing(self.cfg, self.ctx, self.queue, self.compile_options,
                 self.ideal.d_ev[1], fname, self.eos_table, SIGR, SIGZ,
                 KFACTOR)

    def smear_from_p4x4(self,
                        p4x4,
                        SIGR=0.6,
                        SIGZ=0.6,
                        KFACTOR=1.0,
                        force_bjorken=False,
                        longitudinal_profile=None):
        '''generate initial condition from a list of partons given by p4x4,
        SIGR: the gaussian smearing width in transverse direction
        SIGZ: the gaussian smearing width along longitudinal direction
        KFACTOR: scale factor to fit dNch/deta in most central collisions
        force_bjorken: True to switch off longitudinal fluctuation (use mid-rapidity only)'''
        from smearing import SmearingP4X4
        SmearingP4X4(self.cfg, self.ctx, self.queue, self.compile_options,
                     self.ideal.d_ev[1], p4x4, self.eos_table, SIGR, SIGZ,
                     KFACTOR, force_bjorken, longitudinal_profile)

    def check_pizz(self):
        '''initialize pi^{mu nu} tensor'''
        NZ = self.cfg.NZ
        self.kernel_checkpi.pizz_o_ep(self.queue, (NZ, ), None,
                                      self.d_pizz_o_ep, self.d_pi[1],
                                      self.ideal.d_ev[1],
                                      self.eos_table).wait()
        pizz_o_ep = np.zeros(NZ, dtype=np.float32)
        cl.enqueue_copy(self.queue, pizz_o_ep, self.d_pizz_o_ep).wait()
        print('<pizz/(e+P)> =', pizz_o_ep[NZ // 2])

    def check_bad_cell(self):
        '''if max(|pi^{mu nu}|) > T00, the cell is marked as bad_cell.
        This function readout bad_cells from GPU, compare the temperature of the bad cells
        with freeze out temperature '''
        NX, NY, NZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ
        cl.enqueue_copy(self.queue, self.h_goodcell, self.d_goodcell).wait()
        efrz = self.ideal.efrz
        # transfer data from self.ideal.d_ev[1] to self.ideal.h_ev1
        self.ideal.ev_to_host()
        ed_mid_rapidity = self.ideal.h_ev1[:, 0].reshape(NX, NY, NZ)[:, :,
                                                                     NZ // 2]
        frz_sf = (ed_mid_rapidity > efrz).astype(float) * 4.0
        good_cells = 3 * (self.h_goodcell.reshape(NX, NY, NZ)[:, :, NZ // 2] -
                          1)
        cell_masks = frz_sf + good_cells
        comments = '''4 for e>efrz and good cell;
                    1 for e > efrz and bad cell;
                    0 for e < efrz and good cell;
                    -3 for e<efrz and bad cell'''
        outpath = os.path.join(self.cfg.fPathOut,
                               'bad_cell_masks_tau%s.txt' % self.ideal.tau)
        np.savetxt(outpath, cell_masks, header=comments)

    def visc_stepUpdate(self,
                        step,
                        jet_eloss_src={
                            'switch_on': False,
                            'start_pos_index': 0,
                            'direction': 0
                        }):
        ''' Do step update in kernel with KT algorithm for visc evolution
            Args:
                gpu_ev_old: self.d_ev[1] for the 1st step,
                            self.d_ev[2] for the 2nd step
                step: the 1st or the 2nd step in runge-kutta
        '''
        # upadte d_Src by KT time splitting, along=1,2,3 for 'x','y','z'
        # input: gpu_ev_old, tau, size, along_axis
        # output: self.d_Src
        NX, NY, NZ, BSZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ, self.cfg.BSZ
        tau = self.ideal.tau
        self.kernel_visc.kt_src_christoffel(self.queue, (NX * NY * NZ, ), None,
                                            self.ideal.d_Src,
                                            self.ideal.d_ev[step],
                                            self.d_pi[step], self.eos_table,
                                            tau, np.int32(step)).wait()

        self.kernel_visc.kt_src_alongx(self.queue, (BSZ, NY, NZ), (BSZ, 1, 1),
                                       self.ideal.d_Src, self.ideal.d_ev[step],
                                       self.d_pi[step], self.eos_table,
                                       tau).wait()

        self.kernel_visc.kt_src_alongy(self.queue, (NX, BSZ, NZ), (1, BSZ, 1),
                                       self.ideal.d_Src, self.ideal.d_ev[step],
                                       self.d_pi[step], self.eos_table,
                                       tau).wait()

        self.kernel_visc.kt_src_alongz(self.queue, (NX, NY, BSZ), (1, 1, BSZ),
                                       self.ideal.d_Src, self.ideal.d_ev[step],
                                       self.d_pi[step], self.eos_table,
                                       tau).wait()

        if jet_eloss_src['switch_on'] == True:
            jet_start_pos_index = jet_eloss_src['start_pos_index']
            jet_start_angle = jet_eloss_src['direction']
            self.kernel_jet_eloss.jet_eloss_src(self.queue, (NX, NY, NZ), None,
                                                self.ideal.d_Src,
                                                self.ideal.d_ev[step], tau,
                                                self.cfg.real(jet_start_angle),
                                                np.int32(jet_start_pos_index),
                                                self.eos_table).wait()

        # if step=1, T0m' = T0m + d_Src*dt, update d_ev[2]
        # if step=2, T0m = T0m + 0.5*dt*d_Src, update d_ev[1]
        # Notice that d_Src=f(t,x) at step1 and
        # d_Src=(f(t,x)+f(t+dt, x(t+dt))) at step2
        # output: d_ev[] where need_update=2 for step 1 and 1 for step 2
        self.kernel_visc.update_ev(self.queue, (NX * NY * NZ, ), None,
                                   self.ideal.d_ev[3 - step],
                                   self.ideal.d_ev[1], self.d_pi[0],
                                   self.d_pi[3 - step], self.ideal.d_Src,
                                   self.eos_table, self.ideal.tau,
                                   np.int32(step)).wait()

    #@profile
    def IS_stepUpdate(self, step):
        NX, NY, NZ, BSZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ, self.cfg.BSZ

        self.kernel_IS.visc_src_christoffel(self.queue, (NX * NY * NZ, ), None,
                                            self.d_IS_src, self.d_pi[step],
                                            self.ideal.d_ev[step],
                                            self.ideal.tau,
                                            np.int32(step)).wait()

        self.kernel_IS.visc_src_alongx(self.queue, (BSZ, NY, NZ), (BSZ, 1, 1),
                                       self.d_IS_src, self.d_udx,
                                       self.d_pi[step], self.ideal.d_ev[step],
                                       self.eos_table, self.ideal.tau).wait()

        self.kernel_IS.visc_src_alongy(self.queue, (NX, BSZ, NZ), (1, BSZ, 1),
                                       self.d_IS_src, self.d_udy,
                                       self.d_pi[step], self.ideal.d_ev[step],
                                       self.eos_table, self.ideal.tau).wait()

        self.kernel_IS.visc_src_alongz(self.queue, (NX, NY, BSZ), (1, 1, BSZ),
                                       self.d_IS_src, self.d_udz,
                                       self.d_pi[step], self.ideal.d_ev[step],
                                       self.eos_table, self.ideal.tau).wait()

        # for step==1, d_ev[2] is useless, since u_new = u_old + d_udiff
        # for step==2, d_ev[2] is used to calc u_new
        self.kernel_IS.update_pimn(
            self.queue,
            (NX * NY * NZ, ),
            None,
            #needs_update      not_important    start_point   src_for_RK
            self.d_pi[3 - step],
            self.d_goodcell,
            self.d_pi[1],
            self.d_pi[step],
            self.ideal.d_ev[1],
            self.ideal.d_ev[2],
            self.d_udiff,
            self.d_udx,
            self.d_udy,
            self.d_udz,
            self.d_IS_src,
            self.eos_table,
            self.ideal.tau,
            np.int32(step)).wait()

    def get_vorticity(self, save_data=False):
        '''calc vorticity tensor Omega^{mu nu} = da (Tu_b) - db (Tu_a)
        Params:
            :param save_data: default False, set to True to save omega^{mu} vector
        '''
        NX, NY, NZ, BSZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ, self.cfg.BSZ
        self.kernel_vorticity.omega(self.queue, (NX, NY, NZ), None,
                                    self.ideal.d_ev[0], self.ideal.d_ev[1],
                                    self.d_omega[1], self.eos_table,
                                    self.ideal.tau).wait()

        if save_data:
            self.kernel_vorticity.omega_mu(self.queue, (NX * NY * NZ, ), None,
                                           self.a_omega_mu.data,
                                           self.ideal.d_ev[1], self.d_omega[1],
                                           self.eos_table,
                                           self.cfg.real(self.ideal.efrz),
                                           self.ideal.tau).wait()

            path_out = os.path.abspath(self.cfg.fPathOut)

            fname = ('omega_mu_tau%s' % self.ideal.tau).replace('.',
                                                                'p') + '.dat'

            omega_mu = self.a_omega_mu.get()

            np.savetxt(os.path.join(path_out, fname),
                       omega_mu.reshape(NX * NY * NZ, 4),
                       header='omega^{t, x, y, z} = Omega^{mu nu} u_{nu}')

    def update_udiff(self, d_ev0, d_ev1):
        '''get d_udiff = u_{visc}^{n} - u_{visc}^{n-1}, it is possible to 
        set d_udiff in analytical solution for viscous gubser test'''
        NX, NY, NZ = self.cfg.NX, self.cfg.NY, self.cfg.NZ
        self.kernel_IS.get_udiff(self.queue, (NX * NY * NZ, ), None,
                                 self.d_udiff, d_ev0, d_ev1).wait()

    def get_hypersf(self, n, ntskip, is_finished):
        '''get the freeze out hyper surface from d_ev_old and d_ev_new
        global_size=(NX//nxskip, NY//nyskip, NZ//nzskip}
        Params:
            :param n: the time step number
            :param ntskip: time step interval for hypersf calc
            :param is_finished: if True, the last time interval for hypersf
                   calculation will be different'''
        if n == 0:
            cl.enqueue_copy(self.queue, self.ideal.d_ev_old,
                            self.ideal.d_ev[1]).wait()
            cl.enqueue_copy(self.queue, self.d_pi_old, self.d_pi[1]).wait()

            self.tau_old = self.cfg.TAU0
        elif (n % ntskip == 0) or is_finished:
            nx = (self.cfg.NX - 1) // self.cfg.nxskip + 1
            ny = (self.cfg.NY - 1) // self.cfg.nyskip + 1
            nz = (self.cfg.NZ - 1) // self.cfg.nzskip + 1
            tau_new = self.ideal.tau
            self.kernel_hypersf.visc_hypersf(
                self.queue, (nx, ny, nz), None, self.ideal.d_hypersf,
                self.ideal.d_sf_txyz, self.d_pi_sf, self.ideal.d_num_of_sf,
                self.ideal.d_ev_old, self.ideal.d_ev[1], self.d_pi_old,
                self.d_pi[1], self.d_omega_sf, self.d_omega[0],
                self.d_omega[1], self.cfg.real(self.tau_old),
                self.cfg.real(tau_new)).wait()

            # update with current tau and d_ev[1], d_pi[1] and d_omega[1]
            cl.enqueue_copy(self.queue, self.ideal.d_ev_old,
                            self.ideal.d_ev[1]).wait()
            cl.enqueue_copy(self.queue, self.d_pi_old, self.d_pi[1]).wait()
            cl.enqueue_copy(self.queue, self.d_omega[0],
                            self.d_omega[1]).wait()
            self.tau_old = tau_new

    def save_pimn_sf(self, set_to_zero=False):
        '''save pimn information on freeze out hyper surface
        Params:
            :param set_to_zero: True to set pimn on surface to 0.0,
            in case eta/s=0, ideal evolution is switch on'''
        num_of_sf = self.ideal.num_of_sf
        ed = self.ideal.efrz
        pr = self.ideal.eos.f_P(ed)
        T = self.cfg.TFRZ
        const_for_deltaf = 1.0 / (2.0 * T**2 * (ed + pr))
        pi_onsf = np.zeros(10 * num_of_sf, dtype=self.cfg.real)
        if not set_to_zero:
            cl.enqueue_copy(self.queue, pi_onsf, self.d_pi_sf).wait()
        out_path = os.path.join(self.cfg.fPathOut, 'pimnsf.dat')
        print("pimn on frzsf is saved to ", out_path)

        comment_line = 'one_o_2TsqrEplusP=%.6e '%const_for_deltaf + \
               'pi00 01 02 03 11 12 13 22 23 33'
        np.savetxt(out_path,
                   pi_onsf.reshape(num_of_sf, 10),
                   fmt='%.6e',
                   header=comment_line)

    def save(self,
             save_hypersf=True,
             save_bulk=False,
             save_pi=False,
             save_vorticity=False):
        self.ideal.save(save_hypersf, save_bulk, viscous_on=True)

        if save_pi:
            self.pimn_info.save()

        if save_hypersf:
            self.save_pimn_sf()

        if save_vorticity:
            # save vorticity on hypersf to data file
            num_of_sf = self.ideal.num_of_sf
            omega_mu = np.empty(6 * num_of_sf, dtype=self.cfg.real)
            cl.enqueue_copy(self.queue, omega_mu, self.d_omega_sf).wait()
            out_path = os.path.join(self.cfg.fPathOut, 'omegamu_sf.dat')
            print("vorticity omega_{mu, nu} on surface is saved to", out_path)
            np.savetxt(out_path,
                       omega_mu.reshape(self.ideal.num_of_sf, 6),
                       fmt='%.6e',
                       header='omega^{01, 02, 03, 12, 13, 23}')

    def update_time(self, loop):
        self.ideal.update_time(loop)

    def ideal_predict_for_first_step(self):
        # ideal prediction to get umu for the first time step
        self.ideal.stepUpdate(step=1)

    #@profile
    def evolve(self,
               max_loops=1000,
               save_hypersf=True,
               save_bulk=False,
               plot_bulk=True,
               save_pi=True,
               force_run_to_maxloop=False,
               save_vorticity=False,
               jet_eloss_src={
                   'switch_on': False,
                   'start_pos_index': 0,
                   'direction': 0.0
               },
               debug=False):
        '''The main loop of hydrodynamic evolution
        default parameters: save_hypersf, don't save bulk info
        store bulk info by switch on plot_bulk;
        Args:
            jet_eloss_src: one dictionary stores the jet eloss information '''
        # if etaos<1.0E-6, use ideal hydrodynamics which is much faster
        if self.cfg.ETAOS_YMIN < 1.0E-6 and self.cfg.ETAOS_LEFT_SLOP < 1.0E-6 \
           and self.cfg.ETAOS_RIGHT_SLOP < 1.0E-6 and not save_vorticity:
            self.ideal.evolve(max_loops, save_hypersf, save_bulk, plot_bulk,
                              force_run_to_maxloop, jet_eloss_src)

            self.save_pimn_sf(set_to_zero=True)
            return

        if save_pi:
            from pimninfo import PimnInfo
            self.pimn_info = PimnInfo(self.cfg, self.ctx, self.queue,
                                      self.compile_options)

        loop = 0
        #for loop in xrange(max_loops):
        while True:
            t0 = time()
            # stop at max_loops if force_run_to_maxloop set to True
            if force_run_to_maxloop and loop == max_loops:
                break

            if loop % self.cfg.ntskip == 0:
                self.ideal.edmax = self.ideal.max_energy_density()
                self.ideal.history.append([self.ideal.tau, self.ideal.edmax])
                print('tau=', self.ideal.tau, ' EdMax= ', self.ideal.edmax)

            is_finished = self.ideal.edmax < self.ideal.efrz

            if save_hypersf:
                self.get_hypersf(loop, self.cfg.ntskip, is_finished)

            if (plot_bulk or save_bulk) and loop % self.cfg.ntskip == 0:
                self.ideal.bulkinfo.get(self.ideal.tau, self.ideal.d_ev[1],
                                        self.ideal.edmax, self.d_pi[1])

            if save_pi and loop % self.cfg.ntskip == 0:
                self.pimn_info.get(self.ideal.tau, self.d_pi[1])

            # finish if edmax < freeze out energy density
            if is_finished and not force_run_to_maxloop:
                break

            # store d_pi[0] for self.visc_stepUpdate()
            cl.enqueue_copy(self.queue, self.d_pi[0], self.d_pi[1]).wait()

            # copy the d_ev[1] to d_ev[0] for umu_new prediction
            cl.enqueue_copy(self.queue, self.ideal.d_ev[0],
                            self.ideal.d_ev[1]).wait()

            # update pi[2] with d_ev[0] and u_new=u0+d_udiff
            # where d_udiff is prediction from previous step
            self.IS_stepUpdate(step=1)
            self.visc_stepUpdate(step=1)
            self.update_time(loop)
            # update pi[1] with d_ev[0] and d_ev[2]_visc*

            self.IS_stepUpdate(step=2)

            self.visc_stepUpdate(step=2, jet_eloss_src=jet_eloss_src)
            self.update_udiff(self.ideal.d_ev[0], self.ideal.d_ev[1])

            # add the thermal vorticity calculation here
            if loop % self.cfg.ntskip == 0 and save_vorticity:
                self.get_vorticity(save_data=False)

            # save the bad cells at debug stage
            if debug and loop % self.cfg.ntskip == 0:
                self.check_bad_cell()

            loop = loop + 1
            t1 = time()
            print('one step: {dtime}'.format(dtime=t1 - t0))

        self.save(save_hypersf=save_hypersf,
                  save_bulk=save_bulk,
                  save_pi=save_pi,
                  save_vorticity=save_vorticity)
Beispiel #13
0
class TestLongitudinalExpansion(unittest.TestCase):
    def setUp(self):
        self.cfg = cfg
        self.cfg.NX = 1
        self.cfg.NY = 1
        self.cfg.NZ = 401
        self.cfg.DT = 0.005
        self.cfg.DZ = 0.075
        self.cfg.IEOS = 0
        self.cfg.ntskip = 100
        self.cfg.nzskip = 4
        self.ideal = CLIdeal(self.cfg)
        self.ctx = self.ideal.ctx
        self.queue = self.ideal.queue

    def test_longitudinal_expansion(self):
        ''' initialize with uniform energy density in (tau, x, y, eta) coordinates
        to test the Bjorken expansion:
           eps/eps0 = (tau/tau0)**(-4.0/3.0)
        '''

        kernel_src = """
        # include "real_type.h"
        # define Eta_flat 2.95f
        # define Eta_gw   2.0f
        # define NZ %s
        # define DZ %sf

        real weight_along_eta(real z, real etas0_) {
            real heta;
            if( fabs(z-etas0_) > Eta_flat ) {
                heta=exp(-pow(fabs(z-etas0_)-Eta_flat,2.0f)/(2.0f*Eta_gw*Eta_gw));
            } else {
                heta = 1.0f;
            }
            return heta;
        }

        real gaussian_along_eta(real z) {
            return exp(-z*z/(2.0f*Eta_gw*Eta_gw));
        }


        __kernel void init_ev(global real4 * d_ev1, const int size) {
          int gid = (int) get_global_id(0);
          if ( gid < size ) {
             real eta = (gid - NZ/2)*DZ;
             real eds = gaussian_along_eta(eta) * 30.0;
             d_ev1[gid] = (real4)(eds, 0.0f, 0.0f, 0.0f);
          }
        }
        """ % (self.cfg.NZ, self.cfg.DZ)
        cwd, cwf = os.path.split(__file__)

        compile_options = ['-I %s' % os.path.join(cwd, '..', 'kernel')]
        compile_options.append('-D USE_SINGLE_PRECISION')
        prg = cl.Program(self.ctx, kernel_src).build(compile_options)
        prg.init_ev(self.queue, (self.ideal.size, ), None, self.ideal.d_ev[1],
                    np.int32(self.ideal.size)).wait()

        self.ideal.evolve(max_loops=1400,
                          save_bulk=False,
                          save_hypersf=False,
                          plot_bulk=True)

        bulk = self.ideal.bulkinfo

        save_bulk(bulk, timestep=self.cfg.DT * self.cfg.ntskip)
import os, sys
cwd, cwf = os.path.split(__file__)
sys.path.append(os.path.join(cwd, '../pyvisc'))

from ideal import CLIdeal
from config import cfg, write_config
import pyopencl as cl

cfg.IEOS = 0

cfg.NX = 401
cfg.NY = 401
cfg.NZ = 1

cfg.TAU0 = 0.6
cfg.Edmax = 17.0
cfg.Hwn = 1.0
cfg.ImpactParameter = 7.0

write_config(cfg)

ideal = CLIdeal(cfg)

from glauber import Glauber
ini = Glauber(cfg, ideal.ctx, ideal.queue, ideal.gpu_defines, ideal.d_ev[1])

ideal.evolve(max_loops=1000,
             save_bulk=True,
             to_maxloop=True,
             save_hypersf=False)