Python: for 循环中的计算与手动计算的结果不匹配
Python: Computation in for loop doesn't match result of manual computation
我目前正在进行一个研究某些气体混合物特性的项目。使用不同的输入测试我的代码,我遇到了一个我无法解释的错误(?)。基本上,它是关于在 for 循环中对 numpy 数组的计算。当它计算 for 循环时,它会产生与手动构建结果不同(且错误)的结果,使用与 for 循环中完全相同的代码片段,但手动索引。我不知道为什么会这样,是我自己的错误,还是 numpy 中的错误。
超级奇怪,所需输入对象的某些实例 运行 通过整个 for 循环没有任何问题,而其他 运行 完全达到某个索引,而其他甚至无法计算第一个循环。
例如,一个输入总是停在索引 16 处,抛出一个:
ValueError: could not broadcast input array from shape (25,) into shape (32,)
经过进一步调查,我可以确认,前 15 个循环抛出了正确的结果,索引 16 循环中的结果是错误的,甚至大小都不正确。 运行通过控制台手动循环16时,没有出现错误...
The lower array shows the results for index 16, when it's running in the loop.
These are the results for index 16, when running the code in the for loop manually in the console. These are, what one would expect to get.
代码的重要部分实际上只是 for 循环中的 np.multiply() - 我将其余部分留给了上下文,但我很确定它不会干扰我的意图。
def thermic_dissociation(input_gas, pressure):
# Copy of the input_gas object, which may not be altered out of scope
gas = copy.copy(input_gas)
# Temperature range
T = np.logspace(2.473, 4.4, 1000)
# Matrix containing the data over the whole range of interest
moles = np.zeros((gas.gas_cantera.n_species, len(T)))
# Array containing other property of interest
sum_particles = np.zeros(len(T))
# The troublesome for-loop:
for index in range(len(T)):
print(str(index) + ' start')
# Set temperature and pressure of the gas
gas.gas_cantera.TP = T[index], pressure
# Set gas mixture to a state of chemical equilibrium
gas.gas_cantera.equilibrate('TP')
# Sum of particles = Molar Density * Avogadro constant for every temperature
sum_particles[index] = gas.gas_cantera.density_mole * ct.avogadro
#This multiplication is doing the weird stuff, printed it to see what's computed before it puts it into the result matrix and throwing the error
print(np.multiply(list(gas.gas_cantera.mole_fraction_dict().values()), sum_particles[index]))
# This is where the error is thrown, as the resulting array is of smaller size, than it should be and thus resulting in the error
moles[:, index] = np.multiply(list(gas.gas_cantera.mole_fraction_dict().values()), sum_particles[index])
print(str(index) + ' end')
# An array helping to handle the results
molecule_order = list(gas.gas_cantera.mole_fraction_dict().keys())
return [moles, sum_particles, T, molecule_order]
非常感谢您的帮助!
这个特殊问题与 numpy 无关。对 mole_fraction_dict
returns 标准 python 字典的调用。字典中的元素数量取决于可选的 threshold
参数,其默认值为 0.0.
可以检查 Cantera 的源代码以查看究竟发生了什么。
换句话说,如果 x > threshold
,则值最终会出现在字典中。如果在这里使用 >=
而不是 >
可能会更有意义。也许这会阻止你的情况出现意外结果。
如评论中所确认,您可以使用 mole_fraction_dict(threshold=-np.inf)
获取字典中的所有所需值。或者也可以用-float('inf')
。
在您的代码中,您继续对字典调用 .values()
,但如果不能保证值的顺序,这将是有问题的。我不确定是否是这种情况。最好通过使用键从字典中检索值来明确顺序。
如果你想要所有物种摩尔分数的数组,你应该使用 cantera.Solution
对象的 X
属性,它总是直接 returns 那个完整的数组.您可以查看该方法的文档:cantera.Solution.X`.
mole_fraction_dict
方法专门用于您希望通过名称而不是它们在 Solution
对象中的顺序来引用物种的情况,例如关联两个不同的 Solution
定义不同物种集的对象。
我目前正在进行一个研究某些气体混合物特性的项目。使用不同的输入测试我的代码,我遇到了一个我无法解释的错误(?)。基本上,它是关于在 for 循环中对 numpy 数组的计算。当它计算 for 循环时,它会产生与手动构建结果不同(且错误)的结果,使用与 for 循环中完全相同的代码片段,但手动索引。我不知道为什么会这样,是我自己的错误,还是 numpy 中的错误。
超级奇怪,所需输入对象的某些实例 运行 通过整个 for 循环没有任何问题,而其他 运行 完全达到某个索引,而其他甚至无法计算第一个循环。
例如,一个输入总是停在索引 16 处,抛出一个:
ValueError: could not broadcast input array from shape (25,) into shape (32,)
经过进一步调查,我可以确认,前 15 个循环抛出了正确的结果,索引 16 循环中的结果是错误的,甚至大小都不正确。 运行通过控制台手动循环16时,没有出现错误...
The lower array shows the results for index 16, when it's running in the loop. These are the results for index 16, when running the code in the for loop manually in the console. These are, what one would expect to get.
代码的重要部分实际上只是 for 循环中的 np.multiply() - 我将其余部分留给了上下文,但我很确定它不会干扰我的意图。
def thermic_dissociation(input_gas, pressure):
# Copy of the input_gas object, which may not be altered out of scope
gas = copy.copy(input_gas)
# Temperature range
T = np.logspace(2.473, 4.4, 1000)
# Matrix containing the data over the whole range of interest
moles = np.zeros((gas.gas_cantera.n_species, len(T)))
# Array containing other property of interest
sum_particles = np.zeros(len(T))
# The troublesome for-loop:
for index in range(len(T)):
print(str(index) + ' start')
# Set temperature and pressure of the gas
gas.gas_cantera.TP = T[index], pressure
# Set gas mixture to a state of chemical equilibrium
gas.gas_cantera.equilibrate('TP')
# Sum of particles = Molar Density * Avogadro constant for every temperature
sum_particles[index] = gas.gas_cantera.density_mole * ct.avogadro
#This multiplication is doing the weird stuff, printed it to see what's computed before it puts it into the result matrix and throwing the error
print(np.multiply(list(gas.gas_cantera.mole_fraction_dict().values()), sum_particles[index]))
# This is where the error is thrown, as the resulting array is of smaller size, than it should be and thus resulting in the error
moles[:, index] = np.multiply(list(gas.gas_cantera.mole_fraction_dict().values()), sum_particles[index])
print(str(index) + ' end')
# An array helping to handle the results
molecule_order = list(gas.gas_cantera.mole_fraction_dict().keys())
return [moles, sum_particles, T, molecule_order]
非常感谢您的帮助!
这个特殊问题与 numpy 无关。对 mole_fraction_dict
returns 标准 python 字典的调用。字典中的元素数量取决于可选的 threshold
参数,其默认值为 0.0.
可以检查 Cantera 的源代码以查看究竟发生了什么。
换句话说,如果 x > threshold
,则值最终会出现在字典中。如果在这里使用 >=
而不是 >
可能会更有意义。也许这会阻止你的情况出现意外结果。
如评论中所确认,您可以使用 mole_fraction_dict(threshold=-np.inf)
获取字典中的所有所需值。或者也可以用-float('inf')
。
在您的代码中,您继续对字典调用 .values()
,但如果不能保证值的顺序,这将是有问题的。我不确定是否是这种情况。最好通过使用键从字典中检索值来明确顺序。
如果你想要所有物种摩尔分数的数组,你应该使用 cantera.Solution
对象的 X
属性,它总是直接 returns 那个完整的数组.您可以查看该方法的文档:cantera.Solution.X`.
mole_fraction_dict
方法专门用于您希望通过名称而不是它们在 Solution
对象中的顺序来引用物种的情况,例如关联两个不同的 Solution
定义不同物种集的对象。