def setDVGeo(ffdFile, cmplx=False): # Setup geometry/mesh DVGeo = DVGeometry(ffdFile, complex=cmplx) nTwist = 6 DVGeo.addRefAxis( "wing", Curve( x=numpy.linspace(5.0 / 4.0, 1.5 / 4.0 + 7.5, nTwist), y=numpy.zeros(nTwist), z=numpy.linspace(0, 14, nTwist), k=2, ), ) def twist(val, geo): for i in range(nTwist): geo.rot_z["wing"].coef[i] = val[i] def span(val, geo): C = geo.extractCoef("wing") s = geo.extractS("wing") for i in range(len(C)): C[i, 2] += s[i] * val[0] geo.restoreCoef(C, "wing") DVGeo.addGlobalDV("twist", [0] * nTwist, twist, lower=-10, upper=10, scale=1.0) DVGeo.addGlobalDV("span", [0], span, lower=-10, upper=10, scale=1.0) DVGeo.addLocalDV("shape", lower=-0.5, upper=0.5, axis="y", scale=10.0) return DVGeo
def setup_cb(comm): # Create the solver CFDSolver = ADFLOW(options=options, comm=comm, debug=False) # Setup geometry/mesh DVGeo = DVGeometry(ffdFile) nTwist = 6 DVGeo.addRefAxis( 'wing', Curve(x=numpy.linspace(5.0 / 4.0, 1.5 / 4.0 + 7.5, nTwist), y=numpy.zeros(nTwist), z=numpy.linspace(0, 14, nTwist), k=2)) def twist(val, geo): for i in range(nTwist): geo.rot_z['wing'].coef[i] = val[i] DVGeo.addGeoDVGlobal('twist', [0] * nTwist, twist, lower=-10, upper=10, scale=1.0) DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y', scale=10.0) mesh = USMesh(options=meshOptions, comm=comm) CFDSolver.setMesh(mesh) CFDSolver.setDVGeo(DVGeo) return CFDSolver, mesh, DVGeo, None
def generate_dvgeo_dvcon_c172(self): meshfile = os.path.join(self.base_path, '../inputFiles/c172.stl') ffdfile = os.path.join(self.base_path, '../inputFiles/c172.xyz') testmesh = mesh.Mesh.from_file(meshfile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension # create a DVGeo object with a few local thickness variables DVGeo = DVGeometry(ffdfile) nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] DVGeo.addGeoDVGlobal(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing DVCon =DVConstraints() DVCon.setDVGeo(DVGeo) p0 = testmesh.vectors[:,0,:] / 1000 v1 = testmesh.vectors[:,1,:] / 1000 - p0 v2 = testmesh.vectors[:,2,:] / 1000 - p0 DVCon.setSurface([p0, v1, v2]) return DVGeo, DVCon
def test_24_rot0_nonaligned(self, train=False, refDeriv=False): """ Test 24 This test ensures that the scaling attributes (scale_x, scale_y, and scale_z) are effective when rotType=0 is selected. Moreover, this test ensures that rotType=0 reference axis can handle (given appropriate input parameters) FFD blocks that are not aligned with the main system of reference, e.g. the blades of a 3-bladed wind turbine rotor. The newly added input parameters rot0ang and rot0axis are used to provide the user control on this. The operations that pyGeo performs for this test are the following: We start from an initial "vertical" FFD box which, using the combination of rotType=0, rot0ang=-90, and rot0axis=[1,0,0] for addRefAxis(), is first rotated to have its "spanwise" axis along the y axis. Then, the script scales the 2nd section along the z axis for a "thickness" increase and the 4th section along the x axis for "chord" increase, it adds a +/- 30 deg twist respectively, and finally rotates the deformed FFD back in the initial position. The twist is added to ensure that the operation order is maintained, and the scaling preserves the orthogonality of the FFD in the section plane. This is a particular case as the FFD box is already aligned with the main axis and we "flip" the y and z axes, but the same criteria can be applied to a general rotation. """ refFile = os.path.join(self.base_path, "ref/test_DVGeometry_24.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test twist and scaling for FFDs non-aligned to main system of reference") DVGeo = DVGeometry(os.path.join(self.base_path, "../../input_files/2x1x8_rectangle.xyz")) rotType = 0 xfraction = 0.5 nRefAxPts = DVGeo.addRefAxis("RefAx", xFraction=xfraction, alignIndex="k", rotType=rotType, rot0ang=-90) fix_root_sect = 1 nTwist = nRefAxPts - fix_root_sect DVGeo.addGlobalDV(dvName="twist", value=[0] * nTwist, func=commonUtils.twist, lower=-90, upper=90, scale=1) DVGeo.addGlobalDV( dvName="thickness", value=[1.0] * nTwist, func=commonUtils.thickness, lower=0.7, upper=5.0, scale=1 ) DVGeo.addGlobalDV( dvName="chord", value=[1.0] * nTwist, func=commonUtils.chord, lower=0.7, upper=5.0, scale=1 ) commonUtils.testSensitivities(DVGeo, refDeriv, handler, pointset=2) x = DVGeo.getValues() # Modifying the twist keyName = "twist" twistTest = [30, 0, -30] x[keyName] = twistTest # Modifying the chord keyName = "thickness" thickTest = [3.0, 1.0, 1.0] x[keyName] = thickTest # Modifying the chord keyName = "chord" chordTest = [1.0, 1.0, 2.0] x[keyName] = chordTest DVGeo.setDesignVars(x) DVGeo.update("testPoints") FFD_coords = DVGeo.FFD.coef.copy() handler.root_add_val("Updated FFD coordinates", FFD_coords, rtol=1e-12, atol=1e-12)
def test_1(self, train=False, refDeriv=False): refFile = os.path.join(self.base_path, 'ref/test_Cylinder_01.ref') with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test 1: Basic FFD, global DVs") radius = 1.0 height = 10.0 DVCon = DVConstraints() surf = self.make_cylinder_mesh(radius, height) DVCon.setSurface(surf) # DVCon.writeSurfaceTecplot('cylinder_surface.dat') ffd_name = os.path.join(self.base_path, '../inputFiles/cylinder_ffd.xyz') self.make_ffd(ffd_name, radius, height) DVGeo = DVGeometry(ffd_name) nAxPts = DVGeo.addRefAxis('thru', xFraction=0.5, alignIndex='i', raySize=1.0) def scale_circle(val, geo): for i in range(nAxPts): geo.scale['thru'].coef[i] = val[0] DVGeo.addGeoDVGlobal('scale_circle', func=scale_circle, value=[1]) DVCon.setDVGeo(DVGeo) leList = [[0, 0, 0], [-radius / 2, 0, height]] xAxis = [-1, 0, 0] yAxis = [0, 1, 0] DVCon.addLERadiusConstraints(leList, nSpan=5, axis=yAxis, chordDir=xAxis, scaled=False) # DVCon.writeTecplot('cylinder_constraints.dat') funcs = {} DVCon.evalFunctions(funcs) print(funcs) handler.root_add_dict('funcs1', funcs, rtol=1e-6, atol=1e-6) DVGeo.setDesignVars({'scale_circle': 0.5}) funcs = {} DVCon.evalFunctions(funcs) handler.root_add_dict('funcs2', funcs, rtol=1e-6, atol=1e-6) print(funcs) funcsSens = {} DVCon.evalFunctionsSens(funcsSens) print(funcsSens) handler.root_add_dict('funcsSens', funcsSens, rtol=1e-6, atol=1e-6) print(funcsSens)
def test_23_xyzFraction(self, train=False): """ Test 23 This test verifies the correct implementation of the generalized `xFraction`, `yFraction` (and indirectly `zFraction`) Given an arbitrary input for the in-plane location of the reference axis nodes, the test sets up the axis object and compares the nodes location with a reference file. As the geometry of the FFD box is simple, the values can be also hand calculated: xFraction = 0.3, FFD x interval [-1,1] ---> 0.6 displacement from x min (% displ calculated from LE=xmin) --> x = -0.4 yFraction = 0.6, FFD y interval [-0.5,0.5] ---> 0.6 displacement from y max (% displ calculated from top of the box=ymax) --> x = -0.1 """ refFile = os.path.join(self.base_path, "ref/test_DVGeometry_23.ref") with BaseRegTest(refFile, train=train) as handler: handler.root_print("Test generalized axis node location section in plane") DVGeo = DVGeometry(os.path.join(self.base_path, "../../input_files/2x1x8_rectangle.xyz")) xfraction = 0.3 yfraction = 0.6 rotType = 0 DVGeo.addRefAxis("RefAx", xFraction=xfraction, yFraction=yfraction, alignIndex="k", rotType=rotType) nodes_loc = DVGeo.axis["RefAx"]["curve"].X handler.root_add_val("RefAxis_nodes_coord", nodes_loc, rtol=1e-12, atol=1e-12)
def setupDVGeoD8(base_path, isComplex): # create the Parent FFD FFDFile = os.path.join(base_path, "../../input_files/bodyFFD.xyz") DVGeo = DVGeometry(FFDFile, isComplex=isComplex) # create a reference axis for the parent axisPoints = [[0.0, 0.0, 0.0], [26.0, 0.0, 0.0], [30.5, 0.0, 0.9], [32.5, 0.0, 1.01], [34.0, 0.0, 0.95]] c1 = Curve(X=axisPoints, k=2) DVGeo.addRefAxis("mainAxis", curve=c1, axis="y") # create the child FFD FFDFile = os.path.join(base_path, "../../input_files/nozzleFFD.xyz") DVGeoChild = DVGeometry(FFDFile, child=True, isComplex=isComplex) # create a reference axis for the child axisPoints = [[32.4, 1.0, 1.0], [34, 1.0, 0.9]] c1 = Curve(X=axisPoints, k=2) DVGeoChild.addRefAxis("nestedAxis", curve=c1, axis="y") return DVGeo, DVGeoChild
def setupDVGeo(base_path): #create the Parent FFD FFDFile = os.path.join(base_path,'../inputFiles/outerBoxFFD.xyz') DVGeo = DVGeometry(FFDFile) # create a reference axis for the parent axisPoints = [[ -1.0, 0. , 0.],[ 1.5, 0., 0.]] c1 = Curve(X=axisPoints,k=2) DVGeo.addRefAxis('mainAxis',curve=c1, axis='y') # create the child FFD FFDFile = os.path.join(base_path,'../inputFiles/simpleInnerFFD.xyz') DVGeoChild = DVGeometry(FFDFile,child=True) # create a reference axis for the child axisPoints = [[ -0.5, 0. , 0.],[ 0.5, 0., 0.]] c1 = Curve(X=axisPoints,k=2) DVGeoChild.addRefAxis('nestedAxis',curve=c1, axis='y') return DVGeo,DVGeoChild
def deform_DVGeo(geo): # ========================================================================= # Setup DVGeometry object # ========================================================================= # rst DVGeometry DVGeo = DVGeometry(input_files + "deform_geometry_ffd.xyz") # Create reference axis nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") # Set the Twist Variable def twist(val, geo): for i in range(nRefAxPts): geo.rot_z["wing"].coef[i] = val[i] # Add the Twist Design Variable to DVGeo DVGeo.addGlobalDV(dvName="twist", value=[0] * nRefAxPts, func=twist, lower=-10, upper=10, scale=1.0) # Get Design Variables dvDict = DVGeo.getValues() # Set First Twist Section to 5deg dvDict["twist"][0] = 5 # Set Design Variables DVGeo.setDesignVars(dvDict) # rst DVGeometry (end) # ========================================================================= # Update pyGeo Object and output result # ========================================================================= # rst UpdatePyGeo DVGeo.updatePyGeo(geo, "tecplot", "wingNew", nRefU=10, nRefV=10)
def setup_blocks(self, testID, isComplex=False): # Make tiny FFD ffd_name = '../inputFiles/tiny_cube_{:02d}.xyz'.format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 1, 1, 1, 1, 1, 1) tiny = DVGeometry(file_name, child=True, complex=isComplex) os.remove(file_name) tiny.addRefAxis('ref', xFraction=0.5, alignIndex='j', rotType=7) # Make tiny FFD ffd_name = '../inputFiles/small_cube_{:02d}.xyz'.format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 0, 0, 0, 2, 2, 2) small = DVGeometry(file_name, child=True, complex=isComplex) os.remove(file_name) small.addRefAxis('ref', xFraction=0.5, alignIndex='j') # Make big FFD ffd_name = '../inputFiles/big_cube_{:02d}.xyz'.format(testID) file_name = os.path.join(self.base_path, ffd_name) self.make_cube_ffd(file_name, 0, 0, 0, 3, 3, 3) big = DVGeometry(file_name, complex=isComplex) os.remove(file_name) big.addRefAxis('ref', xFraction=0.5, alignIndex='i') big.addChild(small) small.addChild(tiny) # Add point set points = numpy.array([ [0.5, 0.5, 0.5], [1.25, 1.25, 1.25], [1.5, 1.5, 1.5], [2.0, 2.5, 0.5], ]) big.addPointSet(points, 'X') return big, small, tiny
def setupDVGeo(base_path, rotType=None): # create the Parent FFD FFDFile = os.path.join(base_path, "../inputFiles/outerBoxFFD.xyz") DVGeo = DVGeometry(FFDFile) # create a reference axis for the parent axisPoints = [[-1.0, 0.0, 0.0], [1.5, 0.0, 0.0]] c1 = Curve(X=axisPoints, k=2) if rotType is not None: DVGeo.addRefAxis("mainAxis", curve=c1, axis="y", rotType=rotType) else: DVGeo.addRefAxis("mainAxis", curve=c1, axis="y") # create the child FFD FFDFile = os.path.join(base_path, "../inputFiles/simpleInnerFFD.xyz") DVGeoChild = DVGeometry(FFDFile, child=True) # create a reference axis for the child axisPoints = [[-0.5, 0.0, 0.0], [0.5, 0.0, 0.0]] c1 = Curve(X=axisPoints, k=2) DVGeoChild.addRefAxis("nestedAxis", curve=c1, axis="y") return DVGeo, DVGeoChild
chordRef=3.25, evalFuncs=["cl", "cd"]) # Add angle of attack variable ap.addDV("alpha", value=1.5, lower=0, upper=10.0, scale=0.1) # rst aeroproblem (end) # ====================================================================== # Geometric Design Variable Set-up # ====================================================================== # rst dvgeo (beg) # Create DVGeometry object FFDFile = "ffd.xyz" DVGeo = DVGeometry(FFDFile) # Create reference axis nRefAxPts = DVGeo.addRefAxis("wing", xFraction=0.25, alignIndex="k") nTwist = nRefAxPts - 1 # Set up global design variables def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] DVGeo.addGlobalDV(dvName="twist", value=[0] * nTwist, func=twist, lower=-10, upper=10, scale=0.01)
def test_parent_shape_child_rot(self, train=False, refDeriv=False): ffd_name = '../../tests/inputFiles/small_cube.xyz' self.make_cube_ffd(ffd_name, 0.1, 0.1, 0.1, 0.8, 0.8, 0.8) small = DVGeometry(ffd_name, child=True) small.addRefAxis('ref', xFraction=0.5, alignIndex='j') x0 = 0.0 y0 = 0.0 z0 = 0.0 dx = 1.0 dy = 1.0 dz = 1.0 axes = ['k', 'j', 'i'] slices = numpy.array( # Slice 1 [ [[[x0, y0, z0], [x0 + dx, y0, z0], [x0 + 2 * dx, y0, z0]], [[x0, y0 + dy, z0], [x0 + dx, y0 + dy, z0], [x0 + 2 * dx, y0 + dy, z0]]], # Slice 2 [[[x0, y0, z0 + dz], [x0 + dx, y0, z0 + dz], [x0 + 2 * dx, y0, z0 + dz]], [[x0, y0 + dy, z0 + dz], [x0 + dx, y0 + dy, z0 + dz], [x0 + 2 * dx, y0 + dy, z0 + dz]]] ], dtype='d') N0 = [2] N1 = [2] N2 = [3] ffd_name = '../../tests/inputFiles/big_cube.xyz' geo_utils.write_wing_FFD_file(ffd_name, slices, N0, N1, N2, axes=axes) big = DVGeometry(ffd_name) big.addRefAxis('ref', xFraction=0.5, alignIndex='j') big.addChild(small) # Add point set points = numpy.array([[0.5, 0.5, 0.5]]) big.addPointSet(points, 'X') # Add only translation variables add_vars(big, 'big', local='z', rotate='y') add_vars(small, 'small', rotate='y') ang = 45 ang_r = numpy.deg2rad(ang) # Modify design variables x = big.getValues() # add a local shape change x['local_z_big'] = numpy.array( [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5]) big.setDesignVars(x) Xs = big.update('X') # add a rotation of the child FFD x['rotate_y_small'] = ang big.setDesignVars(x) Xrot_ffd = big.update('X') # the modification caused by the child FFD should be the same as rotating the deformed point of the parent # (you would think) rot_mat = numpy.array([[numpy.cos(ang_r), 0, numpy.sin(ang_r)], [0, 1, 0], [-numpy.sin(ang_r), 0, numpy.cos(ang_r)]]) Xrot = numpy.dot(rot_mat, (Xs - points).T) + points.T numpy.testing.assert_array_almost_equal(Xrot_ffd.T, Xrot)
def createFFD(): # Bounding box for bump x_root_range = [-0.1, 3.1] y_root_range = [-0.1, 1.1] z_root_range = [-0.1, 1.1] # Number of FFD control points per dimension nX = 10 # streamwise nY = 2 nZ = 2 # only modify the top control points # Compute grid points span_dist = np.linspace(0, 1, nX) x_sections = span_dist * (x_root_range[1] - x_root_range[0]) + x_root_range[0] z_sections = z_root_range X = np.zeros((nX, nY, nZ)) Y = np.zeros((nX, nY, nZ)) Z = np.zeros((nX, nY, nZ)) for i in range(nX): for j in range(nY): for k in range(nZ): X[i, j, k] = x_sections[i] Y[i, j, k] = y_root_range[j] Z[i, j, k] = z_sections[k] # rst Write # Write FFD to file filename = "plateffdp.xyz" f = open(filename, "w") f.write("\t\t1\n") f.write("\t\t%d\t\t%d\t\t%d\n" % (nX, nY, nZ)) for set in [X, Y, Z]: for k in range(nZ): for j in range(nY): for i in range(nX): f.write("\t%3.8f" % (set[i, j, k])) f.write("\n") f.close() # Create the child FFD, actual DVs defined on this # Bounding box for bump x_root_range_c = optOptions['bumpBounds'] y_root_range_c = [-0.05, 1.05] z_root_range_c = [-0.05, 0.95] # Number of FFD control points per dimension nXc = optOptions['NX'] # streamwise nYc = 2 nZc = 3 # only modify the top control points # Compute grid points span_dist_c = np.linspace(0, 1, nXc) x_sections_c = span_dist_c * (x_root_range_c[1] - x_root_range_c[0]) + x_root_range_c[0] z_span_dist_c = np.linspace(0, 1, nZc) z_sections_c = z_span_dist_c * (z_root_range_c[1] - z_root_range_c[0]) + z_root_range_c[0] Xc = np.zeros((nXc, nYc, nZc)) Yc = np.zeros((nXc, nYc, nZc)) Zc = np.zeros((nXc, nYc, nZc)) for i in range(nXc): for j in range(nYc): for k in range(nZc): Xc[i, j, k] = x_sections_c[i] Yc[i, j, k] = y_root_range_c[j] Zc[i, j, k] = z_sections_c[k] # rst Write # Write FFD to file filenamec = "plateffdc.xyz" fc = open(filenamec, "w") fc.write("\t\t1\n") fc.write("\t\t%d\t\t%d\t\t%d\n" % (nXc, nYc, nZc)) for set in [Xc, Yc, Zc]: for k in range(nZc): for j in range(nYc): for i in range(nXc): fc.write("\t%3.8f" % (set[i, j, k])) fc.write("\n") fc.close() # define the design variables #add point set here? no # meshOptions = warpOptions # mesh = USMesh(options=meshOptions) # coords = mesh.getSurfaceCoordinates() DVGeo = DVGeometry(filename) #DVGeo.addPointSet(coords, "coords") DVGeoc = DVGeometry(filenamec, child=True) DVGeoc.addRefAxis('dummy_axis', xFraction=0.1, alignIndex='i') DVGeo.addChild(DVGeoc) # local design vars are just the Z-positions of (some) upper control points length = x_root_range_c[1] - x_root_range_c[0] z_mid = (z_root_range_c[1] + z_root_range_c[0]) / 2 frac = optOptions['DVFraction'] P1 = [x_root_range_c[0] + frac * length, 0, z_mid / 2] P2 = [x_root_range_c[1] - frac * length, 0, 3 * z_mid / 2] PS = geo_utils.PointSelect(psType='y', pt1=P1, pt2=P2) # vname = "pnts" UB = optOptions['DVUpperBound'] DVGeoc.addGeoDVLocal(dvName=vname, lower=0.0, upper=UB, axis="z", scale=1, pointSelect=PS) return DVGeo # # test out on a mesh # gridFile = "grid_struct_69x49_vol_mod2.cgns" # meshOptions = warpOptions # meshOptions["gridfile"] = gridFile # mesh = USMesh(options=meshOptions) # coords = mesh.getSurfaceCoordinates() # DVGeo.addPointSet(coords, "coords") # dvDict = DVGeoc.getValues() # #for i in range(int(nXc/2)): # dvDict["pnts"][:] = 0.2 # # dvDict["pnts"][2] = 0.2 # # dvDict["pnts"][3] = 0.2 # # dvDict["pnts"][4] = 0.1 # # dvDict["pnts"][5] = 0.1 # # dvDict["pnts"][6] = 0.1 # # dvDict["pnts"][7] = 0.1 # DVGeoc.setDesignVars(dvDict) # DVGeoc.printDesignVariables() # new_coords = DVGeo.update("coords") # DVGeoc.writePlot3d("ffdc_deformed.xyz") # #DVGeo.writePointSet("coords", "surf") # # move the mesh using idwarp # # Reset the newly computed surface coordiantes # mesh.setSurfaceCoordinates(new_coords) # # Actually run the mesh warping # mesh.warpMesh() # # Write the new grid file. # mesh.writeGrid(f'ffd_warped.cgns')
mesh = USMesh(options=meshOptions, comm=gcomm) coords0 = mesh.getSurfaceCoordinates() # setup FFD FFDFile = "./FFD/globalFFD.fmt" DVGeo = DVGeometry(FFDFile) # Setup curves for ref_axis x = [-2.0, 0.0, 0.1, 1.044, 5.0] y = [0.1, 0.1, 0.1, 0.1, 0.1] z = [0.1, 0.1, 0.1, 0.1, 0.1] nLength = len(x) c1 = Curve(x=x, y=y, z=z, k=2) DVGeo.addRefAxis("bodyAxis", curve=c1, axis="z") DVGeoChild = DVGeometry("./FFD/bodyFittedFFD.fmt", child=True) # Setup curves for ref_axis x1 = [0.0, 0.1, 0.862, 1.044] y1 = [0.1, 0.1, 0.1, 0.1] z1 = [0.194, 0.194, 0.194, 0.13] # z1 = [0.338,0.338,0.338,0.21] # z1 = [0.338,0.338,0.338,0.338] nLengthChild = len(x1) c2 = Curve(x=x1, y=y1, z=z1, k=2) DVGeoChild.addRefAxis("localBodyAxis", curve=c2, axis="z")
#rst Import libraries import numpy from pygeo import DVGeometry from idwarp import USMesh #rst Create DVGeometry object FFDFile = 'ffd.xyz' DVGeo = DVGeometry(FFDFile) #rst Create reference axis nRefAxPts = DVGeo.addRefAxis('wing', xFraction=0.25, alignIndex='k') #rst Dihedral def dihedral(val, geo): C = geo.extractCoef('wing') for i in range(1, nRefAxPts): C[i, 1] += val[i - 1] geo.restoreCoef(C, 'wing') #rst Twist def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z['wing'].coef[i] = val[i - 1] #rst Taper def taper(val, geo): s = geo.extractS('wing') slope = (val[1] - val[0]) / (s[-1] - s[0])
def test_parent_shape_child_rot(self, train=False, refDeriv=False): ffd_name = "../../input_files/small_cube.xyz" self.make_cube_ffd(ffd_name, 0.1, 0.1, 0.1, 0.8, 0.8, 0.8) small = DVGeometry(ffd_name, child=True) small.addRefAxis("ref", xFraction=0.5, alignIndex="j") x0 = 0.0 y0 = 0.0 z0 = 0.0 dx = 1.0 dy = 1.0 dz = 1.0 axes = ["k", "j", "i"] slices = np.array( # Slice 1 [ [ [[x0, y0, z0], [x0 + dx, y0, z0], [x0 + 2 * dx, y0, z0]], [[x0, y0 + dy, z0], [x0 + dx, y0 + dy, z0], [x0 + 2 * dx, y0 + dy, z0]], ], # Slice 2 [ [[x0, y0, z0 + dz], [x0 + dx, y0, z0 + dz], [x0 + 2 * dx, y0, z0 + dz]], [[x0, y0 + dy, z0 + dz], [x0 + dx, y0 + dy, z0 + dz], [x0 + 2 * dx, y0 + dy, z0 + dz]], ], ], dtype="d", ) N0 = [2] N1 = [2] N2 = [3] ffd_name = "../../input_files/big_cube.xyz" geo_utils.write_wing_FFD_file(ffd_name, slices, N0, N1, N2, axes=axes) big = DVGeometry(ffd_name) big.addRefAxis("ref", xFraction=0.5, alignIndex="j") big.addChild(small) # Add point set points = np.array([[0.5, 0.5, 0.5]]) big.addPointSet(points, "X") # Add only translation variables add_vars(big, "big", local="z", rotate="y") add_vars(small, "small", rotate="y") ang = 45 ang_r = np.deg2rad(ang) # Modify design variables x = big.getValues() # add a local shape change x["local_z_big"] = np.array( [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5]) big.setDesignVars(x) Xs = big.update("X") # add a rotation of the child FFD x["rotate_y_small"] = ang big.setDesignVars(x) Xrot_ffd = big.update("X") # the modification caused by the child FFD should be the same as rotating the deformed point of the parent # (you would think) rot_mat = np.array([[np.cos(ang_r), 0, np.sin(ang_r)], [0, 1, 0], [-np.sin(ang_r), 0, np.cos(ang_r)]]) Xrot = np.dot(rot_mat, (Xs - points).T) + points.T np.testing.assert_array_almost_equal(Xrot_ffd.T, Xrot)
def regression_test(self, handler): ''' This is where the actual testing happens. ''' import copy from mpi4py import MPI from baseclasses import AeroProblem from ... import ADFLOW from pyspline import Curve from pygeo import DVGeometry from idwarp import USMesh from commonUtils import adjoint_test, adflowDefOpts, IDWarpDefOpts comm = MPI.COMM_WORLD gridFile = 'input_files/mdo_tutorial_euler_scalar_jst.cgns' ffdFile = 'input_files/mdo_tutorial_ffd.fmt' options = copy.copy(adflowDefOpts) options.update({ 'gridfile': gridFile, 'restartfile': gridFile, 'mgcycle': '2w', 'ncyclescoarse': 250, 'ncycles': 500, 'monitorvariables': ['cpu', 'resrho', 'cl', 'cd', 'cmz', 'totalr'], 'usenksolver': True, 'l2convergence': 1e-14, 'l2convergencecoarse': 1e-2, 'nkswitchtol': 1e-2, 'adjointl2convergence': 1e-14, 'solutionprecision': 'double', 'gridprecision': 'double', }) # Setup aeroproblem, cfdsolver, mesh and geometry. ap = AeroProblem(name='mdo_tutorial', alpha=1.8, mach=0.80, P=20000.0, T=220.0, areaRef=45.5, chordRef=3.25, beta=0.0, R=287.87, xRef=0.0, yRef=0.0, zRef=0.0, evalFuncs=['cl', 'cd']) # Create the solver CFDSolver = ADFLOW(options=options, comm=comm, debug=False) # Create mesh warper meshOptions = copy.copy(IDWarpDefOpts) meshOptions.update({'gridFile': gridFile}) mesh = USMesh(options=meshOptions, comm=comm) CFDSolver.setMesh(mesh) # Setup geometry/mesh DVGeo = DVGeometry(ffdFile) nTwist = 6 DVGeo.addRefAxis( 'wing', Curve(x=numpy.linspace(5.0 / 4.0, 1.5 / 4.0 + 7.5, nTwist), y=numpy.zeros(nTwist), z=numpy.linspace(0, 14, nTwist), k=2)) def twist(val, geo): for i in range(nTwist): geo.rot_z['wing'].coef[i] = val[i] DVGeo.addGeoDVGlobal('twist', [0] * nTwist, twist, lower=-10, upper=10, scale=1.0) DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y', scale=10.0) CFDSolver.setDVGeo(DVGeo) # Run adjoint test adjoint_test(handler, CFDSolver, ap)
# Set the chord as well geo.scale['wing'].coef[-1] = val[3] coords = hyp.getSurfaceCoordinates() DVGeo = DVGeometry(ffd_file) coef = DVGeo.FFD.vols[0].coef.copy() # First determine the reference chord lengths: nSpan = coef.shape[2] ref = numpy.zeros((nSpan, 3)) for k in range(nSpan): max_x = numpy.max(coef[:, :, k, 0]) min_x = numpy.min(coef[:, :, k, 0]) ref[k, 0] = min_x + 0.25 * (max_x - min_x) ref[k, 1] = numpy.average(coef[:, :, k, 1]) ref[k, 2] = numpy.average(coef[:, :, k, 2]) c0 = pySpline.Curve(X=ref, k=2) DVGeo.addRefAxis('wing', c0) DVGeo.addGeoDVGlobal('winglet', [0, 0, 0, 1], winglet, lower=-5, upper=5) DVGeo.addPointSet(coords, 'coords') DVGeo.setDesignVars({'winglet': [1.5, 2.5, -2.0, .60]}) hyp.setSurfaceCoordinates(DVGeo.update('coords')) # Run and write grid hyp.run() hyp.writeCGNS('717.cgns')
def test_triangulatedSurface_intersected_2DVGeos(self, train=False, refDeriv=False): refFile = os.path.join(self.base_path, "ref/test_DVConstraints_triangulatedSurface_intersected_2DVGeos.ref") with BaseRegTest(refFile, train=train) as handler: meshFile = os.path.join(self.base_path, "../../input_files/bwb.stl") objFile = os.path.join(self.base_path, "../../input_files/blob_bwb_wing.stl") ffdFile = os.path.join(self.base_path, "../../input_files/bwb.xyz") testMesh = mesh.Mesh.from_file(meshFile) testObj = mesh.Mesh.from_file(objFile) # test mesh dim 0 is triangle index # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension # create a DVGeo object with a few local thickness variables DVGeo1 = DVGeometry(ffdFile) nRefAxPts = DVGeo1.addRefAxis("wing", xFraction=0.25, alignIndex="k") self.nTwist = nRefAxPts - 1 def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] DVGeo1.addGlobalDV(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo1.addLocalDV("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVGeo object with a few local thickness variables DVGeo2 = DVGeometry(ffdFile, name="blobdvgeo") DVGeo2.addLocalDV("local_2", lower=-0.5, upper=0.5, axis="y", scale=1) # check that DVGeos with duplicate var names are not allowed DVGeo3 = DVGeometry(ffdFile) DVGeo3.addLocalDV("local", lower=-0.5, upper=0.5, axis="y", scale=1) # create a DVConstraints object for the wing DVCon = DVConstraints() DVCon.setDVGeo(DVGeo1) DVCon.setDVGeo(DVGeo2, name="second") with self.assertRaises(ValueError): DVCon.setDVGeo(DVGeo3, name="third") p0 = testMesh.vectors[:, 0, :] v1 = testMesh.vectors[:, 1, :] - p0 v2 = testMesh.vectors[:, 2, :] - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=True) p0b = testObj.vectors[:, 0, :] v1b = testObj.vectors[:, 1, :] - p0b v2b = testObj.vectors[:, 2, :] - p0b p0b = p0b + np.array([0.0, 0.3, 0.0]) DVCon.setSurface([p0b, v1b, v2b], name="blob", addToDVGeo=True, DVGeoName="second") DVCon.addTriangulatedSurfaceConstraint("default", "default", "blob", "second", rho=10.0, addToPyOpt=True) funcs = {} DVCon.evalFunctions(funcs, includeLinear=True) handler.root_add_dict("funcs_base", funcs, rtol=1e-6, atol=1e-6) funcsSens = {} DVCon.evalFunctionsSens(funcsSens, includeLinear=True) # regress the derivatives handler.root_add_dict("derivs_base", funcsSens, rtol=1e-6, atol=1e-6) # FD check DVGeo1 funcsSensFD = evalFunctionsSensFD(DVGeo1, DVCon, fdstep=1e-3) at_least_one_var = False for outkey in funcs.keys(): for inkey in DVGeo1.getValues().keys(): analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-3, atol=1e-3) # make sure there are actually checks happening self.assertTrue(np.abs(np.sum(fd)) > 1e-10) at_least_one_var = True self.assertTrue(at_least_one_var) # FD check DVGeo2 funcsSensFD = evalFunctionsSensFD(DVGeo2, DVCon, fdstep=1e-3) at_least_one_var = False for outkey in funcs.keys(): for inkey in DVGeo2.getValues().keys(): analytic = funcsSens[outkey][inkey] fd = funcsSensFD[outkey][inkey] handler.assert_allclose(analytic, fd, name="finite_diff_check", rtol=1e-3, atol=1e-3) self.assertTrue(np.abs(np.sum(fd)) > 1e-10) at_least_one_var = True self.assertTrue(at_least_one_var)
h = 1e-40 # Setup aeroproblem, cfdsolver ap = AeroProblem(name='mdo_tutorial', alpha=1.8, mach=0.80, R=287.87, altitude=10000.0, areaRef=45.5, chordRef=3.25, evalFuncs=['cl','cmz','drag']) CFDSolver = ADFLOW(options=aeroOptions) if 'complex' in sys.argv: DVGeo = DVGeometry('../inputFiles/mdo_tutorial_ffd.fmt', complex=True) else: DVGeo = DVGeometry('../inputFiles/mdo_tutorial_ffd.fmt', complex=False) nTwist = 2 DVGeo.addRefAxis('wing', pyspline.Curve(x=numpy.linspace(5.0/4.0, 1.5/4.0+7.5, nTwist), y=numpy.zeros(nTwist), z=numpy.linspace(0,14, nTwist), k=2)) def twist(val, geo): for i in range(nTwist): geo.rot_z['wing'].coef[i] = val[i] def span(val, geo): # Span C = geo.extractCoef('wing') s = geo.extractS('wing') for i in range(len(C)-1): C[-1, 2] = C[-1, 2] + val[0] geo.restoreCoef(C, 'wing') DVGeo.addGeoDVGlobal('twist', [0]*nTwist, twist, lower=-10, upper=10, scale=1.0) DVGeo.addGeoDVGlobal('span', [0], span, lower=-10, upper=10, scale=1.0)
alpha=3., chordRef=0.24, evalFuncs=['cl', 'cd']) #rst initial # Add angle of attack variable ap.addDV('alpha', value=3., lower=0, upper=10.0, scale=0.1) # Create DVGeometry object for front wing FFDFile_front = 'ffd_front_wing.xyz' DVGeo_front = DVGeometry(FFDFile_front, child=True) # Create reference axis for the front wing nRefAxPts_front = DVGeo_front.addRefAxis('wing_front', xFraction=0.25, alignIndex='k') nTwist_front = nRefAxPts_front - 1 # Create DVGeometry object for back wing FFDFile_back = 'ffd_back_wing.xyz' DVGeo_back = DVGeometry(FFDFile_back, child=True) # Create reference axis for the back wing nRefAxPts_back = DVGeo_back.addRefAxis('wing_back', xFraction=0.25, alignIndex='k') nTwist_back = nRefAxPts_back - 1 # Set up global DVGeometry object FFDFile_GLOBAL = 'ffd_global.xyz'
def generate_dvgeo_dvcon(self, geometry, addToDVGeo=False, intersected=False): """ This function creates the DVGeometry and DVConstraints objects for each geometry used in this class. The C172 wing represents a typical use case with twist and shape variables. The rectangular box is primarily used to test unscaled constraint function values against known values for thickness, volume, and surface area. The BWB is used for the triangulated surface and volume constraint tests. The RAE 2822 wing is used for the curvature constraint test. """ if geometry == "c172": meshFile = os.path.join(self.base_path, "../../input_files/c172.stl") ffdFile = os.path.join(self.base_path, "../../input_files/c172.xyz") xFraction = 0.25 meshScale = 1e-3 elif geometry == "box": meshFile = os.path.join(self.base_path, "../../input_files/2x1x8_rectangle.stl") ffdFile = os.path.join(self.base_path, "../../input_files/2x1x8_rectangle.xyz") xFraction = 0.5 meshScale = 1 elif geometry == "bwb": meshFile = os.path.join(self.base_path, "../../input_files/bwb.stl") ffdFile = os.path.join(self.base_path, "../../input_files/bwb.xyz") xFraction = 0.25 meshScale = 1 elif geometry == "rae2822": ffdFile = os.path.join(self.base_path, "../../input_files/deform_geometry_ffd.xyz") xFraction = 0.25 DVGeo = DVGeometry(ffdFile, child=self.child) DVCon = DVConstraints() nRefAxPts = DVGeo.addRefAxis("wing", xFraction=xFraction, alignIndex="k") self.nTwist = nRefAxPts - 1 if self.child: parentFFD = os.path.join(self.base_path, "../../input_files/parent.xyz") self.parentDVGeo = DVGeometry(parentFFD) self.parentDVGeo.addChild(DVGeo) DVCon.setDVGeo(self.parentDVGeo) else: DVCon.setDVGeo(DVGeo) # Add design variables def twist(val, geo): for i in range(1, nRefAxPts): geo.rot_z["wing"].coef[i] = val[i - 1] DVGeo.addGlobalDV(dvName="twist", value=[0] * self.nTwist, func=twist, lower=-10, upper=10, scale=1) DVGeo.addLocalDV("local", lower=-0.5, upper=0.5, axis="y", scale=1) # RAE 2822 does not have a DVCon surface so we just return if geometry == "rae2822": return DVGeo, DVCon # Get the mesh from the STL testMesh = mesh.Mesh.from_file(meshFile) # dim 0 is triangle index # dim 1 is each vertex of the triangle # dim 2 is x, y, z dimension p0 = testMesh.vectors[:, 0, :] * meshScale v1 = testMesh.vectors[:, 1, :] * meshScale - p0 v2 = testMesh.vectors[:, 2, :] * meshScale - p0 DVCon.setSurface([p0, v1, v2], addToDVGeo=addToDVGeo) # Add the blob surface for the BWB if geometry == "bwb": objFile = os.path.join(self.base_path, "../../input_files/blob_bwb_wing.stl") testObj = mesh.Mesh.from_file(objFile) p0b = testObj.vectors[:, 0, :] v1b = testObj.vectors[:, 1, :] - p0b v2b = testObj.vectors[:, 2, :] - p0b if intersected: p0b = p0b + np.array([0.0, 0.3, 0.0]) DVCon.setSurface([p0b, v1b, v2b], name="blob") return DVGeo, DVCon
# Set the chord as well geo.scale["wing"].coef[-1] = val[3] coords = hyp.getSurfaceCoordinates() DVGeo = DVGeometry(ffdFile) coef = DVGeo.FFD.vols[0].coef.copy() # First determine the reference chord lengths: nSpan = coef.shape[2] ref = numpy.zeros((nSpan, 3)) for k in range(nSpan): max_x = numpy.max(coef[:, :, k, 0]) min_x = numpy.min(coef[:, :, k, 0]) ref[k, 0] = min_x + 0.25 * (max_x - min_x) ref[k, 1] = numpy.average(coef[:, :, k, 1]) ref[k, 2] = numpy.average(coef[:, :, k, 2]) c0 = Curve(X=ref, k=2) DVGeo.addRefAxis("wing", c0) DVGeo.addGlobalDV("winglet", [0, 0, 0, 1], winglet, lower=-5, upper=5) DVGeo.addPointSet(coords, "coords") DVGeo.setDesignVars({"winglet": [1.5, 2.5, -2.0, 0.60]}) hyp.setSurfaceCoordinates(DVGeo.update("coords")) # Run and write grid hyp.run() hyp.writeCGNS(volumeFile)
def test6(): # **************************************************************************** printHeader('MDO tutorial RANS Geometric Variables') # **************************************************************************** aeroOptions = copy.deepcopy(defOpts) # Now set the options that need to be overwritten for this example: aeroOptions.update( {'gridfile': '../inputFiles/mdo_tutorial_rans.cgns', 'mgcycle':'2w', 'equationtype':'RANS', 'smoother':'dadi', 'nsubiterturb':3, 'nsubiter':3, 'cfl':1.5, 'cflcoarse':1.25, 'ncyclescoarse':250, 'ncycles':750, 'monitorvariables':['resrho','resturb','cl','cd','cmz','yplus','totalr'], 'usenksolver':True, 'l2convergence':1e-17, 'l2convergencecoarse':1e-2, 'nkswitchtol':1e-4, 'adjointl2convergence': 1e-16, 'nkls': 'non monotone', 'frozenturbulence':False, 'nkjacobianlag':2, } ) # Setup aeroproblem, cfdsolver ap = AeroProblem(name='mdo_tutorial', alpha=1.8, mach=0.80, altitude=10000.0, areaRef=45.5, chordRef=3.25, evalFuncs=['cl','cmz','drag']) ap.addDV('alpha') ap.addDV('mach') CFDSolver = ADFLOW(options=aeroOptions) if 'complex' in sys.argv: DVGeo = DVGeometry('../inputFiles/mdo_tutorial_ffd.fmt', complex=True) else: DVGeo = DVGeometry('../inputFiles/mdo_tutorial_ffd.fmt', complex=False) nTwist = 2 DVGeo.addRefAxis('wing', pyspline.Curve(x=numpy.linspace(5.0/4.0, 1.5/4.0+7.5, nTwist), y=numpy.zeros(nTwist), z=numpy.linspace(0,14, nTwist), k=2)) def twist(val, geo): for i in xrange(nTwist): geo.rot_z['wing'].coef[i] = val[i] def span(val, geo): # Span C = geo.extractCoef('wing') s = geo.extractS('wing') for i in xrange(len(C)-1): C[-1, 2] = C[-1, 2] + val[0] geo.restoreCoef(C, 'wing') DVGeo.addGeoDVGlobal('twist', [0]*nTwist, twist, lower=-10, upper=10, scale=1.0) DVGeo.addGeoDVGlobal('span', [0], span, lower=-10, upper=10, scale=1.0) DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y', scale=10.0) mesh = MBMesh(options={'gridFile':'../inputFiles/mdo_tutorial_rans.cgns'}) CFDSolver.setMesh(mesh) CFDSolver.setDVGeo(DVGeo) #Aeroproblem must be set before we can call DVGeo.setDesignVars CFDSolver.setAeroProblem(ap) if not 'complex' in sys.argv: # Solve system CFDSolver(ap, writeSolution=False) funcs = {} CFDSolver.evalFunctions(ap, funcs) # Solve sensitivities funcsSens = {} CFDSolver.evalFunctionsSens(ap, funcsSens) # Write values and derivatives out: if MPI.COMM_WORLD.rank == 0: for key in ['cl','cmz','drag']: print 'funcs[%s]:'%key reg_write(funcs['mdo_tutorial_%s'%key],1e-10,1e-10) # Now write the derivatives in the same order the CS will do them: print ('Twist[0] Derivatives:') reg_write(funcsSens['mdo_tutorial_cl']['twist'][0][0], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_cmz']['twist'][0][0], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_drag']['twist'][0][0], 1e-10,1e-10) print ('Span Derivatives:') reg_write(funcsSens['mdo_tutorial_cl']['span'][0], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_cmz']['span'][0], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_drag']['span'][0], 1e-10,1e-10) print ('shape[13] Derivatives:') reg_write(funcsSens['mdo_tutorial_cl']['shape'][0][13], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_cmz']['shape'][0][13], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_drag']['shape'][0][13], 1e-10,1e-10) print ('mach Derivatives:') reg_write(funcsSens['mdo_tutorial_cl']['mach_mdo_tutorial'], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_cmz']['mach_mdo_tutorial'], 1e-10,1e-10) reg_write(funcsSens['mdo_tutorial_drag']['mach_mdo_tutorial'], 1e-10,1e-10) else: # For the complex....we just do successive perturbation for ii in range(4): xRef = {'twist':[0.0, 0.0], 'span':[0.0], 'shape':numpy.zeros(72, dtype='D'), 'mach_mdo_tutorial':0.8} if ii == 0: xRef['twist'][0] += h*1j elif ii == 1: xRef['span'][0] += h*1j elif ii == 2: xRef['shape'][13] += h*1j else: xRef['mach_mdo_tutorial']+=h*1j ap.setDesignVars(xRef) CFDSolver.resetFlow(ap) DVGeo.setDesignVars(xRef) CFDSolver(ap, writeSolution=False) funcs = {} CFDSolver.evalFunctions(ap, funcs) if MPI.COMM_WORLD.rank == 0: if ii == 0: for key in ['cl','cmz','drag']: print 'funcs[%s]:'%key reg_write(numpy.real(funcs['mdo_tutorial_%s'%key]),1e-10,1e-10) if ii == 0: print ('Twist[0] Derivatives:') elif ii == 1: print ('Span Derivatives:') elif ii == 2: print ('shape[13] Derivatives:') elif ii == 3: print ('mach Derivatives:') for key in ['cl','cmz','drag']: deriv = numpy.imag(funcs['mdo_tutorial_%s'%key])/h reg_write(deriv,1e-10,1e-10) del CFDSolver del mesh