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 test_on_exponential(self): systemsize = 2 QoI = examples.Exp_07xp03y(systemsize) jdist = cp.J(cp.Uniform(-1,1), cp.Uniform(-1,1)) active_subspace = ActiveSubspace(QoI, n_dominant_dimensions=1, n_monte_carlo_samples=10000) active_subspace.getDominantDirections(QoI, jdist) expected_W1 = QoI.a / np.linalg.norm(QoI.a) np.testing.assert_almost_equal(active_subspace.dominant_dir[:,0], expected_W1)
def test_SVD_equivalence(self): systemsize = 4 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Create the joint distribution jdist = cp.J(cp.Uniform(-1,1), cp.Uniform(-1,1), cp.Uniform(-1,1), cp.Uniform(-1,1)) active_subspace_eigen = ActiveSubspace(QoI, n_dominant_dimensions=1, n_monte_carlo_samples=10000, use_svd=False, read_rv_samples=False, write_rv_samples=True) active_subspace_eigen.getDominantDirections(QoI, jdist) active_subspace_svd = ActiveSubspace(QoI, n_dominant_dimensions=1, n_monte_carlo_samples=10000, use_svd=True, read_rv_samples=True, write_rv_samples=False) active_subspace_svd.getDominantDirections(QoI, jdist) # Check the iso_eigenvals np.testing.assert_almost_equal(active_subspace_eigen.iso_eigenvals, active_subspace_svd.iso_eigenvals) # check the iso_eigenvecs self.assertTrue(active_subspace_eigen.iso_eigenvecs.shape, active_subspace_svd.iso_eigenvecs.shape) for i in range(active_subspace_eigen.iso_eigenvecs.shape[1]): arr1 = active_subspace_eigen.iso_eigenvecs[:,i] arr2 = active_subspace_svd.iso_eigenvecs[:,i] if np.allclose(arr1, arr2) == False: np.testing.assert_almost_equal(arr1, -arr2)
def test_on_Hadamard_Quadratic(self): systemsize = 4 eigen_decayrate = 2.0 # Create Hadmard Quadratic object QoI = examples.HadamardQuadratic(systemsize, eigen_decayrate) # Create the joint distribution jdist = cp.J(cp.Uniform(-1,1), cp.Uniform(-1,1), cp.Uniform(-1,1), cp.Uniform(-1,1)) # Create the active subspace object active_subspace = ActiveSubspace(QoI, n_dominant_dimensions=2, n_monte_carlo_samples=100000) active_subspace.getDominantDirections(QoI, jdist) # Expected C Hessian = QoI.eval_QoIHessian(np.zeros(systemsize), np.zeros(systemsize)) C = np.matmul(Hessian, Hessian) / 3 err = C - active_subspace.C_tilde self.assertTrue((abs(err) < 1.e-2).all())
1.e-4, 'correlation function': 'squar_exp', } surrogate_QoI = InterceptorSurrogateQoI(systemsize, surrogate_input_dict) # Get the dominant directions dominant_space = DimensionReduction(n_arnoldi_sample=systemsize + 1, exact_Hessian=False, sample_radius=1.e-1) dominant_space.getDominantDirections(surrogate_QoI, jdist, max_eigenmodes=10) # Get the Active Subspace active_subspace = ActiveSubspace(surrogate_QoI, n_dominant_dimensions=20, n_monte_carlo_samples=1000, read_rv_samples=False, use_svd=True, use_iso_transformation=True) active_subspace.getDominantDirections(surrogate_QoI, jdist) # Now get the two angles n_bases = 2 eigenvecs_dom = dominant_space.iso_eigenvecs[:, 0:n_bases] eigenvecs_active = active_subspace.iso_eigenvecs[:, 0:n_bases] angles_radians = utils.compute_subspace_angles(eigenvecs_dom, eigenvecs_active) angles_degrees = np.degrees(angles_radians) print(angles_degrees) """ # Finally plot xvals = range(1, n_bases+1) fname = "dominant_vs_active_angles.pdf"
def __init__(self, rv_dict, design_point, rdo_factor=2.0, krylov_pert=1.e-1, active_subspace=False, max_eigenmodes=2, n_as_samples=1000): self.rdo_factor = rdo_factor # Total number of nodes to use in the spanwise (num_y) and # chordwise (num_x) directions. Vary these to change the level of fidelity. num_y = 21 num_x = 3 mesh_dict = { 'num_y': num_y, 'num_x': num_x, 'wing_type': 'rect', 'symmetry': True, 'span_cos_spacing': 0.5, 'span': 3.11, 'root_chord': 0.3, } self.uq_systemsize = len(rv_dict) dv_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 } mu, std_dev = self.get_input_rv_statistics(rv_dict) self.jdist = cp.MvNormal(mu, std_dev) self.QoI = examples.oas_scaneagle2.OASScanEagleWrapper2( self.uq_systemsize, dv_dict) self.QoI.p['oas_scaneagle.wing.thickness_cp'] = design_point[ 'thickness_cp'] self.QoI.p['oas_scaneagle.wing.twist_cp'] = design_point['twist_cp'] self.QoI.p['oas_scaneagle.wing.sweep'] = design_point['sweep'] self.QoI.p['oas_scaneagle.alpha'] = design_point['alpha'] self.QoI.p.final_setup() # Figure out which dimension reduction technique to use start_time = time.time() if active_subspace == False: self.dominant_space = DimensionReduction( n_arnoldi_sample=self.uq_systemsize + 1, exact_Hessian=False, sample_radius=krylov_pert) self.dominant_space.getDominantDirections( self.QoI, self.jdist, max_eigenmodes=max_eigenmodes) else: self.dominant_space = ActiveSubspace( self.QoI, n_dominant_dimensions=max_eigenmodes, n_monte_carlo_samples=n_as_samples, read_rv_samples=False, use_svd=True, use_iso_transformation=True) self.dominant_space.getDominantDirections(self.QoI, self.jdist) # Reset the design point self.QoI.p['oas_scaneagle.wing.thickness_cp'] = design_point[ 'thickness_cp'] self.QoI.p['oas_scaneagle.wing.twist_cp'] = design_point[ 'twist_cp'] self.QoI.p['oas_scaneagle.wing.sweep'] = design_point['sweep'] self.QoI.p['oas_scaneagle.alpha'] = design_point['alpha'] self.QoI.p.final_setup() # Reset the random variables self.QoI.update_rv(mu) time_elapsed = time.time() - start_time print('time_elapsed =', time_elapsed) dfuelburn_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ObjGradient_dv, 'output_dimensions': dv_dict['ndv'], } } dcon_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ConGradient_dv, 'output_dimensions': dv_dict['ndv'] } } dcon_failure_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ConFailureGradient_dv, 'output_dimensions': dv_dict['ndv'], } } self.QoI_dict = { 'fuelburn': { 'QoI_func': self.QoI.eval_QoI, 'output_dimensions': 1, 'deriv_dict': dfuelburn_dict }, 'constraints': { 'QoI_func': self.QoI.eval_AllConstraintQoI, 'output_dimensions': dv_dict['n_constraints'], 'deriv_dict': dcon_dict }, 'con_failure': { 'QoI_func': self.QoI.eval_confailureQoI, 'output_dimensions': 1, 'deriv_dict': dcon_failure_dict } }
class UQScanEagleOpt(object): """ This class is the conduit for linking pyStatReduce and OpenAeroStruct with pyOptSparse. **Arguments** * `rv_dict` : The random variable dictionary which specifies the random variable, its mean and standard deviation. * `design_point` : dictionary of the design variable values. * `rdo_factor` : robust design optimization factor, its a multiplier that gets multiplied to the wuantity of interest. Currently a single value is used across all QoIs. * `krylov_pert` : finite difference perturbation for the modified Arnoldi method. * `active_subspace` : Boolean for either using active subspace or Arnoldi dimension reduction method. * `max_eigenmodes` : Maximum number of dominant directons expected from the user. This is the maximum number dominant directions that will be used in the subsequent stochastic collocation object. * `n_as_samples` : Number of monte carlo samples used by the active subspace method. This is argument is only utilized if we are using the active subspace method. """ def __init__(self, rv_dict, design_point, rdo_factor=2.0, krylov_pert=1.e-1, active_subspace=False, max_eigenmodes=2, n_as_samples=1000): self.rdo_factor = rdo_factor # Total number of nodes to use in the spanwise (num_y) and # chordwise (num_x) directions. Vary these to change the level of fidelity. num_y = 21 num_x = 3 mesh_dict = { 'num_y': num_y, 'num_x': num_x, 'wing_type': 'rect', 'symmetry': True, 'span_cos_spacing': 0.5, 'span': 3.11, 'root_chord': 0.3, } self.uq_systemsize = len(rv_dict) dv_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 } mu, std_dev = self.get_input_rv_statistics(rv_dict) self.jdist = cp.MvNormal(mu, std_dev) self.QoI = examples.oas_scaneagle2.OASScanEagleWrapper2( self.uq_systemsize, dv_dict) self.QoI.p['oas_scaneagle.wing.thickness_cp'] = design_point[ 'thickness_cp'] self.QoI.p['oas_scaneagle.wing.twist_cp'] = design_point['twist_cp'] self.QoI.p['oas_scaneagle.wing.sweep'] = design_point['sweep'] self.QoI.p['oas_scaneagle.alpha'] = design_point['alpha'] self.QoI.p.final_setup() # Figure out which dimension reduction technique to use start_time = time.time() if active_subspace == False: self.dominant_space = DimensionReduction( n_arnoldi_sample=self.uq_systemsize + 1, exact_Hessian=False, sample_radius=krylov_pert) self.dominant_space.getDominantDirections( self.QoI, self.jdist, max_eigenmodes=max_eigenmodes) else: self.dominant_space = ActiveSubspace( self.QoI, n_dominant_dimensions=max_eigenmodes, n_monte_carlo_samples=n_as_samples, read_rv_samples=False, use_svd=True, use_iso_transformation=True) self.dominant_space.getDominantDirections(self.QoI, self.jdist) # Reset the design point self.QoI.p['oas_scaneagle.wing.thickness_cp'] = design_point[ 'thickness_cp'] self.QoI.p['oas_scaneagle.wing.twist_cp'] = design_point[ 'twist_cp'] self.QoI.p['oas_scaneagle.wing.sweep'] = design_point['sweep'] self.QoI.p['oas_scaneagle.alpha'] = design_point['alpha'] self.QoI.p.final_setup() # Reset the random variables self.QoI.update_rv(mu) time_elapsed = time.time() - start_time print('time_elapsed =', time_elapsed) dfuelburn_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ObjGradient_dv, 'output_dimensions': dv_dict['ndv'], } } dcon_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ConGradient_dv, 'output_dimensions': dv_dict['ndv'] } } dcon_failure_dict = { 'dv': { 'dQoI_func': self.QoI.eval_ConFailureGradient_dv, 'output_dimensions': dv_dict['ndv'], } } self.QoI_dict = { 'fuelburn': { 'QoI_func': self.QoI.eval_QoI, 'output_dimensions': 1, 'deriv_dict': dfuelburn_dict }, 'constraints': { 'QoI_func': self.QoI.eval_AllConstraintQoI, 'output_dimensions': dv_dict['n_constraints'], 'deriv_dict': dcon_dict }, 'con_failure': { 'QoI_func': self.QoI.eval_confailureQoI, 'output_dimensions': 1, 'deriv_dict': dcon_failure_dict } } def get_input_rv_statistics(self, rv_dict): mu, std_dev = utils.get_scaneagle_input_rv_statistics(rv_dict) return mu, std_dev
start_time = time.time() sample_radius = 1.e-1 dominant_space = DimensionReduction(n_arnoldi_sample=int(sys.argv[1]), exact_Hessian=False, sample_radius=sample_radius) dominant_space.getDominantDirections(dymos_obj, jdist, max_eigenmodes=11) # end_time = time.time() time_elapsed = time.time() - start_time print('eigenvals = ', repr(dominant_space.iso_eigenvals)) # print('eigenvecs = \n', repr(dominant_space.iso_eigenvecs)) print('time elapsed = ', time_elapsed) # Save to file: if sample_radius == 1.e-1: fname = fname = os.environ['HOME'] + '/UserApps/pyStatReduce/pystatreduce/optimize/dymos_interceptor/eigenmodes/eigenmodes_' + sys.argv[1] + '_samples' elif sample_radius == 1.e-2: fname = os.environ['HOME'] + '/UserApps/pyStatReduce/pystatreduce/optimize/dymos_interceptor/eigenmodes/eigenmodes_' + sys.argv[1] + '_samples_1e_2' else: raise NotImplementedError # np.savez(fname, eigenvals=dominant_space.iso_eigenvals, eigenvecs=dominant_space.iso_eigenvecs) elif use_active_subspace == True: dominant_space = ActiveSubspace(dymos_obj, n_dominant_dimensions=20, n_monte_carlo_samples=1000, read_rv_samples=False, use_svd=True, use_iso_transformation=True) dominant_space.getDominantDirections(dymos_obj, jdist) fname = os.environ['HOME'] + '/UserApps/pyStatReduce/pystatreduce/optimize/dymos_interceptor/eigenmodes/eigenmodes_1000_samples_active_subspace' np.savez(fname, eigenvals=dominant_space.iso_eigenvals, eigenvecs=dominant_space.iso_eigenvecs)