// File: /workspace/github_c_makefile_star2_O1/PoulinV[P]AxiCLASS/build/../source/thermodynamics.c
// Function: thermodynamics_obtain_z_ini
int thermodynamics_obtain_z_ini(
                                struct precision * ppr,
                                struct background *pba,
                                struct thermodynamics *pth,
                                struct thermo_workspace * ptw
                                ) {

  /* These wil affect when and how the temperature integration starts*/
  double z_initial;
  int Nz_log;
  /* This describes until when (if at all) any idm might be coupled to either photon or IDR temp*/
  double z_idm_dec, z_idm_dec_min=_HUGE_;

  double R_dm;
  double f1nu = 7./8.*pow((4./11.),(4./3.));

  z_initial = ppr->thermo_z_initial;
  Nz_log = ppr->thermo_Nz_log;

  /* Set this initially to False and check if it's needed */
  ptw->has_ap_idmtca = _FALSE_;

  /* If there is idm, we want the thermodynamics table to
   * start at a much larger z, in order to capture the possible
   * non-trivial behavior of the dark matter interaction rate at early times */

  /* First, calculate the approximate decoupling time iff there is coupling, based on formulae from 2010.04074 */
  if (pba->has_idm == _TRUE_) {
    if ((pth->has_idm_g == _TRUE_) && (pth->n_index_idm_g > -2)) {
      z_idm_dec = pow(3.01e9, 1./(2+pth->n_index_idm_g)) * pow((1.+pba->Neff*f1nu)/(1.+3.044*f1nu), 1./(4.+2.*pth->n_index_idm_g)) * pow(pth->u_idm_g*1e4, -1./(2.+pth->n_index_idm_g));
      if (pth->thermodynamics_verbose > 3)
        printf("The decoupling redshift for idm_g is z_idm_dec = %.5e\n", z_idm_dec);
      z_idm_dec_min = MIN(z_idm_dec, z_idm_dec_min);
    }
    if ((pth->has_idm_b == _TRUE_) && (pth->n_index_idm_b > -3)) {
      R_dm = pth->m_idm / (_m_p_*_c_*_c_/_eV_);
      z_idm_dec = 4e4 * pow(  9.15/pth->n_coeff_idm_b
                              *pow((1.+pba->Neff*f1nu)/(1.+3.044*f1nu), 1./2.) * (0.0224/pba->Omega0_b/pba->h/pba->h)
                              *pow(R_dm, (pth->n_index_idm_b+1.)/2.)/pow(1.+R_dm, (pth->n_index_idm_b-1.)/2.)
                              *pow(10.,4*pth->n_index_idm_b - 25)/pth->cross_idm_b        ,  2./(pth->n_index_idm_b+3));

      if (pth->n_index_idm_b == -2)
        z_idm_dec *= 10;
      if (pth->thermodynamics_verbose > 3)
        printf("The decoupling redshift for idm_b is z_idm_dec = %.5e\n", z_idm_dec);
      z_idm_dec_min = MIN(z_idm_dec, z_idm_dec_min);
    }
    if ((pth->has_idm_dr == _TRUE_) && (pth->n_index_idm_dr > 0)) {
      z_idm_dec = pow(10., 7.-6./ pth->n_index_idm_dr)
        * pow( 1.6 * (1e-6/pba->Omega0_idr/pba->h/pba->h)
               * pow((1.+pba->Neff*f1nu)/(1.+3.044*f1nu), 1./2.)
               * (1e6 / pth->a_idm_dr)  ,  1./pth->n_index_idm_dr);
      if (pth->thermodynamics_verbose > 3)
        printf("The decoupling redshift for idm_dr is z_idm_dec = %.5e\n", z_idm_dec);
      /* we need to be careful if idm is coupled to photons and idr at the same time */
      class_test(z_idm_dec_min != _HUGE_ && fabs(pba->T_idr - pba->T_cmb) > 1e-2,
                 pth->error_message,
                 "It seems that at early times idm is thermally coupled to both idr and photons (possibly through baryons).\nPlease set the initial temperatures equal or disable this error.");

      z_idm_dec_min = MIN(z_idm_dec, z_idm_dec_min);
    }

    /* if there is initial coupling then we need the approximation scheme ap_idmtca */
    if (z_idm_dec_min != _HUGE_) {
      ptw->has_ap_idmtca = _TRUE_;
      /* assert that ap_idmtca ends before ap_brec ends */
      ptw->z_ap_idmtca = MAX( 1e2 * z_idm_dec_min, (ppr->recfast_z_He_1+ppr->recfast_delta_z_He_1)*1.5);
      if (pth->thermodynamics_verbose > 3)
        printf("Starting the idm TCA at z_ap_idmtca = %.5e\n", ptw->z_ap_idmtca);
    }

    /* From this, decide the initial time of integration */
    /* start the integration before the decoupling */
    if (ptw->has_ap_idmtca == _TRUE_) {
      class_test(ptw->z_ap_idmtca * ppr->a_ini_over_a_today_default > 1,
                 pth->error_message,
                 "The decoupling time of the idm species is set earlier than the background integration. Start the background integration earlier.");

      z_initial = MAX(z_initial, MIN(100 * ptw->z_ap_idmtca, 1/ppr->a_ini_over_a_today_default-2.));
    }

    /* if there is no coupling at early time, we need to set an another starting point */
    else {
      z_initial = MAX(ppr->thermo_z_initial_if_idm, z_initial);
    }

    if (pth->thermodynamics_verbose > 2)
      printf(" -> Increasing the initial redshift of thermodynamics from %e to %e \n",ppr->thermo_z_initial,z_initial);

    /* Rescale Nz_log (if necessary) in order to cover with equal spacing the enlarged range */
    Nz_log = MAX((int)(Nz_log/log(ppr->thermo_z_initial)*log(z_initial)),Nz_log);
  }

  ppr->thermo_z_initial = z_initial;
  ppr->thermo_Nz_log = Nz_log;
  class_test(z_initial * ppr->a_ini_over_a_today_default > 1.,
             pth->error_message,
             "The initial starting time for the temperature integration is set earlier than the background integration. Adjust obtain_z_ini to mitigate this");
  class_test(z_initial <  ppr->recfast_z_He_3,
             pth->error_message,
             "The initial starting time for the temperature integration is set after HeliumIII recombination starts. Adjust obtain_z_ini to mitigate this");

  return _SUCCESS_;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x1020, %rsp           # imm = 0x1020
movq %rdx, %rbx
movq %rdi, %r14
movsd 0x190(%rdi), %xmm3
movl 0x1ac(%rdi), %ebp
movw $0x0, 0x60(%rcx)
cmpw $0x1, 0x4b6(%rsi)
jne 0x6b34f
movq %rcx, %r15
movq %rsi, %r12
movsd 0xa593e(%rip), %xmm2    # 0x110690
cmpw $0x1, 0x36(%rbx)
movsd %xmm3, 0x10(%rsp)
jne 0x6ae5c
movl 0x1058(%rbx), %eax
cmpl $-0x1, %eax
jl 0x6ae5c
addl $0x2, %eax
cvtsi2sd %eax, %xmm0
movsd 0x864df(%rip), %xmm1    # 0xf1260
divsd %xmm0, %xmm1
movsd 0xa590b(%rip), %xmm0    # 0x110698
callq 0x8620
movsd %xmm0, (%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0xa2ce7(%rip), %xmm0    # 0x10da90
movsd 0x864af(%rip), %xmm2    # 0xf1260
addsd %xmm2, %xmm0
divsd 0xa58e3(%rip), %xmm0    # 0x1106a0
xorps %xmm1, %xmm1
cvtsi2sdl 0x1058(%rbx), %xmm1
addsd %xmm1, %xmm1
addsd 0x89654(%rip), %xmm1    # 0xf4428
divsd %xmm1, %xmm2
movapd %xmm2, %xmm1
callq 0x8620
mulsd (%rsp), %xmm0
movsd %xmm0, (%rsp)
movsd 0x1050(%rbx), %xmm0
mulsd 0xa58ad(%rip), %xmm0    # 0x1106a8
xorps %xmm2, %xmm2
cvtsi2sdl 0x1058(%rbx), %xmm2
addsd 0x86ef2(%rip), %xmm2    # 0xf1d00
movsd 0x869d2(%rip), %xmm1    # 0xf17e8
divsd %xmm2, %xmm1
callq 0x8620
movapd %xmm0, %xmm2
mulsd (%rsp), %xmm2
cmpw $0x4, 0x1060(%rbx)
jl 0x6ae4e
leaq 0xa9ff3(%rip), %rdi     # 0x114e2c
movapd %xmm2, %xmm0
movb $0x1, %al
movsd %xmm2, (%rsp)
callq 0x8030
movsd (%rsp), %xmm2
minsd 0xa583a(%rip), %xmm2    # 0x110690
movsd 0x10(%rsp), %xmm3
cmpw $0x1, 0x34(%rbx)
jne 0x6b01b
cmpl $-0x2, 0x1038(%rbx)
jl 0x6b01b
movsd %xmm2, (%rsp)
movsd 0x1010(%rbx), %xmm0
divsd 0xa57c7(%rip), %xmm0    # 0x110650
movsd %xmm0, 0x18(%rsp)
movsd 0xa5819(%rip), %xmm0    # 0x1106b0
divsd 0x1040(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0xa2bd9(%rip), %xmm0    # 0x10da90
addsd 0x863a1(%rip), %xmm0    # 0xf1260
divsd 0xa57d9(%rip), %xmm0    # 0x1106a0
movsd 0x86e01(%rip), %xmm1    # 0xf1cd0
callq 0x8620
mulsd 0x8(%rsp), %xmm0
movsd 0xa57d6(%rip), %xmm2    # 0x1106b8
divsd 0x20(%r12), %xmm2
movsd 0x8(%r12), %xmm1
divsd %xmm1, %xmm2
divsd %xmm1, %xmm2
mulsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
xorps %xmm1, %xmm1
cvtsi2sdl 0x1038(%rbx), %xmm1
addsd 0x8634b(%rip), %xmm1    # 0xf1260
mulsd 0x86db3(%rip), %xmm1    # 0xf1cd0
movsd 0x18(%rsp), %xmm0
callq 0x8620
mulsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
xorps %xmm1, %xmm1
cvtsi2sdl 0x1038(%rbx), %xmm1
movsd 0x18(%rsp), %xmm0
addsd 0x86313(%rip), %xmm0    # 0xf1260
addsd 0x86893(%rip), %xmm1    # 0xf17e8
mulsd 0x86d73(%rip), %xmm1    # 0xf1cd0
callq 0x8620
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movl 0x1038(%rbx), %eax
leal -0x19(,%rax,4), %eax
xorps %xmm1, %xmm1
cvtsi2sd %eax, %xmm1
movsd 0x86862(%rip), %xmm0    # 0xf17f0
callq 0x8620
mulsd 0x8(%rsp), %xmm0
divsd 0x1030(%rbx), %xmm0
movl 0x1038(%rbx), %eax
addl $0x3, %eax
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
movsd 0x86d47(%rip), %xmm1    # 0xf1d00
divsd %xmm2, %xmm1
callq 0x8620
movapd %xmm0, %xmm2
mulsd 0xa56f2(%rip), %xmm2    # 0x1106c0
cmpl $-0x2, 0x1038(%rbx)
jne 0x6afdf
mulsd 0x86811(%rip), %xmm2    # 0xf17f0
movsd (%rsp), %xmm0
cmpw $0x4, 0x1060(%rbx)
jl 0x6b011
leaq 0xa9e6e(%rip), %rdi     # 0x114e63
movapd %xmm2, %xmm0
movb $0x1, %al
movsd %xmm2, 0x8(%rsp)
callq 0x8030
movsd 0x8(%rsp), %xmm2
movsd (%rsp), %xmm0
minsd %xmm0, %xmm2
movsd 0x10(%rsp), %xmm3
cmpw $0x1, 0x38(%rbx)
jne 0x6b1c0
movsd 0x1028(%rbx), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x6b1c0
movsd %xmm2, (%rsp)
movsd 0x8761f(%rip), %xmm1    # 0xf2668
divsd %xmm0, %xmm1
addsd 0x8770b(%rip), %xmm1    # 0xf2760
movsd 0x86793(%rip), %xmm0    # 0xf17f0
callq 0x8620
movsd 0x86c86(%rip), %xmm2    # 0xf1cf0
divsd 0xf8(%r12), %xmm2
movsd 0x8(%r12), %xmm1
divsd %xmm1, %xmm2
divsd %xmm1, %xmm2
mulsd 0x8aacd(%rip), %xmm2    # 0xf5b58
movsd %xmm2, 0x18(%rsp)
movsd %xmm0, 0x8(%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0xa29e7(%rip), %xmm0    # 0x10da90
addsd 0x861af(%rip), %xmm0    # 0xf1260
divsd 0xa55e7(%rip), %xmm0    # 0x1106a0
movsd 0x86c0f(%rip), %xmm1    # 0xf1cd0
callq 0x8620
movsd 0x8aa52(%rip), %xmm1    # 0xf5b20
divsd 0x1018(%rbx), %xmm1
mulsd 0x18(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd 0x86178(%rip), %xmm1    # 0xf1260
divsd 0x1028(%rbx), %xmm1
callq 0x8620
movapd %xmm0, %xmm2
mulsd 0x8(%rsp), %xmm2
cmpw $0x4, 0x1060(%rbx)
jl 0x6b127
leaq 0xa9d8a(%rip), %rdi     # 0x114e9a
movapd %xmm2, %xmm0
movb $0x1, %al
movsd %xmm2, 0x8(%rsp)
callq 0x8030
movsd 0x8(%rsp), %xmm2
movsd (%rsp), %xmm1
ucomisd 0xa555c(%rip), %xmm1    # 0x110690
movsd 0x10(%rsp), %xmm3
jne 0x6b13e
jnp 0x6b1bc
movsd 0x100(%r12), %xmm0
subsd 0x18(%r12), %xmm0
andpd 0x860e9(%rip), %xmm0    # 0xf1240
ucomisd 0x88e51(%rip), %xmm0    # 0xf3fb0
jbe 0x6b1bc
leaq 0xa9d6a(%rip), %rsi     # 0x114ed2
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c2c
leaq 0x85f01(%rip), %rsi     # 0xf1082
leaq 0xa9df5(%rip), %rdx     # 0x114f7d
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x30c2c
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x85e8c(%rip), %rsi     # 0xf1034
leaq 0xa9e0e(%rip), %rdx     # 0x114fbd
movq %rbx, %rdi
movl $0x1232, %ecx           # imm = 0x1232
jmp 0x6b431
minsd %xmm1, %xmm2
ucomisd 0xa54c8(%rip), %xmm2    # 0x110690
jne 0x6b1cc
jnp 0x6b21d
movw $0x1, 0x60(%r15)
mulsd 0x86b45(%rip), %xmm2    # 0xf1d20
movsd 0x258(%r14), %xmm0
addsd 0x260(%r14), %xmm0
mulsd 0x88dc3(%rip), %xmm0    # 0xf3fb8
maxsd %xmm2, %xmm0
movsd %xmm0, 0x68(%r15)
cmpw $0x4, 0x1060(%rbx)
jl 0x6b21d
leaq 0xa9dc9(%rip), %rdi     # 0x114fd9
movb $0x1, %al
callq 0x8030
movsd 0x10(%rsp), %xmm3
cmpw $0x1, 0x60(%r15)
jne 0x6b2a1
movsd 0x68(%r15), %xmm0
movsd (%r14), %xmm1
movapd %xmm0, %xmm2
mulsd %xmm1, %xmm2
ucomisd 0x86020(%rip), %xmm2    # 0xf1260
jbe 0x6b450
leaq 0xa9db8(%rip), %rsi     # 0x115005
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c2c
leaq 0x85e1c(%rip), %rsi     # 0xf1082
leaq 0xa9e19(%rip), %rdx     # 0x115086
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x30c2c
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x85da7(%rip), %rsi     # 0xf1034
leaq 0xa9d29(%rip), %rdx     # 0x114fbd
movq %rbx, %rdi
movl $0x1245, %ecx           # imm = 0x1245
jmp 0x6b431
maxsd 0x198(%r14), %xmm3
movsd %xmm3, 0x10(%rsp)
cmpw $0x3, 0x1060(%rbx)
jl 0x6b2d7
movsd 0x190(%r14), %xmm0
leaq 0xa9df3(%rip), %rdi     # 0x1150bd
movsd 0x10(%rsp), %xmm1
movb $0x2, %al
callq 0x8030
xorps %xmm0, %xmm0
cvtsi2sd %ebp, %xmm0
movsd %xmm0, (%rsp)
movsd 0x190(%r14), %xmm0
callq 0x82c0
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
callq 0x82c0
mulsd 0x8(%rsp), %xmm0
cvttsd2si %xmm0, %eax
cmpl %eax, %ebp
jg 0x6b349
movsd 0x190(%r14), %xmm0
callq 0x82c0
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%rsp)
movsd 0x10(%rsp), %xmm0
callq 0x82c0
mulsd (%rsp), %xmm0
cvttsd2si %xmm0, %ebp
movsd 0x10(%rsp), %xmm3
movsd %xmm3, 0x190(%r14)
movl %ebp, 0x1ac(%r14)
movsd (%r14), %xmm0
mulsd %xmm3, %xmm0
ucomisd 0x85ef0(%rip), %xmm0    # 0xf1260
jbe 0x6b3ca
leaq 0xa9d8a(%rip), %rsi     # 0x115103
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c2c
leaq 0x85cf0(%rip), %rsi     # 0xf1082
leaq 0xa9df9(%rip), %rdx     # 0x115192
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x30c2c
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x85c7b(%rip), %rsi     # 0xf1034
leaq 0xa9bfd(%rip), %rdx     # 0x114fbd
movq %rbx, %rdi
movl $0x125a, %ecx           # imm = 0x125A
jmp 0x6b431
movsd 0x278(%r14), %xmm0
xorl %eax, %eax
ucomisd %xmm3, %xmm0
jbe 0x6b440
leaq 0xa9de1(%rip), %rsi     # 0x1151c3
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x30c2c
leaq 0x85c87(%rip), %rsi     # 0xf1082
leaq 0xa61d0(%rip), %rdx     # 0x1115d2
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x30c2c
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x85c12(%rip), %rsi     # 0xf1034
leaq 0xa9b94(%rip), %rdx     # 0x114fbd
movq %rbx, %rdi
movl $0x125d, %ecx           # imm = 0x125D
movq %r15, %r8
xorl %eax, %eax
callq 0x30c2c
movl $0x1, %eax
addq $0x1020, %rsp           # imm = 0x1020
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
mulsd 0x868c8(%rip), %xmm0    # 0xf1d20
movsd 0x85e00(%rip), %xmm2    # 0xf1260
divsd %xmm1, %xmm2
addsd 0x872ec(%rip), %xmm2    # 0xf2758
minsd %xmm2, %xmm0
ucomisd %xmm3, %xmm0
jbe 0x6b2aa
movapd %xmm0, %xmm3
jmp 0x6b2aa