// File: /workspace/github_cpp_makefile_star2_O1/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 $0xc8, %rsp
movsd %xmm3, -0xb8(%rbp)
movsd %xmm2, -0xc0(%rbp)
movsd %xmm1, -0x38(%rbp)
movsd %xmm0, -0x48(%rbp)
movq %rsi, %r15
movq %rdi, %r12
movslq 0x48(%rsi), %r14
leaq 0x1(%r14), %r13
leaq -0x88(%rbp), %rbx
movq %rbx, %rdi
callq 0x533c
leaq -0xa0(%rbp), %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x5346
movq %r13, -0xa8(%rbp)
movq %r12, -0xb0(%rbp)
movl %r14d, %ebx
leaq -0x88(%rbp), %rdi
callq 0x5a80
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
callq 0x539c
movabsq $0x3ff0000000000000, %rcx # imm = 0x3FF0000000000000
movq %rcx, (%rax)
movq %rbx, -0x58(%rbp)
testl %ebx, %ebx
jle 0xc4cf
addq $0x88, %r15
movsd 0x15d3e(%rip), %xmm0    # 0x22008
movsd %xmm0, -0x40(%rbp)
xorl %r12d, %r12d
leaq -0x68(%rbp), %r13
leaq -0xe0(%rbp), %r14
movq %r13, %rdi
callq 0x4540
leaq -0x88(%rbp), %rbx
movq %rbx, %rdi
leaq 0x15d4a(%rip), %rsi     # 0x22040
movq %r13, %rdx
callq 0x4160
movq %r15, %r13
movq %r15, %rdi
movq %rbx, %rsi
callq 0xd1fc
leaq -0xf0(%rbp), %r15
movq %r15, %rdi
movq %rax, %rsi
callq 0xd1f2
movq %rbx, %rdi
callq 0x41a0
leaq -0x68(%rbp), %rdi
callq 0x58c6
movq %r15, %rdi
callq 0x53ae
movq %rax, %rdi
movl %r12d, %esi
movsd -0x48(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x1136e
movsd %xmm0, -0x50(%rbp)
movq %r14, %rdi
callq 0x4540
movq %rbx, %rdi
leaq 0x15ce8(%rip), %rsi     # 0x2204b
movq %r14, %rdx
callq 0x4160
movq %r13, %r15
movq %r13, %rdi
movq %rbx, %rsi
callq 0xd1fc
leaq -0x68(%rbp), %r13
movq %r13, %rdi
movq %rax, %rsi
callq 0xd1f2
movq %rbx, %rdi
callq 0x41a0
movq %r14, %rdi
callq 0x58c6
movq %r13, %rdi
callq 0x53ae
movq %rax, %rdi
movl %r12d, %esi
movsd -0x48(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x1136e
movsd %xmm0, -0xd0(%rbp)
leaq -0x29(%rbp), %r13
movq %r13, %rdi
callq 0x4540
movq %rbx, %rdi
leaq 0x173d6(%rip), %rsi     # 0x237a9
movq %r13, %rdx
callq 0x4160
movq %r15, %rdi
movq %rbx, %rsi
callq 0xd1fc
movq %r14, %rdi
movq %rax, %rsi
callq 0xd1f2
movq %rbx, %rdi
callq 0x41a0
movq %r13, %rdi
callq 0x58c6
movq %r14, %rdi
callq 0x53ae
movq %rax, %rdi
movl %r12d, %esi
movsd -0x48(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
callq 0x1136e
movsd %xmm0, -0xc8(%rbp)
leaq -0xa0(%rbp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x50(%rbp), %xmm1
movsd -0x38(%rbp), %xmm2
mulsd %xmm2, %xmm1
movsd -0xc8(%rbp), %xmm3
mulsd -0xb8(%rbp), %xmm3
movsd -0xd0(%rbp), %xmm0
mulsd %xmm2, %xmm0
addsd %xmm3, %xmm0
divsd %xmm0, %xmm1
mulsd (%rax), %xmm1
movsd %xmm1, -0x50(%rbp)
incq %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x50(%rbp), %xmm0
movsd %xmm0, (%rax)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x539c
movsd -0x40(%rbp), %xmm0
addsd (%rax), %xmm0
movsd %xmm0, -0x40(%rbp)
movq %r14, %rdi
callq 0x53b8
leaq -0x68(%rbp), %r13
movq %r13, %rdi
callq 0x53b8
leaq -0xf0(%rbp), %rdi
callq 0x53b8
cmpq %r12, -0x58(%rbp)
jne 0xc2dd
jmp 0xc4dc
movsd 0x15b31(%rip), %xmm0    # 0x22008
movsd %xmm0, -0x40(%rbp)
movq -0x58(%rbp), %r13
testl %r13d, %r13d
js 0xc527
leaq 0x1(%r13), %r15
xorl %ebx, %ebx
leaq -0xa0(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x539c
movsd (%rax), %xmm0
divsd -0x40(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %r14, %rdi
movq %rbx, %rsi
callq 0x539c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %rbx
cmpq %rbx, %r15
jne 0xc4f2
leaq -0x88(%rbp), %rbx
movq %rbx, %rdi
callq 0x533c
movq -0xb0(%rbp), %r12
movq %r12, %rdi
movq -0xa8(%rbp), %rsi
movq %rbx, %rdx
callq 0x5346
leaq -0x88(%rbp), %rdi
callq 0x5a80
testl %r13d, %r13d
js 0xc5a5
leal 0x1(%r13), %r15d
xorl %ebx, %ebx
leaq -0xa0(%rbp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x539c
movsd (%rax), %xmm0
mulsd -0xc0(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x539c
movsd -0x38(%rbp), %xmm0
movsd %xmm0, (%rax)
incq %rbx
cmpq %rbx, %r15
jne 0xc56d
leaq -0xa0(%rbp), %rdi
callq 0x53c6
movq %r12, %rax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq -0x88(%rbp), %rdi
callq 0x5a80
jmp 0xc67c
movq %rax, %rbx
leaq -0x88(%rbp), %rdi
callq 0x5a80
jmp 0xc688
movq %rax, %rbx
jmp 0xc602
movq %rax, %rbx
leaq -0x88(%rbp), %rdi
callq 0x41a0
leaq -0x68(%rbp), %rdi
callq 0x58c6
jmp 0xc67c
movq %rax, %rbx
jmp 0xc670
movq %rax, %rbx
jmp 0xc626
movq %rax, %rbx
leaq -0x88(%rbp), %rdi
callq 0x41a0
leaq -0xe0(%rbp), %rdi
callq 0x58c6
jmp 0xc670
movq %rax, %rbx
jmp 0xc667
movq %rax, %rbx
jmp 0xc64d
movq %rax, %rbx
leaq -0x88(%rbp), %rdi
callq 0x41a0
leaq -0x29(%rbp), %rdi
callq 0x58c6
jmp 0xc667
movq %rax, %rbx
leaq -0xe0(%rbp), %rdi
callq 0x53b8
leaq -0x68(%rbp), %rdi
callq 0x53b8
leaq -0xf0(%rbp), %rdi
callq 0x53b8
leaq -0xa0(%rbp), %rdi
callq 0x53c6
movq %rbx, %rdi
callq 0x45a0