同时涉及变量和数组的Julia表达式的向量化

同时涉及变量和数组的Julia表达式的向量化,julia,Julia,我使用了以下代码,作为在Julia 0.6中实现for water的一部分 struct parameterizedeos Tc::Float64 ρc::Float64 R::Float64 #parameters for ideal gas portion n₀::Vector{Float64} γ₀::Vector{Float64} end h2o_n₀ = [-8.3204464837497, 6.6832105275932, 3.00632, 0.01243

我使用了以下代码,作为在Julia 0.6中实现for water的一部分

struct parameterizedeos
  Tc::Float64
  ρc::Float64
  R::Float64

  #parameters for ideal gas portion
  n₀::Vector{Float64}
  γ₀::Vector{Float64}
end

h2o_n₀ = [-8.3204464837497, 6.6832105275932, 3.00632, 0.012436, 0.97315, 1.27950,
          0.96956, 0.24873]
h2o_γ₀ = [1.28728967, 3.53734222, 7.74073708, 9.24437796, 27.5075105]

function Σ(expr)
    return sum(eval(@. expr))
end

function ig(eos, δ, τ)
  end_ = Σ(eos.n₀[4:8]*log(1-exp(-eos.γ₀)*τ))
  return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end

Tc = 647.096
ρc = 322
R = 0.46151805

eos = parameterizedeos(Tc,ρc,R,h2o_n₀,h2o_γ₀)
δ₁ = 838.025/ρc
τ₁ = Tc/500
print(ig(eos,δ₁,τ₁))
∑被认为是数学中对应运算符的简单形式,而δ和τ使用链接参考中的术语(分别为无量纲密度和温度)。我得到
LoadError:dimensionsmatch(“不能乘以两个向量”)

我在Julia REPL中使用了各种各样的子示例,它们似乎都像我预期的那样工作<代码>∑(对数(1-exp(-h2o_u)γ₀)*τ) )按预期对元素进行矢量化和求和。见鬼,
eval(@.h2o\n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) 
愉快地返回一个5元素向量。但是调用
∑(h2o\n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) )
中断

我是Julia和macros等神秘事物的noob,所以任何人都可以帮我弄清楚这里发生了什么,那太好了。

试试这个(改用。*和log.and exp.)


您得到的错误:
dimensionsmatch(“无法乘以两个向量”)
发生在函数
ig
eos.n时₀[4:8]*对数(1-exp(-eos.γ₀)*τ) 在将结果传递给∑
之前,对进行求值

此外:
@。
在解析时在全局范围内展开,它向函数调用和运算符添加点。
expr
只是一个变量,不是运算符,不是函数调用,因此
@。
不做任何事情。
eval
也不做任何事情,因此
sum(eval(@.expr))
与普通
sum完全相同(expr)
。但由于程序在该点之前失败,这不是您的问题

Edit:实际上
eval
做的不仅仅是什么。它做了一些工作;结果是相同的,但额外的工作完全浪费了。)

解决方案:删除函数
,您不需要它。按如下方式重新编写函数
ig

function ig(eos, δ, τ)
  end_ = sum(@. eos.n₀[4:8] * log(1 - exp(-eos.γ₀) * τ))
  return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end
编辑:

我在Julia REPL和 它们似乎都像我预期的那样工作₀)*τ) ) 按预期对元素进行矢量化和求和。Heck,
eval(@.h2o\n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) 
愉快地返回一个5元素向量。 但是调用
∑(h2o\n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) )
中断

这里的一切都按预期工作。
log
exp
目前自动矢量化,但这种行为已被弃用。在1.0版中,对向量调用
log
exp
(或
sin
sqrt
等)将是一个错误

eval(@.h2o\n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) 
按预期将此表达式矢量化。(但是删除
eval
,您只是在值上调用它,对
eval
没有任何意义)


和<代码>∑(h2o_n₀[4:8]*对数(1-exp(-h2o_u)γ₀)*τ) )失败,因为您试图将两个向量相乘,但这是一种从未奏效的方法(您可以使用点积(例如,
“*
),也可以进行元素相乘。)你后来试图把这个结果传递到<代码> > <代码>是无关的。< <代码> Ex> <代码>和<代码>日志> <代码>没有帮助,但是在中间使用了<代码> *>代码。实际上,我认为这是@宏中的一个bug,可能会报告它,因为我认为使用那个宏应该把所有的东西都矢量化。表达式。
eval
的存在是一个巨大的危险信号。不要使用
eval
。相反,你可以使用@stefanbachert的答案,但在第一行中用
sum
替换
eval
。或者你可以写:
sum(@.eos.n₀[4:8]*对数(1-exp(-eos.γ₀) * τ₁))
sum(@.eos.n₀[4:8]*对数(1-exp(-eos.γ₀) * τ₁))也会断开(自己试试!).正如我在对已接受答案的评论中所说,只需手动将
添加到中间
*
就有帮助了,我认为这是@宏中的一个缺陷,我认为它应该将所有内容向量化。就∑而言,它只是为了使向量化操作的求和更容易,但@宏中的缺陷(或者我对它缺乏理解)似乎使这不可能。我已经尝试过了,而且效果非常好。关于∑,使用
eval
是多余的(通常建议不要使用)仔细看,您的代码实际上比您想象的更早失败,
@
宏甚至从未发挥作用。您的代码尝试评估
eos.n₀[4:8]*对数(1-exp(-eos.γ₀)*τ) 
,甚至在将结果传递给
函数。你必须传递一个
Expr
才能让它工作。实际上,即使是我最后的建议(传递一个
Expr
)也可能不起作用。宏在解析过程中被展开,解析器在代码中只看到
@.Expr
,而不知道如何处理
Expr
function ig(eos, δ, τ)
  end_ = sum(@. eos.n₀[4:8] * log(1 - exp(-eos.γ₀) * τ))
  return log(δ) + eos.n₀[1] + eos.n₀[2]*τ + eos.n₀[3]*log(τ) + end_
end