Пример #1
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
Пример #2
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
Пример #3
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):
        # Span
        C = geo.extractCoef("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)
    DVGeo.addGeoDVLocal("shape", lower=-0.5, upper=0.5, axis="y", scale=10.0)

    return DVGeo
Пример #4
0
    def test_13b(self, train=False, refDeriv=False):
        refFile = os.path.join(self.base_path,'ref/test_DVConstraints_13b.ref')
        with BaseRegTest(refFile, train=train) as handler:
            handler.root_print("Test 13: PlanarityConstraint, rectangular box")
            ffdfile = os.path.join(self.base_path, '../inputFiles/2x1x8_rectangle.xyz')
            DVGeo = DVGeometry(ffdfile)
            DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1)

            # create a DVConstraints object with a simple plane consisting of 2 triangles
            DVCon =DVConstraints()
            DVCon.setDVGeo(DVGeo)

            p0 = np.zeros(shape=(2,3))
            p1 = np.zeros(shape=(2,3))
            p2 = np.zeros(shape=(2,3))

            vertex1 = np.array([0.5, -0.25, 0.0])
            vertex2 = np.array([0.5, -0.25, 4.0])
            vertex3 = np.array([-0.5, -0.25, 0.0])
            vertex4 = np.array([-0.5, -0.25, 4.0])

            p0[:,:] = vertex1
            p2[:,:] = vertex4
            p1[0,:] = vertex2
            p1[1,:] = vertex3

            v1 = p1 - p0
            v2 = p2 - p0
            DVCon.setSurface([p0, v1, v2])

            DVCon.addPlanarityConstraint(origin=[0.,-0.25,2.0], planeAxis=[0.,1.,0.])

            funcs, funcsSens = self.generic_test_base(DVGeo, DVCon, handler, checkDerivs=False)

            # this should be coplanar and the planarity constraint shoudl be zero
            handler.assert_allclose(funcs['DVCon1_planarity_constraints_0'], np.zeros(1), 
                                    name='planarity', rtol=1e-7, atol=1e-7)
Пример #5
0
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.addGeoDVGlobal(dvName="twist", value=[0] * nTwist, func=twist, lower=-10, upper=10, scale=0.01)

# Set up local design variables
DVGeo.addGeoDVLocal("local", lower=-0.5, upper=0.5, axis="y", scale=1)

# Add DVGeo object to CFD solver
CFDSolver.setDVGeo(DVGeo)
# rst dvgeo (end)
# ======================================================================
#         DVConstraint Setup, and Thickness and Volume Constraints
# ======================================================================
# rst dvconVolThick (beg)
DVCon = DVConstraints()
DVCon.setDVGeo(DVGeo)

# Only ADflow has the getTriangulatedSurface Function
DVCon.setSurface(CFDSolver.getTriangulatedMeshSurface())

# Volume constraints
Пример #6
0
                                        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)
DVGeo.addGeoDVLocal('shape', lower=-0.5, upper=0.5, axis='y', scale=10.0)
mesh = MBMesh(options={'gridFile':'../inputFiles/mdo_tutorial_euler.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:
Пример #7
0
        chordRef=1.0,
        evalFuncs=["cl", "cd"],
    )
    # Add angle of attack variable
    ap.addDV("alpha", value=alpha[i], lower=0, upper=10.0, scale=1.0)
    aeroProblems.append(ap)
# rst aeroproblem (end)
# ======================================================================
#         Geometric Design Variable Set-up
# ======================================================================
# rst dvgeo (beg)
# Create DVGeometry object
FFDFile = "ffd.xyz"

DVGeo = DVGeometry(FFDFile)  # DVGeo = DVGeometry_FFD(FFDFile)
DVGeo.addGeoDVLocal("shape", lower=-0.05, upper=0.05, axis="y", scale=1.0)

span = 1.0
pos = np.array([0.5]) * span
CFDSolver.addSlices("z", pos, sliceType="absolute")

# Add DVGeo object to CFD solver
CFDSolver.setDVGeo(DVGeo)
# rst dvgeo (end)
# ======================================================================
#         DVConstraint Setup
# ======================================================================
# rst dvcon (beg)
DVCon = DVConstraints()  # DVCon = DVConstraints_FFD_data()
DVCon.setDVGeo(DVGeo)
Пример #8
0
DVGeo.addGeoDVGlobal(dvName='twist',
                     value=[0] * nTwist,
                     func=twist,
                     lower=-10,
                     upper=10,
                     scale=1)
DVGeo.addGeoDVGlobal(dvName='taper',
                     value=[1] * 2,
                     func=taper,
                     lower=0.5,
                     upper=1.5,
                     scale=1)

#rst Add local dvs
# Comment out one or the other
DVGeo.addGeoDVLocal('local', lower=-0.5, upper=0.5, axis='y', scale=1)
DVGeo.addGeoDVSectionLocal('slocal',
                           secIndex='k',
                           axis=1,
                           lower=-0.5,
                           upper=0.5,
                           scale=1)

#rst Embed points
gridFile = 'wing_vol.cgns'
meshOptions = {'gridFile': gridFile}
mesh = USMesh(options=meshOptions)
coords = mesh.getSurfaceCoordinates()

DVGeo.addPointSet(coords, 'coords')
Пример #9
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)
Пример #10
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')
Пример #11
0
                           func=twist_front,
                           lower=-10,
                           upper=10,
                           scale=0.01)

DVGeo_back.addGeoDVGlobal(dvName='twist_back',
                          value=[0] * nTwist_back,
                          func=twist_back,
                          lower=-10,
                          upper=10,
                          scale=0.01)

# Set up local design variables
DVGeo_front.addGeoDVLocal('local_front',
                          lower=-0.05,
                          upper=0.05,
                          axis='y',
                          scale=10)

DVGeo_back.addGeoDVLocal('local_back',
                         lower=-0.05,
                         upper=0.05,
                         axis='y',
                         scale=10)

# Add DVGeo object to CFD solver
CFDSolver.setDVGeo(DVGeo_GLOBAL)

#rst dvs

DVCon = DVConstraints(name='con')
Пример #12
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