// File: 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
subq $0x210, %rsp            # imm = 0x210
movq %rdi, -0x170(%rbp)
movq %rdi, %rax
movq %rax, -0x168(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movsd %xmm0, -0x18(%rbp)
movsd %xmm1, -0x20(%rbp)
movsd %xmm2, -0x28(%rbp)
movsd %xmm3, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x160(%rbp)
movl 0x48(%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
incl %eax
cltq
movq %rax, -0x158(%rbp)
leaq -0x51(%rbp), %rdi
movq %rdi, -0x150(%rbp)
callq 0x58a0
movq -0x158(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0x50(%rbp), %rdi
callq 0x58c0
jmp 0x120a0
leaq -0x51(%rbp), %rdi
callq 0x5930
leaq -0x50(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x5950
movsd 0x23f4a(%rip), %xmm0    # 0x36008
movsd %xmm0, (%rax)
movsd 0x23f3e(%rip), %xmm0    # 0x36008
movsd %xmm0, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x12513
movq -0x160(%rbp), %rax
addq $0x88, %rax
movq %rax, -0x180(%rbp)
leaq -0xa9(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0x45f0
movq -0x178(%rbp), %rdx
leaq 0x23f19(%rip), %rsi     # 0x36030
leaq -0xa8(%rbp), %rdi
callq 0x44d0
jmp 0x12125
movq -0x180(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x13990
movq %rax, -0x188(%rbp)
jmp 0x12141
movq -0x188(%rbp), %rsi
leaq -0x88(%rbp), %rdi
movq %rdi, -0x198(%rbp)
callq 0x13960
leaq -0xa8(%rbp), %rdi
callq 0x4220
leaq -0xa9(%rbp), %rdi
callq 0x4410
movq -0x198(%rbp), %rdi
callq 0x5970
movq %rax, %rdi
movl -0x74(%rbp), %esi
movsd -0x18(%rbp), %xmm0
movsd -0x20(%rbp), %xmm1
callq 0x1aa40
movsd %xmm0, -0x190(%rbp)
jmp 0x1219e
movq -0x160(%rbp), %rax
movsd -0x190(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
addq $0x88, %rax
movq %rax, -0x1a8(%rbp)
leaq -0xe9(%rbp), %rdi
movq %rdi, -0x1a0(%rbp)
callq 0x45f0
movq -0x1a0(%rbp), %rdx
leaq 0x23e58(%rip), %rsi     # 0x3603b
leaq -0xe8(%rbp), %rdi
callq 0x44d0
jmp 0x121f1
movq -0x1a8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
callq 0x13990
movq %rax, -0x1b0(%rbp)
jmp 0x1220d
movq -0x1b0(%rbp), %rsi
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
callq 0x13960
leaq -0xe8(%rbp), %rdi
callq 0x4220
leaq -0xe9(%rbp), %rdi
callq 0x4410
movq -0x1c0(%rbp), %rdi
callq 0x5970
movq %rax, %rdi
movl -0x74(%rbp), %esi
movsd -0x18(%rbp), %xmm0
movsd -0x20(%rbp), %xmm1
callq 0x1aa40
movsd %xmm0, -0x1b8(%rbp)
jmp 0x1226a
movq -0x160(%rbp), %rax
movsd -0x1b8(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
addq $0x88, %rax
movq %rax, -0x1d0(%rbp)
leaq -0x129(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0x45f0
movq -0x1c8(%rbp), %rdx
leaq 0x2567a(%rip), %rsi     # 0x37929
leaq -0x128(%rbp), %rdi
callq 0x44d0
jmp 0x122bd
movq -0x1d0(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x13990
movq %rax, -0x1d8(%rbp)
jmp 0x122d9
movq -0x1d8(%rbp), %rsi
leaq -0x108(%rbp), %rdi
movq %rdi, -0x1e8(%rbp)
callq 0x13960
leaq -0x128(%rbp), %rdi
callq 0x4220
leaq -0x129(%rbp), %rdi
callq 0x4410
movq -0x1e8(%rbp), %rdi
callq 0x5970
movq %rax, %rdi
movl -0x74(%rbp), %esi
movsd -0x18(%rbp), %xmm0
movsd -0x20(%rbp), %xmm1
callq 0x1aa40
movsd %xmm0, -0x1e0(%rbp)
jmp 0x12336
movsd -0x1e0(%rbp), %xmm0
movsd %xmm0, -0x138(%rbp)
movslq -0x74(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movsd (%rax), %xmm0
movsd -0xb8(%rbp), %xmm1
mulsd -0x20(%rbp), %xmm1
movsd -0xf8(%rbp), %xmm2
movsd -0x20(%rbp), %xmm4
movsd -0x138(%rbp), %xmm3
mulsd -0x30(%rbp), %xmm3
mulsd %xmm4, %xmm2
addsd %xmm3, %xmm2
divsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0x1f0(%rbp)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movsd -0x1f0(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movsd (%rax), %xmm0
addsd -0x70(%rbp), %xmm0
movsd %xmm0, -0x70(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x5990
leaq -0xc8(%rbp), %rdi
callq 0x5990
leaq -0x88(%rbp), %rdi
callq 0x5990
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x120d6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x51(%rbp), %rdi
callq 0x5930
jmp 0x12684
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x12446
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x4220
leaq -0xa9(%rbp), %rdi
callq 0x4410
jmp 0x1267b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x12502
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x1248e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0x4220
leaq -0xe9(%rbp), %rdi
callq 0x4410
jmp 0x12502
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x124f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x124d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x4220
leaq -0x129(%rbp), %rdi
callq 0x4410
jmp 0x124f6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x5990
leaq -0xc8(%rbp), %rdi
callq 0x5990
leaq -0x88(%rbp), %rdi
callq 0x5990
jmp 0x1267b
movl $0x0, -0x13c(%rbp)
movl -0x13c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jg 0x12576
movslq -0x13c(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movsd (%rax), %xmm0
divsd -0x70(%rbp), %xmm0
movsd %xmm0, -0x1f8(%rbp)
movslq -0x13c(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movsd -0x1f8(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x13c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x13c(%rbp)
jmp 0x1251d
movb $0x0, -0x13d(%rbp)
movl -0x34(%rbp), %eax
incl %eax
cltq
movq %rax, -0x208(%rbp)
leaq -0x13e(%rbp), %rdi
movq %rdi, -0x200(%rbp)
callq 0x58a0
movq -0x170(%rbp), %rdi
movq -0x208(%rbp), %rsi
movq -0x200(%rbp), %rdx
callq 0x58c0
jmp 0x125ba
leaq -0x13e(%rbp), %rdi
callq 0x5930
movl $0x0, -0x144(%rbp)
movl -0x144(%rbp), %eax
cmpl -0x34(%rbp), %eax
jg 0x12646
movslq -0x144(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x5950
movq -0x170(%rbp), %rdi
movsd (%rax), %xmm0
mulsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x210(%rbp)
movslq -0x144(%rbp), %rsi
callq 0x5950
movsd -0x210(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x144(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x144(%rbp)
jmp 0x125d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x13e(%rbp), %rdi
callq 0x5930
jmp 0x1267b
movb $0x1, -0x13d(%rbp)
testb $0x1, -0x13d(%rbp)
jne 0x12662
movq -0x170(%rbp), %rdi
callq 0x59b0
leaq -0x50(%rbp), %rdi
callq 0x59b0
movq -0x168(%rbp), %rax
addq $0x210, %rsp            # imm = 0x210
popq %rbp
retq
leaq -0x50(%rbp), %rdi
callq 0x59b0
movq -0x60(%rbp), %rdi
callq 0x45e0
nopl (%rax)