// File: /workspace/github_c_makefile_star2_O2/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 %rdi, %r14
movsd 0x190(%rdi), %xmm1
movl 0x1ac(%rdi), %ebp
andw $0x0, 0x60(%rcx)
movq %rdx, %rbx
cmpw $0x1, 0x4b6(%rsi)
jne 0x646c3
movq %rcx, %r15
movq %rsi, %r12
movsd 0xa048f(%rip), %xmm3    # 0x104570
cmpw $0x1, 0x36(%rbx)
movsd %xmm1, 0x10(%rsp)
jne 0x641e5
movl 0x1058(%rbx), %eax
cmpl $-0x1, %eax
jl 0x641e5
addl $0x2, %eax
cvtsi2sd %eax, %xmm0
movsd 0x81150(%rip), %xmm1    # 0xe5260
divsd %xmm0, %xmm1
movsd 0xa045c(%rip), %xmm0    # 0x104578
callq 0x8650
movsd %xmm0, (%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0x9d848(%rip), %xmm0    # 0x101980
movsd 0x81120(%rip), %xmm2    # 0xe5260
addsd %xmm2, %xmm0
divsd 0xa0434(%rip), %xmm0    # 0x104580
cvtsi2sdl 0x1058(%rbx), %xmm1
addsd %xmm1, %xmm1
addsd 0x84298(%rip), %xmm1    # 0xe83f8
divsd %xmm1, %xmm2
movapd %xmm2, %xmm1
callq 0x8650
mulsd (%rsp), %xmm0
movsd %xmm0, (%rsp)
movsd 0x1050(%rbx), %xmm0
mulsd 0xa0401(%rip), %xmm0    # 0x104588
cvtsi2sdl 0x1058(%rbx), %xmm2
addsd 0x81b49(%rip), %xmm2    # 0xe5ce0
movsd 0x81649(%rip), %xmm1    # 0xe57e8
divsd %xmm2, %xmm1
callq 0x8650
movapd %xmm0, %xmm3
mulsd (%rsp), %xmm3
cmpw $0x4, 0x1060(%rbx)
jl 0x641d7
leaq 0xa4b5a(%rip), %rdi     # 0x108d1c
movapd %xmm3, %xmm0
movb $0x1, %al
movsd %xmm3, (%rsp)
callq 0x8030
movsd (%rsp), %xmm3
minsd 0xa0391(%rip), %xmm3    # 0x104570
movsd 0x10(%rsp), %xmm1
cmpw $0x1, 0x34(%rbx)
jne 0x64398
cmpl $-0x2, 0x1038(%rbx)
jl 0x64398
movsd %xmm3, (%rsp)
movsd 0x1010(%rbx), %xmm0
divsd 0xa031e(%rip), %xmm0    # 0x104530
movsd %xmm0, 0x18(%rsp)
movsd 0xa0370(%rip), %xmm0    # 0x104590
divsd 0x1040(%rbx), %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0x9d740(%rip), %xmm0    # 0x101980
addsd 0x81018(%rip), %xmm0    # 0xe5260
divsd 0xa0330(%rip), %xmm0    # 0x104580
movsd 0x81a58(%rip), %xmm1    # 0xe5cb0
callq 0x8650
mulsd 0x8(%rsp), %xmm0
movsd 0xa032d(%rip), %xmm2    # 0x104598
divsd 0x20(%r12), %xmm2
movsd 0x8(%r12), %xmm1
divsd %xmm1, %xmm2
divsd %xmm1, %xmm2
mulsd %xmm2, %xmm0
movsd %xmm0, 0x8(%rsp)
cvtsi2sdl 0x1038(%rbx), %xmm1
addsd 0x80fc5(%rip), %xmm1    # 0xe5260
mulsd 0x81a0d(%rip), %xmm1    # 0xe5cb0
movsd 0x18(%rsp), %xmm0
callq 0x8650
mulsd 0x8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
cvtsi2sdl 0x1038(%rbx), %xmm1
movsd 0x18(%rsp), %xmm0
addsd 0x80f90(%rip), %xmm0    # 0xe5260
addsd 0x81510(%rip), %xmm1    # 0xe57e8
mulsd 0x819d0(%rip), %xmm1    # 0xe5cb0
callq 0x8650
movsd 0x8(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movl 0x1038(%rbx), %eax
leal -0x19(,%rax,4), %eax
cvtsi2sd %eax, %xmm1
movsd 0x814e2(%rip), %xmm0    # 0xe57f0
callq 0x8650
mulsd 0x8(%rsp), %xmm0
divsd 0x1030(%rbx), %xmm0
movl 0x1038(%rbx), %eax
addl $0x3, %eax
cvtsi2sd %eax, %xmm2
movsd 0x819aa(%rip), %xmm1    # 0xe5ce0
divsd %xmm2, %xmm1
callq 0x8650
movapd %xmm0, %xmm3
mulsd 0xa0255(%rip), %xmm3    # 0x1045a0
cmpl $-0x2, 0x1038(%rbx)
jne 0x6435c
mulsd 0x81494(%rip), %xmm3    # 0xe57f0
movsd (%rsp), %xmm0
cmpw $0x4, 0x1060(%rbx)
jl 0x6438e
leaq 0xa49e1(%rip), %rdi     # 0x108d53
movapd %xmm3, %xmm0
movb $0x1, %al
movsd %xmm3, 0x8(%rsp)
callq 0x8030
movsd 0x8(%rsp), %xmm3
movsd (%rsp), %xmm0
minsd %xmm0, %xmm3
movsd 0x10(%rsp), %xmm1
cmpw $0x1, 0x38(%rbx)
jne 0x6453d
movsd 0x1028(%rbx), %xmm0
xorpd %xmm2, %xmm2
ucomisd %xmm2, %xmm0
jbe 0x6453d
movsd %xmm3, (%rsp)
movsd 0x82282(%rip), %xmm1    # 0xe6648
divsd %xmm0, %xmm1
addsd 0x8236e(%rip), %xmm1    # 0xe6740
movsd 0x81416(%rip), %xmm0    # 0xe57f0
callq 0x8650
movsd 0x818e9(%rip), %xmm2    # 0xe5cd0
divsd 0xf8(%r12), %xmm2
movsd 0x8(%r12), %xmm1
divsd %xmm1, %xmm2
divsd %xmm1, %xmm2
mulsd 0x85640(%rip), %xmm2    # 0xe9a48
movsd %xmm2, 0x18(%rsp)
movsd %xmm0, 0x8(%rsp)
movsd 0x328(%r12), %xmm0
mulsd 0x9d55a(%rip), %xmm0    # 0x101980
addsd 0x80e32(%rip), %xmm0    # 0xe5260
divsd 0xa014a(%rip), %xmm0    # 0x104580
movsd 0x81872(%rip), %xmm1    # 0xe5cb0
callq 0x8650
movsd 0x855c5(%rip), %xmm1    # 0xe9a10
divsd 0x1018(%rbx), %xmm1
mulsd 0x18(%rsp), %xmm0
mulsd %xmm1, %xmm0
movsd 0x80dfb(%rip), %xmm1    # 0xe5260
divsd 0x1028(%rbx), %xmm1
callq 0x8650
movapd %xmm0, %xmm3
mulsd 0x8(%rsp), %xmm3
cmpw $0x4, 0x1060(%rbx)
jl 0x644a4
leaq 0xa48fd(%rip), %rdi     # 0x108d8a
movapd %xmm3, %xmm0
movb $0x1, %al
movsd %xmm3, 0x8(%rsp)
callq 0x8030
movsd 0x8(%rsp), %xmm3
movsd (%rsp), %xmm2
ucomisd 0xa00bf(%rip), %xmm2    # 0x104570
movsd 0x10(%rsp), %xmm1
jne 0x644bb
jnp 0x64539
movsd 0x100(%r12), %xmm0
subsd 0x18(%r12), %xmm0
andpd 0x80d6c(%rip), %xmm0    # 0xe5240
ucomisd 0x83aa4(%rip), %xmm0    # 0xe7f80
jbe 0x64539
leaq 0xa48dd(%rip), %rsi     # 0x108dc2
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x80b84(%rip), %rsi     # 0xe5082
leaq 0xa4968(%rip), %rdx     # 0x108e6d
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x80b0f(%rip), %rsi     # 0xe5034
leaq 0xa4981(%rip), %rdx     # 0x108ead
movq %rbx, %rdi
movl $0x1232, %ecx           # imm = 0x1232
jmp 0x647a5
minsd %xmm2, %xmm3
ucomisd 0xa002b(%rip), %xmm3    # 0x104570
jne 0x64549
jnp 0x6459a
movw $0x1, 0x60(%r15)
mulsd 0x817a8(%rip), %xmm3    # 0xe5d00
movsd 0x258(%r14), %xmm0
addsd 0x260(%r14), %xmm0
mulsd 0x83a16(%rip), %xmm0    # 0xe7f88
maxsd %xmm3, %xmm0
movsd %xmm0, 0x68(%r15)
cmpw $0x4, 0x1060(%rbx)
jl 0x6459a
leaq 0xa493c(%rip), %rdi     # 0x108ec9
movb $0x1, %al
callq 0x8030
movsd 0x10(%rsp), %xmm1
cmpw $0x1, 0x60(%r15)
jne 0x6461e
movsd 0x68(%r15), %xmm0
movsd (%r14), %xmm3
movapd %xmm0, %xmm2
mulsd %xmm3, %xmm2
ucomisd 0x80ca3(%rip), %xmm2    # 0xe5260
jbe 0x647c2
leaq 0xa492b(%rip), %rsi     # 0x108ef5
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x80a9f(%rip), %rsi     # 0xe5082
leaq 0xa498c(%rip), %rdx     # 0x108f76
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x80a2a(%rip), %rsi     # 0xe5034
leaq 0xa489c(%rip), %rdx     # 0x108ead
movq %rbx, %rdi
movl $0x1245, %ecx           # imm = 0x1245
jmp 0x647a5
maxsd 0x198(%r14), %xmm1
cmpw $0x3, 0x1060(%rbx)
movsd 0x190(%r14), %xmm0
movsd %xmm1, 0x10(%rsp)
jl 0x64657
leaq 0xa4966(%rip), %rdi     # 0x108fad
movb $0x2, %al
callq 0x8030
movsd 0x190(%r14), %xmm0
cvtsi2sd %ebp, %xmm1
movsd %xmm1, (%rsp)
callq 0x82e0
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movsd 0x10(%rsp), %xmm0
callq 0x82e0
mulsd 0x8(%rsp), %xmm0
cvttsd2si %xmm0, %eax
cmpl %eax, %ebp
jg 0x646bd
movsd 0x190(%r14), %xmm0
callq 0x82e0
movsd (%rsp), %xmm1
divsd %xmm0, %xmm1
movsd %xmm1, (%rsp)
movsd 0x10(%rsp), %xmm0
callq 0x82e0
mulsd (%rsp), %xmm0
cvttsd2si %xmm0, %ebp
movsd 0x10(%rsp), %xmm1
movsd %xmm1, 0x190(%r14)
movl %ebp, 0x1ac(%r14)
movsd (%r14), %xmm0
mulsd %xmm1, %xmm0
ucomisd 0x80b7c(%rip), %xmm0    # 0xe5260
jbe 0x6473e
leaq 0xa4906(%rip), %rsi     # 0x108ff3
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x8097c(%rip), %rsi     # 0xe5082
leaq 0xa4975(%rip), %rdx     # 0x109082
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x80907(%rip), %rsi     # 0xe5034
leaq 0xa4779(%rip), %rdx     # 0x108ead
movq %rbx, %rdi
movl $0x125a, %ecx           # imm = 0x125A
jmp 0x647a5
movsd 0x278(%r14), %xmm0
xorl %eax, %eax
ucomisd %xmm1, %xmm0
jbe 0x647b2
leaq 0xa495d(%rip), %rsi     # 0x1090b3
leaq 0x820(%rsp), %r14
movq %r14, %rdi
xorl %eax, %eax
callq 0x2e014
leaq 0x80913(%rip), %rsi     # 0xe5082
leaq 0xa0d4c(%rip), %rdx     # 0x1054c2
leaq 0x20(%rsp), %r15
movq %r15, %rdi
movq %r14, %rcx
xorl %eax, %eax
callq 0x2e014
addq $0x1064, %rbx           # imm = 0x1064
leaq 0x8089e(%rip), %rsi     # 0xe5034
leaq 0xa4710(%rip), %rdx     # 0x108ead
movq %rbx, %rdi
movl $0x125d, %ecx           # imm = 0x125D
movq %r15, %r8
xorl %eax, %eax
callq 0x2e014
pushq $0x1
popq %rax
addq $0x1020, %rsp           # imm = 0x1020
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
mulsd 0x81536(%rip), %xmm0    # 0xe5d00
movsd 0x80a8e(%rip), %xmm2    # 0xe5260
divsd %xmm3, %xmm2
addsd 0x81f5a(%rip), %xmm2    # 0xe6738
minsd %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x64627
movapd %xmm0, %xmm1
jmp 0x64627