// File: /workspace/github_cpp_makefile_star2_O2/TBody[P]atomicpp/atomicpp/ImpuritySpecies.cpp
// Function: atomicpp::ImpuritySpecies::calculateNzk(double, double, double, double)
std::vector<double> ImpuritySpecies::calculateNzk(double Te, double Ne, double Nz, double Nn){
		// Calculates the relative distribution across ionisation stages of the impurity by assuming collisional-radiative
		// equilbrium. This is then used to calculate the density within each state, allowing the total power at a point
		// to be evaluated
		// std::cout << "Called for Te = " << Te << ", Ne = " << Ne << ", Nz = " << Nz << ", Nn = " << Nn << std::endl;

		int Z = 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 RateCoefficient from the rate_coefficient std::map (atrribute of impurity)
			std::shared_ptr<RateCoefficient> iz_rate_coefficient = rate_coefficients["ionisation"];
			// Evaluate the RateCoefficient at the point
			double k_iz_evaluated = iz_rate_coefficient->call0D(k, Te, Ne);

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

			std::shared_ptr<RateCoefficient> cx_rate_coefficient = rate_coefficients["cx_rec"];
			// Evaluate the RateCoefficient at the point
			double k_cx_evaluated = cx_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*Ne/(k_rec_evaluated*Ne + k_cx_evaluated*Nn));
			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;
		}

		std::vector<double> Nzk(Z+1);
		for(int k=0; k<=Z; ++k){
			Nzk[k] = iz_stage_distribution[k]*Nz;
		}
		return Nzk;
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xd8, %rsp
movsd %xmm3, -0xb0(%rbp)
movsd %xmm2, -0xb8(%rbp)
movsd %xmm1, -0x38(%rbp)
movsd %xmm0, -0x50(%rbp)
movq %rdi, -0xa8(%rbp)
movq %rsi, -0x40(%rbp)
movslq 0x48(%rsi), %r14
leaq 0x1(%r14), %r12
leaq -0x90(%rbp), %rbx
movq %rbx, %rdi
callq 0x531c
leaq -0x70(%rbp), %rdi
movq %r12, -0xa0(%rbp)
movq %r12, %rsi
movq %rbx, %rdx
callq 0x5326
leaq -0x90(%rbp), %r12
movq %r12, %rdi
callq 0x5a64
xorl %r13d, %r13d
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
callq 0x537c
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax)
addq $0x88, -0x40(%rbp)
testl %r14d, %r14d
movl $0x0, %eax
movq %r14, -0x98(%rbp)
cmovgl %r14d, %eax
movq %rax, -0xc0(%rbp)
movsd 0x14fb8(%rip), %xmm0    # 0x21008
movsd %xmm0, -0x48(%rbp)
leaq -0xf0(%rbp), %r14
cmpq %r13, -0xc0(%rbp)
je 0xc24f
leaq -0xe0(%rbp), %rbx
movq %rbx, %rdi
callq 0x4540
movq %r12, %rdi
leaq 0x14fbe(%rip), %rsi     # 0x21040
movq %rbx, %rdx
callq 0x4160
movq %r14, %r15
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0xcf52
leaq -0x100(%rbp), %r14
movq %r14, %rdi
movq %rax, %rsi
callq 0xcf48
movq %r12, %rdi
callq 0x41a0
movq %rbx, %rdi
callq 0x58aa
movq %r14, %rdi
callq 0x538e
movq %rax, %rdi
movl %r13d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x10f96
movsd %xmm0, -0x58(%rbp)
movq %r15, %r14
movq %r15, %rdi
callq 0x4540
movq %r12, %rdi
leaq 0x14f59(%rip), %rsi     # 0x2104b
movq %r15, %rdx
callq 0x4160
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0xcf52
movq %rbx, %rdi
movq %rax, %rsi
callq 0xcf48
movq %r12, %rdi
callq 0x41a0
movq %r14, %rdi
callq 0x58aa
movq %rbx, %rdi
callq 0x538e
movq %rax, %rdi
movl %r13d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x10f96
movsd %xmm0, -0xd0(%rbp)
leaq -0x29(%rbp), %rbx
movq %rbx, %rdi
callq 0x4540
movq %r12, %rdi
leaq 0x1664d(%rip), %rsi     # 0x227a9
movq %rbx, %rdx
callq 0x4160
movq -0x40(%rbp), %rdi
movq %r12, %rsi
callq 0xcf52
movq %r14, %rdi
movq %rax, %rsi
callq 0xcf48
movq %r12, %rdi
callq 0x41a0
movq %rbx, %rdi
callq 0x58aa
movq %r14, %rdi
callq 0x538e
movq %rax, %rdi
movl %r13d, %esi
movsd -0x50(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x10f96
movsd %xmm0, -0xc8(%rbp)
leaq -0x70(%rbp), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x58(%rbp), %xmm1
movsd -0x38(%rbp), %xmm2
mulsd %xmm2, %xmm1
movsd -0xc8(%rbp), %xmm3
mulsd -0xb0(%rbp), %xmm3
movsd -0xd0(%rbp), %xmm0
mulsd %xmm2, %xmm0
addsd %xmm3, %xmm0
divsd %xmm0, %xmm1
mulsd (%rax), %xmm1
movsd %xmm1, -0x58(%rbp)
incq %r13
movq %r15, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x58(%rbp), %xmm0
movsd %xmm0, (%rax)
movq %r15, %rdi
movq %r13, %rsi
callq 0x537c
movsd -0x48(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
movq %r14, %rdi
callq 0x5398
leaq -0xe0(%rbp), %rdi
callq 0x5398
leaq -0x100(%rbp), %rdi
callq 0x5398
jmp 0xc05c
xorl %ebx, %ebx
leaq -0x70(%rbp), %r14
movq -0xa8(%rbp), %r15
movq -0x98(%rbp), %r12
cmpq %r12, %rbx
jg 0xc29a
movq %r14, %rdi
movq %rbx, %rsi
callq 0x537c
movsd (%rax), %xmm0
divsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x537c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %rbx
jmp 0xc263
leaq -0x90(%rbp), %rbx
movq %rbx, %rdi
callq 0x531c
movq %r15, %rdi
movq -0xa0(%rbp), %rsi
movq %rbx, %rdx
callq 0x5326
leaq -0x90(%rbp), %rdi
callq 0x5a64
xorl %ebx, %ebx
leaq -0x70(%rbp), %r14
cmpq %r12, %rbx
jg 0xc307
movq %r14, %rdi
movq %rbx, %rsi
callq 0x537c
movsd (%rax), %xmm0
mulsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0x537c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %rbx
jmp 0xc2cd
leaq -0x70(%rbp), %rdi
callq 0x53a6
movq %r15, %rax
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x5a64
jmp 0xc3e1
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x5a64
jmp 0xc3ea
movq %rax, %rbx
jmp 0xc380
movq %rax, %rbx
jmp 0xc366
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58aa
jmp 0xc380
movq %rax, %rbx
leaq -0xf0(%rbp), %rdi
callq 0x5398
leaq -0xe0(%rbp), %rdi
callq 0x5398
jmp 0xc3d5
movq %rax, %rbx
jmp 0xc3a2
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x41a0
leaq -0xe0(%rbp), %rdi
callq 0x58aa
jmp 0xc3e1
movq %rax, %rbx
jmp 0xc3d5
movq %rax, %rbx
jmp 0xc3c9
movq %rax, %rbx
leaq -0x90(%rbp), %rdi
callq 0x41a0
leaq -0xf0(%rbp), %rdi
callq 0x58aa
leaq -0x100(%rbp), %rdi
callq 0x5398
leaq -0x70(%rbp), %rdi
callq 0x53a6
movq %rbx, %rdi
callq 0x45a0