def test_roundtrip(): """Assert that forward/inverse Rosenblatt transforms is non-destructive.""" mean = numpy.array([0.1, -0.5, 0]) cov = numpy.array([[1.0, -0.9, 0.3], [-0.9, 1.0, 0.0], [0.3, 0.0, 1.0]]) dist1 = chaospy.MvNormal(mean, cov, rotation=[0, 1, 2]) dist2 = chaospy.MvNormal(mean, cov, rotation=[2, 1, 0]) dist3 = chaospy.MvNormal(mean, cov, rotation=[2, 0, 1]) mesh = numpy.mgrid[0.25:0.75:3j, 0.25:0.75:5j, 0.25:0.75:4j].reshape(3, -1) assert not numpy.allclose(dist1.fwd(dist2.inv(mesh)), mesh) assert numpy.allclose(dist1.fwd(dist1.inv(mesh)), mesh) assert numpy.allclose(dist2.fwd(dist2.inv(mesh)), mesh) assert numpy.allclose(dist3.fwd(dist3.inv(mesh)), mesh)
def test_dimensionReduction(self): systemsize = 4 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Create stochastic collocation object collocation = StochasticCollocation(3, "Normal") # Create dimension reduction object threshold_factor = 0.9 dominant_space = DimensionReduction(threshold_factor=threshold_factor, exact_Hessian=True) # Initialize chaospy distribution std_dev = 0.2 * np.ones(QoI.systemsize) x = np.ones(QoI.systemsize) jdist = cp.MvNormal(x, np.diag(std_dev)) # Get the eigenmodes of the Hessian product and the dominant indices dominant_space.getDominantDirections(QoI, jdist) true_eigenvals = np.array([0.08, 0.02, 0.005, 0.00888888888888889]) err_eigenvals = abs(dominant_space.iso_eigenvals - true_eigenvals) true_eigenvecs = np.array([[0.5, 0.5, -0.5, -0.5], [0.5, -0.5, 0.5, -0.5], [0.5, 0.5, 0.5, 0.5], [0.5, -0.5, -0.5, 0.5]]) err_eigenvecs = abs(dominant_space.iso_eigenvecs - true_eigenvecs) self.assertTrue((err_eigenvals < 1.e-15).all()) self.assertTrue((err_eigenvecs < 1.e-15).all()) self.assertEqual(dominant_space.dominant_indices, [0, 1])
def setup(self): print("In Setup!!") self.std_dev_xi = np.array([0.3, 0.2, 0.1]) system_size = 3 mean_xi = np.ones(system_size) # Inputs self.add_input('mean_xi', val=mean_xi) # Intermediate operations jdist = cp.MvNormal(mean_xi, np.diag(self.std_dev_xi)) self.collocation_QoI = StochasticCollocation(system_size, "Normal") self.collocation_QoI_grad = StochasticCollocation( system_size, "Normal", system_size) # Create a Stochastic collocation object self.QoI = examples.Paraboloid3D(system_size) # Create QoI threshold_factor = 0.9 self.dominant_space = DimensionReduction(threshold_factor, exact_Hessian=True) self.dominant_space.getDominantDirections(self.QoI, jdist) # Outputs self.add_output('mean_QoI', 0.0) # Partial derivatives self.declare_partials('mean_QoI', 'mean_xi')
def test_hadamard_accuracy(self): systemsize = 4 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) mu = np.zeros(systemsize) std_dev = np.eye(systemsize) jdist = cp.MvNormal(mu, std_dev) active_subspace = ActiveSubspace(QoI, n_dominant_dimensions=4, n_monte_carlo_samples=10000, use_svd=True, read_rv_samples=False, write_rv_samples=False) active_subspace.getDominantDirections(QoI, jdist) mu_j_analytical = QoI.eval_analytical_QoI_mean(mu, cp.Cov(jdist)) var_j_analytical = QoI.eval_analytical_QoI_variance(mu, cp.Cov(jdist)) # Create reduced collocation object QoI_dict = {'Hadamard' : {'QoI_func' : QoI.eval_QoI, 'output_dimensions' : 1, }, } sc_obj_active = StochasticCollocation2(jdist, 4, 'MvNormal', QoI_dict, include_derivs=False, reduced_collocation=True, dominant_dir=active_subspace.dominant_dir) sc_obj_active.evaluateQoIs(jdist) mu_j_active = sc_obj_active.mean(of=['Hadamard']) var_j_active = sc_obj_active.variance(of=['Hadamard'])
def run_hadamard(systemsize, eigen_decayrate, std_dev, n_sample): # n_collocation_pts = 2 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Create stochastic collocation object # collocation = StochasticCollocation(n_collocation_pts, "Normal") # Initialize chaospy distribution x = np.random.randn(QoI.systemsize) jdist = cp.MvNormal(x, np.diag(std_dev)) threshold_factor = 0.5 dominant_space_exact = DimensionReduction( threshold_factor=threshold_factor, exact_Hessian=True) dominant_space = DimensionReduction(threshold_factor=threshold_factor, exact_Hessian=False, n_arnoldi_sample=n_sample) dominant_space.getDominantDirections(QoI, jdist, max_eigenmodes=20) dominant_space_exact.getDominantDirections(QoI, jdist) # Sort the exact eigenvalues in descending order sort_ind = dominant_space_exact.iso_eigenvals.argsort()[::-1] # Compare the eigenvalues of the 10 most dominant spaces lambda_exact = dominant_space_exact.iso_eigenvals[sort_ind] error_arr = dominant_space.iso_eigenvals[0:10] - lambda_exact[0:10] # print 'error_arr = ', error_arr rel_error_norm = np.linalg.norm(error_arr) / np.linalg.norm( lambda_exact[0:10]) return rel_error_norm
def calcMarginals(self, jdist): """ Compute the marginal density object for the dominant space. The current implementation is only for Gaussian distribution. """ marginal_size = len(self.dominant_indices) orig_mean = cp.E(jdist) orig_covariance = cp.Cov(jdist) # Step 1: Rotate the mean & covariance matrix of the the original joint # distribution along the eigenve dominant_vecs = self.iso_eigenvecs[:, self.dominant_indices] marginal_mean = np.dot(dominant_vecs.T, orig_mean) marginal_covariance = np.matmul( dominant_vecs.T, np.matmul(orig_covariance, dominant_vecs)) # Step 2: Create the new marginal distribution if marginal_size == 1: # Univariate distributions have to be treated separately marginal_std_dev = np.sqrt(np.asscalar(marginal_covariance)) self.marginal_distribution = cp.Normal(np.asscalar(marginal_mean), marginal_std_dev) else: self.marginal_distribution = cp.MvNormal(marginal_mean, marginal_covariance)
def test_derivatives_scalarQoI(self): systemsize = 3 mu = mean_3dim # np.random.randn(systemsize) std_dev = std_dev_3dim # np.diag(np.random.rand(systemsize)) jdist = cp.MvNormal(mu, std_dev) # Create QoI Object QoI = examples.Paraboloid3D(systemsize) # Create the Stochastic Collocation object deriv_dict = { 'xi': { 'dQoI_func': QoI.eval_QoIGradient, 'output_dimensions': systemsize } } QoI_dict = { 'paraboloid': { 'quadrature_degree': 3, 'reduced_collocation': False, 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, 'include_derivs': True, 'deriv_dict': deriv_dict } } sc_obj = StochasticCollocation3(jdist, 'MvNormal', QoI_dict) sc_obj.evaluateQoIs(jdist) dmu_j = sc_obj.dmean(of=['paraboloid'], wrt=['xi']) # dvar_j = sc_obj.dvariance(of=['paraboloid'], wrt=['xi']) # Analytical dmu_j dmu_j_analytical = np.array([100 * mu[0], 50 * mu[1], 2 * mu[2]]) err = abs( (dmu_j['paraboloid']['xi'] - dmu_j_analytical) / dmu_j_analytical) self.assertTrue((err < 1.e-12).all())
def multivariate(mean, cov, size): # rule must be of 'L', 'M', 'H', 'K' or 'S' res = chaospy.MvNormal(mean, cov).sample(size=size, rule=rule or 'L') res = np.moveaxis(res, 0, res.ndim - 1) np.random.shuffle(res) return res
def test_nonrv_derivatives(self): # This test checks the analytical derivative w.r.t complex step systemsize = 2 n_parameters = 2 mu = mean_2dim # np.random.randn(systemsize) std_dev = std_dev_2dim # np.diag(np.random.rand(systemsize)) jdist = cp.MvNormal(mu, std_dev) QoI = examples.PolyRVDV(data_type=complex) # Create the Stochastic Collocation object deriv_dict = { 'dv': { 'dQoI_func': QoI.eval_QoIGradient_dv, 'output_dimensions': n_parameters } } QoI_dict = { 'PolyRVDV': { 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, 'deriv_dict': deriv_dict } } dv = np.random.randn(systemsize) + 0j QoI.set_dv(dv) sc_obj = StochasticCollocation2(jdist, 3, 'MvNormal', QoI_dict, include_derivs=True, data_type=complex) sc_obj.evaluateQoIs(jdist, include_derivs=True) dmu_j = sc_obj.dmean(of=['PolyRVDV'], wrt=['dv']) dvar_j = sc_obj.dvariance(of=['PolyRVDV'], wrt=['dv']) dstd_dev = sc_obj.dStdDev(of=['PolyRVDV'], wrt=['dv']) # Lets do complex step pert = complex(0, 1e-30) dmu_j_complex = np.zeros(n_parameters, dtype=complex) dvar_j_complex = np.zeros(n_parameters, dtype=complex) dstd_dev_complex = np.zeros(n_parameters, dtype=complex) for i in range(0, n_parameters): dv[i] += pert QoI.set_dv(dv) sc_obj.evaluateQoIs(jdist, include_derivs=False) mu_j = sc_obj.mean(of=['PolyRVDV']) var_j = sc_obj.variance(of=['PolyRVDV']) std_dev_j = np.sqrt(var_j['PolyRVDV'][0, 0]) dmu_j_complex[i] = mu_j['PolyRVDV'].imag / pert.imag dvar_j_complex[i] = var_j['PolyRVDV'].imag / pert.imag dstd_dev_complex[i] = std_dev_j.imag / pert.imag dv[i] -= pert err1 = dmu_j['PolyRVDV']['dv'] - dmu_j_complex self.assertTrue((err1 < 1.e-13).all()) err2 = dvar_j['PolyRVDV']['dv'] - dvar_j_complex self.assertTrue((err2 < 1.e-13).all()) err3 = dstd_dev['PolyRVDV']['dv'] - dstd_dev_complex self.assertTrue((err2 < 1.e-13).all())
def test_scalarQoI(self): systemsize = 3 mu = np.random.rand(systemsize) std_dev = np.diag(np.random.rand(systemsize)) jdist = cp.MvNormal(mu, std_dev) # Create QoI Object QoI = Paraboloid3D(systemsize) # Create the Monte Carlo object QoI_dict = { 'paraboloid': { 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, } } nsample = 1000000 mc_obj = MonteCarlo(nsample, jdist, QoI_dict) mc_obj.getSamples(jdist) # Get the mean and variance using Monte Carlo mu_js = mc_obj.mean(jdist, of=['paraboloid']) var_js = mc_obj.variance(jdist, of=['paraboloid']) # Analytical mean mu_j_analytical = QoI.eval_QoI_analyticalmean(mu, cp.Cov(jdist)) err = abs((mu_js['paraboloid'] - mu_j_analytical) / mu_j_analytical) self.assertTrue(err < 1e-3) # Analytical variance var_j_analytical = QoI.eval_QoI_analyticalvariance(mu, cp.Cov(jdist)) err = abs((var_js['paraboloid'] - var_j_analytical) / var_j_analytical) # print('var_js paraboloid = ', var_js['paraboloid'], '\n') self.assertTrue(err < 1e-2)
def test_multipleQoI(self): # This tests for multiple QoIs. We only compute the mean in this test, # because it is only checking if it can do multiple loops systemsize = 2 theta = 0 mu = mean_2dim # np.random.randn(systemsize) std_dev = std_dev_2dim # np.diag(np.random.rand(systemsize)) jdist = cp.MvNormal(mu, std_dev) QoI1 = examples.Paraboloid2D(systemsize, (theta, )) QoI2 = examples.PolyRVDV() QoI_dict = { 'paraboloid2': { 'QoI_func': QoI1.eval_QoI, 'output_dimensions': 1, }, 'PolyRVDV': { 'QoI_func': QoI2.eval_QoI, 'output_dimensions': 1, } } sc_obj = StochasticCollocation2(jdist, 3, 'MvNormal', QoI_dict) sc_obj.evaluateQoIs(jdist) mu_js = sc_obj.mean(of=['paraboloid2', 'PolyRVDV']) # Compare against known values # 1. Paraboloid2D, we use nested loops mu_j1_analytical = QoI1.eval_QoI_analyticalmean(mu, cp.Cov(jdist)) err = abs( (mu_js['paraboloid2'][0] - mu_j1_analytical) / mu_j1_analytical) self.assertTrue(err < 1.e-15)
def run_hadamard(systemsize, eigen_decayrate, std_dev, n_eigenmodes): n_collocation_pts = 2 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # # Create stochastic collocation object # collocation = StochasticCollocation(n_collocation_pts, "Normal") # Initialize chaospy distribution x = np.random.rand(QoI.systemsize) jdist = cp.MvNormal(x, np.diag(std_dev)) threshold_factor = 0.5 dominant_space = DimensionReduction(threshold_factor=threshold_factor, exact_Hessian=False, n_arnoldi_sample=71, min_eigen_accuracy=1.e-2) dominant_space.getDominantDirections(QoI, jdist, max_eigenmodes=n_eigenmodes) # if systemsize == 64: # print('x = \n', repr(x)) # print('std_dev = \n', repr(std_dev)) # print('iso_eigenvals = ', dominant_space.iso_eigenvals) # print("dominant_indices = ", dominant_space.dominant_indices) # Collocate # collocation = StochasticCollocation(n_collocation_pts, "Normal") # mu_j = collocation.normal.reduced_mean(QoI.eval_QoI, jdist, dominant_space) # print "mu_j = ", mu_j QoI_dict = { 'Hadamard': { 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, }, } sc_obj = StochasticCollocation2(jdist, n_collocation_pts, 'MvNormal', QoI_dict, include_derivs=False, reduced_collocation=True, dominant_dir=dominant_space.dominant_dir) sc_obj.evaluateQoIs(jdist) mu_j_dict = sc_obj.mean(of=['Hadamard']) mu_j = mu_j_dict['Hadamard'] # Evaluate the analytical value of the Hadamard Quadratic covariance = cp.Cov(jdist) mu_analytic = QoI.eval_analytical_QoI_mean(x, covariance) # print "mu_analytic = ", mu_analytic relative_error = np.linalg.norm((mu_j - mu_analytic) / mu_analytic) # print "relative_error = ", relative_error return relative_error
def test_dimensionReduction_arnoldi_partial(self): # Compute 21 major the eigenmodes of an isoprobabilistic Hadamard # quadratic system using Arnoldi sampling and verify against the exact # computation systemsize = 64 eigen_decayrate = 2.0 num_sample = 51 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Initialize chaospy distribution std_dev = np.random.rand(QoI.systemsize) sqrt_Sigma = np.diag(std_dev) mu = np.random.rand(QoI.systemsize) jdist = cp.MvNormal(mu, sqrt_Sigma) # Estimate the eigenmodes of the Hessenberg matrix using Arnoldi perturbation_size = 1.e-6 arnoldi = ArnoldiSampling(perturbation_size, num_sample) eigenvals = np.zeros(num_sample-1) eigenvecs = np.zeros([QoI.systemsize, num_sample-1]) mu_iso = np.zeros(QoI.systemsize) mu_iso[:] = 0.0 gdata0 = np.zeros([QoI.systemsize, num_sample]) gdata0[:,0] = np.dot(QoI.eval_QoIGradient(mu, np.zeros(QoI.systemsize)), sqrt_Sigma) dim, error_estimate = arnoldi.arnoldiSample(QoI, jdist, mu_iso, gdata0, eigenvals, eigenvecs) # Compute the exact eigenmodes Hessian = QoI.eval_QoIHessian(mu, np.zeros(QoI.systemsize)) Hessian_Product = np.matmul(sqrt_Sigma, np.matmul(Hessian, sqrt_Sigma)) exact_eigenvals, exact_eigenvecs = np.linalg.eig(Hessian_Product) # Sort in descending order sort_ind1 = exact_eigenvals.argsort()[::-1] sort_ind2 = eigenvals.argsort()[::-1] lambda_exact = exact_eigenvals[sort_ind1] lambda_arnoldi = eigenvals[sort_ind2] # Compare the eigenvalues for i in range(0, num_sample-1): if i < 10: self.assertAlmostEqual(lambda_arnoldi[i], lambda_exact[i], places=6) else: # print "lambda_exact[i] = ", lambda_exact[i], "lambda_arnoldi[i] = ", lambda_arnoldi[i] self.assertAlmostEqual(lambda_arnoldi[i], lambda_exact[i], places=1) # Compare the eigenvectors V_exact = exact_eigenvecs[:, sort_ind1] V_arnoldi = eigenvecs[:, sort_ind2] for i in range(0, num_sample-1): product = abs(np.dot(V_exact[:,i], V_arnoldi[:,i])) if i < 10: self.assertAlmostEqual(product, 1.0, places=6)
def test_rotation(): """Make sure various rotations do not affect results.""" mean = numpy.array([0, 10, 0]) cov = numpy.array([[1.0, -0.2, 0.3], [-0.2, 1.0, 0.0], [0.3, 0.0, 1.0]]) mesh = numpy.mgrid[-1:1:2j, 9:11:3j, -1:1:4j] dist1 = chaospy.MvNormal(mean, cov, rotation=[0, 1, 2]) dist2 = chaospy.MvNormal(mean, cov, rotation=[2, 1, 0]) dist3 = chaospy.MvNormal(mean, cov, rotation=[2, 0, 1]) # PDF should be unaffected by rotation. assert numpy.allclose(dist1.pdf(mesh), dist2.pdf(mesh)) assert numpy.allclose(dist1.pdf(mesh), dist3.pdf(mesh)) assert numpy.allclose(dist2.pdf(mesh), dist3.pdf(mesh)) # One axis is constant. Verify that is the case for each rotation. assert numpy.all(dist1.fwd(mesh)[0, :, 0, 0] == dist1.fwd(mesh)[0].T) assert numpy.all(dist2.fwd(mesh)[2, 0, 0, :] == dist2.fwd(mesh)[2]) assert numpy.all(dist3.fwd(mesh)[2, 0, 0, :] == dist2.fwd(mesh)[2])
def objfunc(xdict): mu = xdict['xvars'] funcs = {} jdist = cp.MvNormal(mu, std_dev) QoI_func = QoI.eval_QoI funcs['obj'] = collocation.normal.reduced_mean(QoI_func, jdist, dominant_space) fail = False return funcs, fail
def compute(self, inputs, outputs): print("In compute") mu = inputs['mean_xi'] # print("mu = ", mu) jdist = cp.MvNormal(mu, np.diag(self.std_dev_xi)) QoI_func = self.QoI.eval_QoI outputs['mean_QoI'] = self.collocation_QoI.normal.reduced_mean( QoI_func, jdist, self.dominant_space)
def sens(xdict, funcs): mu = xdict['xvars'] jdist = cp.MvNormal(mu, std_dev) QoI_func = QoI.eval_QoIGradient funcsSens = {} funcsSens['obj', 'xvars'] = collocation_grad.normal.reduced_mean( QoI_func, jdist, dominant_space) fail = False return funcsSens, fail
def compute_partials(self, inputs, J): print("In compute_partials") mu = inputs['mean_xi'] jdist = cp.MvNormal(mu, np.diag(self.std_dev_xi)) QoI_func = self.QoI.eval_QoIGradient val = self.collocation_QoI_grad.normal.reduced_mean( QoI_func, jdist, self.dominant_space) J['mean_QoI', 'mean_xi'] = val # self.collocation.normal.reduced_mean(QoI_func, jdist, self.dominant_space)
def test_sampling_statistics(): """Assert that given mean and covariance matches sample statistics.""" mean = [100, 10, 10, 100] cov = [[10, -9, 3, -1], [-9, 20, 1, -2], [3, 1, 30, 4], [-1, -2, 4, 40]] dist = chaospy.MvNormal(mean, cov, rotation=[3, 0, 2, 1]) samples = dist.sample(100000) assert numpy.allclose(numpy.mean(samples, axis=-1), mean, atol=1e-2, rtol=1e-3), numpy.mean(samples, axis=-1).round(3) assert numpy.allclose(numpy.cov(samples), cov, atol=1e-1, rtol=1e-2), numpy.cov(samples).round(3)
def test_arnoldiSample_complete(self): # Compute all of the eigenmodes of an isoprobabilistic Hadamard # quadratic system using Arnoldi sampling and verify against the exact # computation systemsize = 16 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Initialize chaospy distribution std_dev = np.random.rand(QoI.systemsize) sqrt_Sigma = np.diag(std_dev) mu = np.random.rand(QoI.systemsize) jdist = cp.MvNormal(mu, sqrt_Sigma) # Estimate the eigenmodes of the Hessenberg matrix using Arnoldi perturbation_size = 1.e-6 num_sample = QoI.systemsize+1 arnoldi = ArnoldiSampling(perturbation_size, num_sample) eigenvals = np.zeros(num_sample-1) eigenvecs = np.zeros([QoI.systemsize, num_sample-1]) mu_iso = np.zeros(QoI.systemsize) mu_iso[:] = 0.0 gdata0 = np.zeros([QoI.systemsize, num_sample]) gdata0[:,0] = np.dot(QoI.eval_QoIGradient(mu, np.zeros(QoI.systemsize)), sqrt_Sigma) dim, error_estimate = arnoldi.arnoldiSample(QoI, jdist, mu_iso, gdata0, eigenvals, eigenvecs) # Compute the exact eigenmodes Hessian = QoI.eval_QoIHessian(mu, np.zeros(QoI.systemsize)) Hessian_Product = np.matmul(sqrt_Sigma, np.matmul(Hessian, sqrt_Sigma)) exact_eigenvals, exact_eigenvecs = np.linalg.eig(Hessian_Product) # Sort in descending order sort_ind1 = exact_eigenvals.argsort()[::-1] sort_ind2 = eigenvals.argsort()[::-1] # Compare the eigenvalues err_eigenvals = abs(exact_eigenvals[sort_ind1] - eigenvals[sort_ind2]) self.assertTrue((err_eigenvals < 1.e-7).all()) # Compare the eigenvectors V_exact = exact_eigenvecs[:, sort_ind1] V_arnoldi = eigenvecs[:, sort_ind2] product = np.zeros(QoI.systemsize) for i in range(0, systemsize): product[i] = abs(np.dot(V_exact[:,i], V_arnoldi[:,i])) self.assertAlmostEqual(product[i], 1.0, places=7)
def test_slicing(): """Test if slicing of distribution works as expected.""" dist = chaospy.MvNormal(mu=[1, 2], sigma=[[4, -1], [-1, 3]], rotation=[1, 0]) with pytest.raises(IndexError): dist[-2] with pytest.raises(IndexError): dist[2] with pytest.raises(IndexError): dist["illigal_index"] assert dist[-1] == dist[1] assert dist[1].mom(1) == 2
def test_sampling(): """Assert that inverse mapping results in samples with the correct statistics.""" mean = numpy.array([100, 10, 50]) cov = numpy.array([[10, -8, 4], [-8, 20, 2], [4, 2, 30]]) samples_u = chaospy.Uniform().sample((3, 100000)) for rotation in [(0, 1, 2), (2, 1, 0), (2, 0, 1)]: dist = chaospy.MvNormal(mean, cov, rotation=rotation) samples_ = dist.inv(samples_u) assert numpy.allclose(numpy.mean(samples_, axis=-1), mean, atol=1e-3, rtol=1e-3) assert numpy.allclose(numpy.cov(samples_), cov, atol=1e-2, rtol=1e-2)
def test_deterministic_model(self): # Check if the quantity of interest is being computed as expected uq_systemsize = 6 mu_orig = np.array( [mean_Ma, mean_TSFC, mean_W0, mean_E, mean_G, mean_mrho]) std_dev = np.diag([0.005, 0.00607 / 3600, 0.2, 5.e9, 1.e9, 50]) jdist = cp.MvNormal(mu_orig, std_dev) rv_dict = { 'Mach_number': mean_Ma, 'CT': mean_TSFC, 'W0': mean_W0, 'E': mean_E, # surface RV 'G': mean_G, # surface RV 'mrho': mean_mrho, # surface RV } input_dict = { 'n_twist_cp': 3, 'n_thickness_cp': 3, 'n_CM': 3, 'n_thickness_intersects': 10, 'n_constraints': 1 + 10 + 1 + 3 + 3, 'ndv': 3 + 3 + 2, 'mesh_dict': mesh_dict, 'rv_dict': rv_dict } QoI = examples.OASScanEagleWrapper(uq_systemsize, input_dict, include_dict_rv=True) # Check the value at the starting point fval = QoI.eval_QoI(mu_orig, np.zeros(uq_systemsize)) true_val = 5.229858093218218 err = abs(fval - true_val) self.assertTrue(err < 1.e-6) # Check if plugging back value also yields the expected results QoI.p['oas_scaneagle.wing.twist_cp'] = np.array([2.60830137, 10., 5.]) QoI.p['oas_scaneagle.wing.thickness_cp'] = np.array( [0.001, 0.001, 0.001]) QoI.p['oas_scaneagle.wing.sweep'] = [18.89098985] QoI.p['oas_scaneagle.alpha'] = [2.19244059] fval = QoI.eval_QoI(mu_orig, np.zeros(uq_systemsize)) true_val = 4.735819672292367 err = abs(fval - true_val) self.assertTrue(err < 1.e-6)
def test_reduced_montecarlo(self): systemsize = 4 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = HadamardQuadratic(systemsize, eigen_decayrate) true_eigenvals = np.array([0.08, 0.02, 0.005, 0.00888888888888889]) true_eigenvecs = np.array([[0.5, 0.5, -0.5, -0.5], [0.5, -0.5, 0.5, -0.5], [0.5, 0.5, 0.5, 0.5], [0.5, -0.5, -0.5, 0.5]]) dominant_dir = true_eigenvecs[:, 0:3] QoI_dict = { 'hadamard4_2': { 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, } } # Create the distribution mu = np.ones(systemsize) std_dev = 0.2 * np.eye(systemsize) jdist = cp.MvNormal(mu, std_dev) # Create the Monte Carlo object nsample = 100000 mc_obj = MonteCarlo(nsample, jdist, QoI_dict, reduced_collocation=True, dominant_dir=dominant_dir, include_derivs=False) mc_obj.getSamples(jdist, include_derivs=False) mu_j_mc = mc_obj.mean(jdist, of=['hadamard4_2']) # Compare against a reduced stochastic collocation object sc_obj = StochasticCollocation2(jdist, 3, 'MvNormal', QoI_dict, reduced_collocation=True, dominant_dir=dominant_dir) sc_obj.evaluateQoIs(jdist) mu_j_sc = sc_obj.mean(of=['hadamard4_2']) rel_err = abs((mu_j_mc['hadamard4_2'] - mu_j_sc['hadamard4_2']) / mu_j_sc['hadamard4_2']) self.assertTrue(rel_err[0] < 1.e-3)
def test_dist_addition_wrappers(): dists = [ chaospy.J(chaospy.Normal(2), chaospy.Normal(2), chaospy.Normal(3)), # ShiftScale chaospy.J(chaospy.Uniform(1, 3), chaospy.Uniform(1, 3), chaospy.Uniform(1, 5)), # LowerUpper chaospy.MvNormal([2, 2, 3], numpy.eye(3)), # MeanCovariance ] for dist in dists: joint = chaospy.Add([1, 1, 3], dist) assert numpy.allclose(joint.inv([0.5, 0.5, 0.5]), [3, 3, 6]) assert numpy.allclose(joint.fwd([3, 3, 6]), [0.5, 0.5, 0.5]) density = joint.pdf([2, 2, 2], decompose=True) assert numpy.isclose(density[0], density[1]), (dist, density) assert not numpy.isclose(density[0], density[2]), dist assert numpy.isclose(joint[0].inv([0.5]), 3) assert numpy.isclose(joint[0].fwd([3]), 0.5)
def x_cond(n, subset_j, subsetj_conditional, xjc): if subsetj_conditional is None: cov_int = np.array(cov) cov_int = cov_int.take(subset_j, axis=1) cov_int = cov_int[subset_j] distribution = cp.MvNormal(mean[subset_j], cov_int) return distribution.sample(n) else: return _r_condmvn( n, mean=mean, cov=cov, dependent_ind=subset_j, given_ind=subsetj_conditional, x_given=xjc, )
def test_operator_slicing(): dists = [ chaospy.Normal([2, 2, 3]), # ShiftScale chaospy.Uniform(1, [3, 3, 5]), # LowerUpper chaospy.MvNormal([2, 2, 3], numpy.eye(3)), # MeanCovariance chaospy.J(chaospy.Uniform(1, 3), chaospy.Uniform(1, [3, 5])), # Joint ] for dist in dists: assert numpy.allclose(dist.inv([0.5, 0.5, 0.5]), [2, 2, 3]) assert numpy.allclose(dist.fwd([2, 2, 3]), [0.5, 0.5, 0.5]) density = dist.pdf([2, 2, 2], decompose=True) assert numpy.isclose(density[0], density[1]), dist assert not numpy.isclose(density[0], density[2]), dist assert numpy.isclose(dist[0].inv([0.5]), 2) assert numpy.isclose(dist[0].fwd([2]), 0.5)
def test_evaluation(self): uq_systemsize = 5 mean_v = 248.136 # Mean value of input random variable mean_alpha = 5 # mean_Ma = 0.84 mean_re = 1.e6 mean_rho = 0.38 mean_cg = np.zeros((3)) std_dev = np.eye(uq_systemsize) mu_init = np.array([mean_v, mean_alpha, mean_Ma, mean_re, mean_rho]) rv_dict = { 'v': mean_v, 'alpha': mean_alpha, 'Mach_number': mean_Ma, 're': mean_re, 'rho': mean_rho, } QoI = examples.OASAerodynamicWrapper(uq_systemsize, rv_dict) jdist = cp.MvNormal(mu_init, std_dev) fval = QoI.eval_QoI(mu_init, np.zeros(uq_systemsize)) # Check the values expected_CD = 0.03721668965447261 expected_CL = 0.5123231521985626 expected_CM = np.array([0., -0.1793346481832254, 0.]) self.assertAlmostEqual(QoI.p['oas_example1.aero_point_0.CD'][0], expected_CD, places=13) self.assertAlmostEqual(QoI.p['oas_example1.aero_point_0.CL'][0], expected_CL, places=13) # np.testing.assert_array_almost_equal(QoI.p['oas_example1.aero_point_0.CM'][1], expected_CM, decimal=12) # Check the gradients grad = QoI.eval_QoIGradient(mu_init, np.zeros(uq_systemsize)) expected_dCD = np.array([0., 0.00245012, 0.00086087, -0., 0.]) expected_dCL = np.array([-0., 0.07634319, -0., -0., -0.]) np.testing.assert_array_almost_equal( QoI.deriv['oas_example1.aero_point_0.CD', 'mu'][0], expected_dCD, decimal=7) np.testing.assert_array_almost_equal( QoI.deriv['oas_example1.aero_point_0.CL', 'mu'][0], expected_dCL, decimal=7)
def test_segmented_mappings(): """Assert that conditional distributions in various rotation works as expected.""" mean_ref = numpy.array([1, 10, 100]) covariance = numpy.array([[1, 0.4, -0.5], [0.4, 2, 0], [-0.5, 0, 3]]) for rot in [(0, 1, 2), (2, 1, 0), (2, 0, 1)]: dist = chaospy.MvNormal(mean_ref, covariance, rotation=rot) mean = mean_ref[numpy.array(rot)] samples = dist.sample(100) isamples = dist.fwd(samples) density = dist.pdf(samples, decompose=True) caches = [{}, { (rot[0], dist): (samples[rot[0]], isamples[rot[0]]) }, { (rot[0], dist): (samples[rot[0]], isamples[rot[0]]), (rot[1], dist): (samples[rot[1]], isamples[rot[1]]) }] for idx, cache in zip(rot, caches): assert numpy.allclose( dist._get_fwd(samples[idx], idx, cache=cache.copy()), isamples[idx]) assert numpy.allclose( dist._get_inv(isamples[idx], idx, cache=cache.copy()), samples[idx]) assert numpy.allclose( dist._get_pdf(samples[idx], idx, cache=cache.copy()), density[idx]) if cache: with pytest.raises(chaospy.StochasticallyDependentError): dist[idx].fwd(samples[idx]) with pytest.raises(chaospy.StochasticallyDependentError): dist[idx].inv(isamples[idx]) with pytest.raises(chaospy.StochasticallyDependentError): dist[idx].pdf(samples[idx]) else: assert numpy.allclose(dist[idx].fwd(samples[idx]), isamples[idx]) assert numpy.allclose(dist[idx].inv(isamples[idx]), samples[idx]) assert numpy.allclose(dist[idx].pdf(samples[idx]), density[idx]) assert dist[idx].mom(1, allow_approx=False) == mean_ref[idx] assert numpy.isclose(dist[idx].mom(1, allow_approx=False), mean_ref[idx]) with pytest.raises(chaospy.StochasticallyDependentError): dist[idx].ttr(1)
def test_reduced_normalStochasticCollocation3D(self): # This is not a very good test because we are comparing the reduced collocation # against the analytical expected value. The only hting it tells us is that # the solution is within the ball park of actual value. We still need to # come up with a better test. systemsize = 3 mu = mean_3dim # np.random.randn(systemsize) std_dev = std_dev_3dim # abs(np.diag(np.random.randn(systemsize))) jdist = cp.MvNormal(mu, std_dev) # Create QoI Object QoI = examples.Paraboloid3D(systemsize) dominant_dir = np.array([[1.0, 0.0], [0.0, 1.0], [0.0, 0.0]], dtype=np.float) # Create the Stochastic Collocation object deriv_dict = { 'xi': { 'dQoI_func': QoI.eval_QoIGradient, 'output_dimensions': systemsize } } QoI_dict = { 'paraboloid': { 'QoI_func': QoI.eval_QoI, 'output_dimensions': 1, 'deriv_dict': deriv_dict } } sc_obj = StochasticCollocation2(jdist, 3, 'MvNormal', QoI_dict, reduced_collocation=True, dominant_dir=dominant_dir) sc_obj.evaluateQoIs(jdist) mu_js = sc_obj.mean(of=['paraboloid']) var_js = sc_obj.variance(of=['paraboloid']) # Analytical mean mu_j_analytical = QoI.eval_QoI_analyticalmean(mu, cp.Cov(jdist)) err = abs((mu_js['paraboloid'][0] - mu_j_analytical) / mu_j_analytical) self.assertTrue(err < 1e-1) # Analytical variance var_j_analytical = QoI.eval_QoI_analyticalvariance(mu, cp.Cov(jdist)) err = abs( (var_js['paraboloid'][0, 0] - var_j_analytical) / var_j_analytical) self.assertTrue(err < 0.01)