Example #1
0
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
Example #2
0
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
Example #3
0
    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
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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)
Example #7
0
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
Example #8
0
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
Example #9
0
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)
Example #10
0
    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
Example #11
0
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
Example #12
0
                 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)
Example #14
0
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')
Example #15
0
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")
Example #16
0
#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])
Example #17
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)
Example #18
0
    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)
Example #19
0
        # 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')
Example #20
0
    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)
Example #21
0
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'
Example #23
0
    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
Example #24
0
        # 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)
Example #25
0
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