Dear developer,
hello. I have a question to ask.
I have a correlation between two arbitrary distributions ρ_x. How can I get the correlation between standard normal distributions ρ_z through Nataf transformation in OpenTURNS?
Thanks
Dear developer,
hello. I have a question to ask.
I have a correlation between two arbitrary distributions ρ_x. How can I get the correlation between standard normal distributions ρ_z through Nataf transformation in OpenTURNS?
Thanks
Hi,
There is no service allowing to convert a linear correlation coefficient between two arbitrary distributions and the correlation of the supposed normal copula between these distributions (which is what is done when using the Nataf transformation). The reason for that is that either you built your joint distribution based on the marginal distributions and a normal copula, and the linear correlation is a consequence of this construction, or you try to mix two univariate distributions and a normal copula in order to get a target linear correlation, and this problem is ill posed as in general, there is no joint distribution (using a normal copula or any other copula) having the target linear correlation and the target marginal distributions.
The following example illustrates this problem (and gives you a way to compute the Nataf correlation when it exists):
import openturns as ot
ot.ResourceMap.SetAsBool("JointDistribution-UseGenericCovarianceAlgorithm", True)
ot.ResourceMap.SetAsBool("Distribution-UseCovarianceAdaptiveAlgorithm", False)
ot.ResourceMap.SetAsUnsignedInteger("Distribution-DefaultIntegrationNodesNumber", 2**16)
epsilon = 1e-2
rho_target = 0.5 # fails with any value < -0.5
marginal1 = ot.LogNormal(0.0, 1.0)
marginal2 = ot.Exponential(1.0)
distribution = ot.JointDistribution([marginal1, marginal2], ot.NormalCopula(2))
def computeRho(r):
copula = ot.NormalCopula(ot.CorrelationMatrix(2, [1.0, r[0], r[0], 1.0]))
distribution.setCopula(copula)
return [distribution.getCorrelation()[0, 1]]
fRho = ot.PythonFunction(1, 1, computeRho)
fRho.setInputDescription(["Nataf correlation"])
fRho.setOutputDescription(["Linear correlation"])
ot.Show(fRho.draw(-1.0+epsilon, 1.0-epsilon))
r = ot.Brent().solve(fRho, rho_target, -1.0+epsilon, 1.0-epsilon)
print(f"for {rho_target=}, {r=}")
print("distribution=", distribution)
Several points are to be noted:
Cheers
Régis