// File: /workspace/github_cpp_makefile_star2_O2/TBody[P]atomicpp/Prad.cpp
// Function: computeIonisationDistribution(atomicpp::ImpuritySpecies&, double, double, double, double)
std::vector<double> computeIonisationDistribution(atomicpp::ImpuritySpecies& impurity, double Te, double Ne, double Nz, double Nn){

	int Z = impurity.get_atomic_number();
	std::vector<double> iz_stage_distribution(Z+1);

	// std::set GS density equal to 1 (arbitrary)
	iz_stage_distribution[0] = 1;
	double sum_iz = 1;

	// Loop over 0, 1, ..., Z-1
	// Each charge state is std::set in terms of the density of the previous
	for(int k=0; k<Z; ++k){
		// Ionisation
		// Get the atomicpp::RateCoefficient from the rate_coefficient std::map (atrribute of impurity)
		std::shared_ptr<atomicpp::RateCoefficient> iz_rate_coefficient = impurity.get_rate_coefficient("ionisation");
		// Evaluate the atomicpp::RateCoefficient at the point
		double k_iz_evaluated = iz_rate_coefficient->call0D(k, Te, Ne);

		// Recombination
		// Get the atomicpp::RateCoefficient from the rate_coefficient std::map (atrribute of impurity)
		std::shared_ptr<atomicpp::RateCoefficient> rec_rate_coefficient = impurity.get_rate_coefficient("recombination");
		// Evaluate the atomicpp::RateCoefficient at the point
		double k_rec_evaluated = rec_rate_coefficient->call0D(k, Te, Ne);

		// The ratio of ionisation from the (k)th stage and recombination from the (k+1)th std::sets the equilibrium densities
		// of the (k+1)th stage in terms of the (k)th (since R = Nz * Ne * rate_coefficient) N.b. Since there is no
		// ionisation from the bare nucleus, and no recombination onto the neutral (ignoring anion formation) the 'k'
		// value of ionisation coeffs is shifted down  by one relative to the recombination coeffs - therefore this
		// evaluation actually gives the balance

		iz_stage_distribution[k+1] = iz_stage_distribution[k] * (k_iz_evaluated/k_rec_evaluated);
		sum_iz += iz_stage_distribution[k+1];
	}

	// # Normalise such that the sum over all ionisation stages is '1' at all points
	for(int k=0; k<=Z; ++k){
		iz_stage_distribution[k] = iz_stage_distribution[k] / sum_iz;
	}
	return iz_stage_distribution;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movsd %xmm1, -0x58(%rbp)
movsd %xmm0, -0x50(%rbp)
movq %rdi, %rbx
movq %rsi, -0x60(%rbp)
movq %rsi, %rdi
callq 0xbf0c
movl %eax, %r14d
leal 0x1(%r14), %eax
movslq %eax, %r15
leaq -0xb0(%rbp), %r12
movq %r12, %rdi
callq 0x531c
movq %rbx, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0x5326
movq %r12, %rdi
callq 0x5a64
xorl %r13d, %r13d
movq %rbx, -0x40(%rbp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x537c
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax)
testl %r14d, %r14d
movl $0x0, %eax
cmovgl %r14d, %eax
movq %rax, -0x68(%rbp)
movsd 0x1c59a(%rip), %xmm0    # 0x21008
movsd %xmm0, -0x48(%rbp)
leaq -0x80(%rbp), %r15
cmpq %r13, -0x68(%rbp)
je 0x4bae
movq %r15, %rdi
callq 0x4540
movq %r12, %rdi
leaq 0x1c5ad(%rip), %rsi     # 0x21040
movq %r15, %rdx
callq 0x4160
leaq -0x90(%rbp), %rbx
movq %rbx, %rdi
movq -0x60(%rbp), %rsi
movq %r12, %rdx
callq 0xbf68
movq %r12, %rdi
callq 0x41a0
movq %r15, %rdi
callq 0x58aa
movq %rbx, %rdi
callq 0x538e
movq %rax, %rdi
movl %r13d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
callq 0x10f96
movsd %xmm0, -0x38(%rbp)
leaq -0x29(%rbp), %rbx
movq %rbx, %rdi
callq 0x4540
movq %r12, %rdi
leaq 0x1c552(%rip), %rsi     # 0x2104b
movq %rbx, %rdx
callq 0x4160
movq %r15, %rdi
movq -0x60(%rbp), %rsi
movq %r12, %rdx
callq 0xbf68
movq %r12, %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58aa
movq %r15, %rdi
callq 0x538e
movq %rax, %rdi
movl %r13d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x58(%rbp), %xmm1
callq 0x10f96
movsd %xmm0, -0x70(%rbp)
movq -0x40(%rbp), %rbx
movq %rbx, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x38(%rbp), %xmm0
divsd -0x70(%rbp), %xmm0
mulsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
incq %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
movq %rbx, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x48(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
movq %r15, %rdi
callq 0x5398
leaq -0x90(%rbp), %rdi
callq 0x5398
jmp 0x4a77
movslq %r14d, %r15
xorl %r14d, %r14d
movq -0x40(%rbp), %rbx
cmpq %r15, %r14
jg 0x4bef
movq %rbx, %rdi
movq %r14, %rsi
callq 0x537c
movsd (%rax), %xmm0
divsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x537c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %r14
jmp 0x4bb8
movq %rbx, %rax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq -0xb0(%rbp), %rdi
callq 0x5a64
jmp 0x4c79
movq %rax, %r14
jmp 0x4c45
movq %rax, %r14
jmp 0x4c2e
movq %rax, %r14
leaq -0xb0(%rbp), %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58aa
jmp 0x4c45
movq %rax, %r14
leaq -0x80(%rbp), %rdi
callq 0x5398
leaq -0x90(%rbp), %rdi
callq 0x5398
jmp 0x4c70
movq %rax, %r14
jmp 0x4c67
movq %rax, %r14
leaq -0xb0(%rbp), %rdi
callq 0x41a0
leaq -0x80(%rbp), %rdi
callq 0x58aa
movq -0x40(%rbp), %rdi
callq 0x53a6
movq %r14, %rdi
callq 0x45a0