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

  /** - define local variables */
  /* Index of current approximation scheme */
  int index_ap;
  /* number of time intervals of one approximation scheme */
  int interval_number;
  /* index running over such time intervals */
  int index_interval;
  /* edge of intervals where approximation scheme is uniform: z_ini, z_switch_1, ..., z_end */
  double * interval_limit;
  /* other z sampling variables */
  int i;
  double * mz_output;

  /* contains all fixed parameters which should be passed to thermodynamics_derivs */
  struct thermodynamics_parameters_and_workspace tpaw;

  /* function pointer to ODE evolver and names of possible evolvers. */
  extern int evolver_rk(EVOLVER_PROTOTYPE);
  extern int evolver_ndf15(EVOLVER_PROTOTYPE);
  int (*generic_evolver)(EVOLVER_PROTOTYPE) = evolver_ndf15;

  /** - choose evolver */
  switch (ppr->thermo_evolver) {
  case rk:
    generic_evolver = evolver_rk;
    break;
  case ndf15:
    generic_evolver = evolver_ndf15;
    break;
  }

  /** - define the fields of the 'thermodynamics parameter and workspace' structure */
  tpaw.pba = pba;
  tpaw.ppr = ppr;
  tpaw.pth = pth;
  tpaw.pvecback = pvecback;
  tpaw.ptw = ptw;

  /** - define time sampling: create a local array of minus z values
      called mz (from mz=-zinitial growing towards mz=0) */

  class_alloc(mz_output,pth->tt_size*sizeof(double), pth->error_message);
  for (i=0; i < pth->tt_size; ++i) {
    mz_output[i] = -pth->z_table[pth->tt_size-1-i];
  }

  /** - define intervals for each approximation scheme */

  /* create the array of interval limits */
  class_alloc(interval_limit,(ptw->ptdw->ap_size+1)*sizeof(double),pth->error_message);
  /* fix interval number to number of approximations */
  interval_number = ptw->ptdw->ap_size;
  /* integration starts at z_ini and ends at z_end */
  interval_limit[0]= mz_output[0];
  interval_limit[ptw->ptdw->ap_size] = mz_output[ptw->Nz_tot-1];
  /* each interval ends with the proper ending redshift of its approximation */
  for (index_ap=0; index_ap < ptw->ptdw->ap_size-1; index_ap++) {
    interval_limit[index_ap+1] = -ptw->ptdw->ap_z_limits[index_ap];
  }

  /** - loop over intervals over which approximation scheme is
      uniform. For each interval: */

  for (index_interval=0; index_interval<interval_number; index_interval++) {

    /** - --> (a) fix current approximation scheme. */

    ptw->ptdw->ap_current = index_interval;

    /** - --> (b) define the vector of quantities to be integrated
        over. If the current interval starts from the
        initial time zinitial, fill the vector with initial
        conditions. If it starts from an approximation
        switching point, redistribute correctly the values
        from the previous to the new vector. For both
        RECFAST and HYREC, the vector consists of Tmat, x_H,
        x_He, + others for exotic models */

    class_call(thermodynamics_vector_init(ppr,
                                          pba,
                                          pth,
                                          interval_limit[index_interval],
                                          ptw),
               pth->error_message,
               pth->error_message);

    /* find the value of last_index_back at z = - interval_limit[index_interval], in order to speed up
       subsequent interpolations in thermodynamics_derivs */
    class_call(background_at_z(pba,
                               -interval_limit[index_interval],
                               normal_info,
                               inter_normal,
                               &(ptw->last_index_back),
                               pvecback),
               pba->error_message,
               pth->error_message);

    /** - --> (c1) If we have the optical depth tau_reio as input the
        last evolver step (reionization approximation) is done
        separately in a loop, to find the approximate redshift of
        reionization given the input of tau_reio, using a bisection
        method. This is similar to the general CLASS shooting method,
        but doing this step here is more advantageous since we only
        need to do repeatedly the last approximation step of the
        integration, instead of the full background and thermodynamics
        module */
    if ((pth->reio_z_or_tau == reio_tau) && (index_interval == ptw->ptdw->index_ap_reio)) {

      class_call(thermodynamics_reionization_evolve_with_tau(&tpaw,
                                                             interval_limit[index_interval],
                                                             interval_limit[index_interval+1],
                                                             mz_output,
                                                             pth->tt_size),
                 pth->error_message,
                 pth->error_message);
    }

    /** --> (c2) otherwise, just integrate quantities over the current interval. */
    else{

      class_call(generic_evolver(thermodynamics_derivs,
                                 interval_limit[index_interval],
                                 interval_limit[index_interval+1],
                                 ptw->ptdw->ptv->y,
                                 ptw->ptdw->ptv->used_in_output,
                                 ptw->ptdw->ptv->ti_size,
                                 &tpaw,
                                 ppr->tol_thermo_integration,
                                 ppr->smallest_allowed_variation,
                                 thermodynamics_timescale,  // timescale
                                 ppr->thermo_integration_stepsize, // stepsize = this number * timescale
                                 mz_output, // values of z for output
                                 pth->tt_size, // size of previous array
                                 thermodynamics_sources, // function for output
                                 NULL, // print variables
                                 pth->error_message),
                 pth->error_message,
                 pth->error_message);
    }

  }

  /** - Compute reionization optical depth, if not supplied as input parameter */
  if (pth->reio_z_or_tau == reio_z) {

    class_call(thermodynamics_reionization_get_tau(ppr,
                                                   pba,
                                                   pth,
                                                   ptw),
               pth->error_message,
               pth->error_message);

    pth->tau_reio=ptw->reionization_optical_depth;

  }

  /** - free quantities allocated at the beginning of the routine */
  if (ptw->ptdw->ap_size != 0) {
    class_call(thermodynamics_vector_free(ptw->ptdw->ptv),
               pth->error_message,
               pth->error_message);
  }

  free(interval_limit);
  free(mz_output);

  return _SUCCESS_;

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x40d8, %rsp           # imm = 0x40D8
movq %rdi, 0x40c8(%rsp)
movq %rsi, 0x40c0(%rsp)
movq %rdx, 0x40b8(%rsp)
movq %rcx, 0x40b0(%rsp)
movq %r8, 0x40a8(%rsp)
leaq -0xaa1bc(%rip), %rax    # 0xf540
movq %rax, 0x4050(%rsp)
movq 0x40c8(%rsp), %rax
movl 0x1b0(%rax), %eax
movl %eax, 0x2c(%rsp)
testl %eax, %eax
je 0xb9727
jmp 0xb971c
movl 0x2c(%rsp), %eax
subl $0x1, %eax
je 0xb9738
jmp 0xb9747
leaq -0xaac6e(%rip), %rax    # 0xeac0
movq %rax, 0x4050(%rsp)
jmp 0xb9747
leaq -0xaa1ff(%rip), %rax    # 0xf540
movq %rax, 0x4050(%rsp)
movq 0x40c0(%rsp), %rax
movq %rax, 0x4058(%rsp)
movq 0x40c8(%rsp), %rax
movq %rax, 0x4060(%rsp)
movq 0x40b8(%rsp), %rax
movq %rax, 0x4068(%rsp)
movq 0x40a8(%rsp), %rax
movq %rax, 0x4078(%rsp)
movq 0x40b0(%rsp), %rax
movq %rax, 0x4070(%rsp)
movq 0x40b8(%rsp), %rax
movslq 0xf08(%rax), %rdi
shlq $0x3, %rdi
callq 0x8460
movq %rax, 0x4080(%rsp)
cmpq $0x0, 0x4080(%rsp)
jne 0xb9841
movq 0x40b8(%rsp), %rax
movslq 0xf08(%rax), %rax
shlq $0x3, %rax
movl %eax, 0x404c(%rsp)
leaq 0x3840(%rsp), %rdi
movl 0x404c(%rsp), %ecx
leaq 0x118812(%rip), %rsi    # 0x1d2004
leaq 0x13972f(%rip), %rdx    # 0x1f2f28
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x3840(%rsp), %r8
leaq 0x118816(%rip), %rsi    # 0x1d2034
leaq 0x13970d(%rip), %rdx    # 0x1f2f32
movl $0x635, %ecx            # imm = 0x635
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
movl $0x0, 0x408c(%rsp)
movl 0x408c(%rsp), %eax
movq 0x40b8(%rsp), %rcx
cmpl 0xf08(%rcx), %eax
jge 0xb98d4
movq 0x40b8(%rsp), %rax
movq 0xf10(%rax), %rax
movq 0x40b8(%rsp), %rcx
movl 0xf08(%rcx), %ecx
subl $0x1, %ecx
subl 0x408c(%rsp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq 0x4080(%rsp), %rax
movslq 0x408c(%rsp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x408c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x408c(%rsp)
jmp 0xb984c
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movl 0x94(%rax), %eax
addl $0x1, %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x8460
movq %rax, 0x4090(%rsp)
cmpq $0x0, 0x4090(%rsp)
jne 0xb9999
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movl 0x94(%rax), %eax
addl $0x1, %eax
cltq
shlq $0x3, %rax
movl %eax, 0x383c(%rsp)
leaq 0x3030(%rsp), %rdi
movl 0x383c(%rsp), %ecx
leaq 0x1186ba(%rip), %rsi    # 0x1d2004
leaq 0x1395f6(%rip), %rdx    # 0x1f2f47
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x3030(%rsp), %r8
leaq 0x1186be(%rip), %rsi    # 0x1d2034
leaq 0x1395b5(%rip), %rdx    # 0x1f2f32
movl $0x63d, %ecx            # imm = 0x63D
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movl 0x94(%rax), %eax
movl %eax, 0x40a0(%rsp)
movq 0x4080(%rsp), %rax
movsd (%rax), %xmm0
movq 0x4090(%rsp), %rax
movsd %xmm0, (%rax)
movq 0x4080(%rsp), %rax
movq 0x40b0(%rsp), %rcx
movl 0x10(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x4090(%rsp), %rax
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
movslq 0x94(%rcx), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl $0x0, 0x40a4(%rsp)
movl 0x40a4(%rsp), %eax
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
movl 0x94(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0xb9aa6
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movq 0xa0(%rax), %rax
movslq 0x40a4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq 0x4090(%rsp), %rax
movl 0x40a4(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl 0x40a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40a4(%rsp)
jmp 0xb9a19
movl $0x0, 0x409c(%rsp)
movl 0x409c(%rsp), %eax
cmpl 0x40a0(%rsp), %eax
jge 0xb9ef0
movl 0x409c(%rsp), %ecx
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movl %ecx, 0x90(%rax)
movq 0x40c8(%rsp), %rdi
movq 0x40c0(%rsp), %rsi
movq 0x40b8(%rsp), %rdx
movq 0x4090(%rsp), %rax
movslq 0x409c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x40b0(%rsp), %rcx
callq 0xbad50
cmpl $0x1, %eax
jne 0xb9b8d
leaq 0x2830(%rsp), %rdi
movq 0x40b8(%rsp), %rcx
addq $0x1064, %rcx           # imm = 0x1064
leaq 0x11889a(%rip), %rsi    # 0x1d23d8
leaq 0x139411(%rip), %rdx    # 0x1f2f56
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x2830(%rsp), %r8
leaq 0x1184ca(%rip), %rsi    # 0x1d2034
leaq 0x1393c1(%rip), %rdx    # 0x1f2f32
movl $0x660, %ecx            # imm = 0x660
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
movq 0x40c0(%rsp), %rdi
movq 0x4090(%rsp), %rax
movslq 0x409c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movq 0x40b0(%rsp), %rcx
addq $0x78, %rcx
movq 0x40a8(%rsp), %r8
movl $0x1, %esi
xorl %edx, %edx
callq 0x9e4b0
cmpl $0x1, %eax
jne 0xb9c53
leaq 0x2030(%rsp), %rdi
movq 0x40c0(%rsp), %rcx
addq $0xd1c, %rcx            # imm = 0xD1C
leaq 0x1187d4(%rip), %rsi    # 0x1d23d8
leaq 0x13939a(%rip), %rdx    # 0x1f2fa5
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x2030(%rsp), %r8
leaq 0x118404(%rip), %rsi    # 0x1d2034
leaq 0x1392fb(%rip), %rdx    # 0x1f2f32
movl $0x66b, %ecx            # imm = 0x66B
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
movq 0x40b8(%rsp), %rax
cmpl $0x1, 0x1c(%rax)
jne 0xb9d50
movl 0x409c(%rsp), %eax
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
cmpl 0x8c(%rcx), %eax
jne 0xb9d50
movq 0x4090(%rsp), %rax
movslq 0x409c(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq 0x4090(%rsp), %rax
movl 0x409c(%rsp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm1
movq 0x4080(%rsp), %rsi
movq 0x40b8(%rsp), %rax
movl 0xf08(%rax), %edx
leaq 0x4058(%rsp), %rdi
callq 0xbc160
cmpl $0x1, %eax
jne 0xb9d4b
leaq 0x1830(%rsp), %rdi
movq 0x40b8(%rsp), %rcx
addq $0x1064, %rcx           # imm = 0x1064
leaq 0x1186dc(%rip), %rsi    # 0x1d23d8
leaq 0x139316(%rip), %rdx    # 0x1f3019
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x1830(%rsp), %r8
leaq 0x11830c(%rip), %rsi    # 0x1d2034
leaq 0x139203(%rip), %rdx    # 0x1f2f32
movl $0x67e, %ecx            # imm = 0x67E
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
jmp 0xb9ed8
movq 0x4050(%rsp), %rax
movq 0x4090(%rsp), %rcx
movslq 0x409c(%rsp), %rdx
movsd (%rcx,%rdx,8), %xmm0
movq 0x4090(%rsp), %rcx
movl 0x409c(%rsp), %edx
addl $0x1, %edx
movslq %edx, %rdx
movsd (%rcx,%rdx,8), %xmm1
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
movq 0xb8(%rcx), %rcx
movq 0x18(%rcx), %rsi
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
movq 0xb8(%rcx), %rcx
movq 0x28(%rcx), %rdx
movq 0x40b0(%rsp), %rcx
movq 0x80(%rcx), %rcx
movq 0xb8(%rcx), %rcx
movl (%rcx), %ecx
movq 0x40c8(%rsp), %rdi
movsd 0x1b8(%rdi), %xmm2
movq 0x40c8(%rsp), %rdi
movsd 0xa28(%rdi), %xmm3
movq 0x40c8(%rsp), %rdi
movsd 0x1c0(%rdi), %xmm4
movq 0x4080(%rsp), %r14
movq 0x40b8(%rsp), %rdi
movl 0xf08(%rdi), %ebx
movq 0x40b8(%rsp), %r10
addq $0x1064, %r10           # imm = 0x1064
leaq 0x3c71(%rip), %rdi      # 0xbdaa0
leaq 0x4058(%rsp), %r8
leaq 0x4e22(%rip), %r9       # 0xbec60
leaq 0x4f7b(%rip), %r11      # 0xbedc0
xorl %ebp, %ebp
movq %r14, (%rsp)
movl %ebx, 0x8(%rsp)
movq %r11, 0x10(%rsp)
movq $0x0, 0x18(%rsp)
movq %r10, 0x20(%rsp)
callq *%rax
cmpl $0x1, %eax
jne 0xb9ed6
leaq 0x1030(%rsp), %rdi
movq 0x40b8(%rsp), %rcx
addq $0x1064, %rcx           # imm = 0x1064
leaq 0x118551(%rip), %rsi    # 0x1d23d8
leaq 0x139219(%rip), %rdx    # 0x1f30a7
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x1030(%rsp), %r8
leaq 0x118181(%rip), %rsi    # 0x1d2034
leaq 0x139078(%rip), %rdx    # 0x1f2f32
movl $0x695, %ecx            # imm = 0x695
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
jmp 0xb9ed8
jmp 0xb9eda
movl 0x409c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x409c(%rsp)
jmp 0xb9ab1
movq 0x40b8(%rsp), %rax
cmpl $0x0, 0x1c(%rax)
jne 0xb9fb3
movq 0x40c8(%rsp), %rdi
movq 0x40c0(%rsp), %rsi
movq 0x40b8(%rsp), %rdx
movq 0x40b0(%rsp), %rcx
callq 0xbfa00
cmpl $0x1, %eax
jne 0xb9f99
leaq 0x830(%rsp), %rdi
movq 0x40b8(%rsp), %rcx
addq $0x1064, %rcx           # imm = 0x1064
leaq 0x11848e(%rip), %rsi    # 0x1d23d8
leaq 0x1392dd(%rip), %rdx    # 0x1f322e
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x830(%rsp), %r8
leaq 0x1180be(%rip), %rsi    # 0x1d2034
leaq 0x138fb5(%rip), %rdx    # 0x1f2f32
movl $0x6a2, %ecx            # imm = 0x6A2
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
movq 0x40b0(%rsp), %rax
movsd 0x70(%rax), %xmm0
movq 0x40b8(%rsp), %rax
movsd %xmm0, 0x20(%rax)
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
cmpl $0x0, 0x94(%rax)
je 0xba055
movq 0x40b0(%rsp), %rax
movq 0x80(%rax), %rax
movq 0xb8(%rax), %rdi
callq 0xbfe10
cmpl $0x1, %eax
jne 0xba053
leaq 0x30(%rsp), %rdi
movq 0x40b8(%rsp), %rcx
addq $0x1064, %rcx           # imm = 0x1064
leaq 0x1183ce(%rip), %rsi    # 0x1d23d8
leaq 0x139255(%rip), %rdx    # 0x1f3266
movb $0x0, %al
callq 0x5b9c0
movq 0x40b8(%rsp), %rdi
addq $0x1064, %rdi           # imm = 0x1064
leaq 0x30(%rsp), %r8
leaq 0x118001(%rip), %rsi    # 0x1d2034
leaq 0x138ef8(%rip), %rdx    # 0x1f2f32
movl $0x6ac, %ecx            # imm = 0x6AC
movb $0x0, %al
callq 0x5b9c0
movl $0x1, 0x40d4(%rsp)
jmp 0xba07a
jmp 0xba055
movq 0x4090(%rsp), %rdi
callq 0x8420
movq 0x4080(%rsp), %rdi
callq 0x8420
movl $0x0, 0x40d4(%rsp)
movl 0x40d4(%rsp), %eax
addq $0x40d8, %rsp           # imm = 0x40D8
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop