Пример #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
class TestAdjoint(reg_test_classes.RegTest):
    """
    Tests that sensitives calculated from solving an adjoint are correct.
    and jacobian vector products are accurate.

    based on old regression tests 12, and 14
    """

    N_PROCS = 2

    options = None
    ap = None
    ref_file = None

    def setUp(self):
        if not hasattr(self, "name"):
            # return immediately when the setup method is being called on the based class and NOT the
            # classes created using parametrized
            # this will happen when training, but will hopefully be fixed down the line
            return

        super().setUp()

        options = copy.copy(adflowDefOpts)
        options["outputdirectory"] = os.path.join(baseDir, options["outputdirectory"])
        options.update(self.options)

        self.ffdFile = os.path.join(baseDir, "../../input_files/mdo_tutorial_ffd.fmt")

        mesh_options = copy.copy(IDWarpDefOpts)
        mesh_options.update({"gridFile": options["gridfile"]})

        self.ap = copy.deepcopy(self.aero_prob)

        # Setup aeroproblem
        self.ap.evalFuncs = self.evalFuncs

        # add the default dvs to the problem
        for dv in defaultAeroDVs:
            self.ap.addDV(dv)

        self.CFDSolver = ADFLOW(options=options, debug=True)

        self.CFDSolver.setMesh(USMesh(options=mesh_options))
        self.CFDSolver.setDVGeo(setDVGeo(self.ffdFile, cmplx=False))

        # propagates the values from the restart file throughout the code
        self.CFDSolver.getResidual(self.ap)

    def test_residuals(self):
        utils.assert_residuals_allclose(self.handler, self.CFDSolver, self.ap, tol=1e-10)

    def test_adjoint(self):
        utils.assert_adjoint_sens_allclose(self.handler, self.CFDSolver, self.ap, tol=1e-10)
        self.assert_adjoint_failure()
Пример #3
0
# rst dvconLeTe (beg)
# Le/Te constraints
DVCon.addLeTeConstraints(0, "iLow")
DVCon.addLeTeConstraints(0, "iHigh")

if comm.rank == 0:
    # Only make one processor do this
    DVCon.writeTecplot(os.path.join(args.output, "constraints.dat"))
# rst dvconLeTe (end)
# ======================================================================
#         Mesh Warping Set-up
# ======================================================================
# rst warp (beg)
meshOptions = {"gridFile": args.gridFile}
mesh = USMesh(options=meshOptions, comm=comm)
CFDSolver.setMesh(mesh)


# rst warp (end)
# ======================================================================
#         Functions:
# ======================================================================
# rst funcs (beg)
def cruiseFuncs(x):
    if comm.rank == 0:
        print(x)
    # Set design vars
    DVGeo.setDesignVars(x)
    ap.setDesignVars(x)
    # Run CFD
    CFDSolver(ap)
class TestSolve(reg_test_classes.RegTest):
    """
    Tests for time spectral case for an airfoil.
    """

    N_PROCS = 2
    ref_file = "solve_euler_time_spectral_naca64A010.json"

    def setUp(self):

        # Introduce a transfer class for displacement transfer from struct to aero.
        class Transfer:

            # simplified transfer class
            # converting csd displacement to cfd surface nodes

            def __init__(self, alpha, xRot, aeroSolver):

                # takes in displacement history

                self.alpha = alpha
                self.ntimeintervalsspectral = len(alpha)

                self.aeroSolver = aeroSolver  # a shallow copy of CFD solver

                self.xRot = xRot

            def getUndeformedSurfaceNodes(self):

                self.MDGroup = self.aeroSolver.allWallsGroup

                self.cfdPts0 = self.aeroSolver.getSurfaceCoordinates(self.MDGroup, includeZipper=False)

            def setDisplacements(self):

                xRot = self.xRot
                ntimeintervalsspectral = self.ntimeintervalsspectral
                alpha = self.alpha  # notice a shallow copy introduced here; dont change the underlying obj!
                cfdPoints_init = self.cfdPts0  # notice a shallow copy introduced here; dont change the underlying obj!

                N_pts = cfdPoints_init.shape[0]

                self.cfdPts = []

                for sps in range(ntimeintervalsspectral):

                    cfdPoints_deformed = numpy.zeros((N_pts, 3))

                    ptch_loc = alpha[sps]

                    cc = numpy.cos(ptch_loc)
                    ss = numpy.sin(ptch_loc)

                    for j in range(N_pts):

                        cfdPoints_deformed[j, 0] = cc * (cfdPoints_init[j, 0] - xRot) + ss * cfdPoints_init[j, 1] + xRot
                        cfdPoints_deformed[j, 1] = -ss * (cfdPoints_init[j, 0] - xRot) + cc * cfdPoints_init[j, 1]
                        cfdPoints_deformed[j, 2] = cfdPoints_init[j, 2]

                    self.cfdPts.append(cfdPoints_deformed)

            def setVolumeMesh(self):

                ntimeintervalsspectral = self.ntimeintervalsspectral

                for sps in range(ntimeintervalsspectral):

                    self.aeroSolver.mesh.setSurfaceCoordinates(self.cfdPts[sps])
                    self.aeroSolver.mesh.warpMesh()
                    m = self.aeroSolver.mesh.getSolverGrid()
                    self.aeroSolver.adflow.warping.setgridforoneinstance(m, sps=sps + 1)

                self.aeroSolver._updateGeomInfo = True
                self.aeroSolver.updateGeometryInfo()

        # Set up the test for the parent RegTest class.
        super().setUp()

        gridFile = os.path.join(baseDir, "../../input_files/naca64A010_euler-L2.cgns")

        ntimeintervalsspectral = 3
        options = copy.copy(adflowDefOpts)
        options.update(
            {
                "gridfile": gridFile,
                "outputDirectory": os.path.join(baseDir, "../output_files"),
                "writeVolumeSolution": False,
                "writeSurfaceSolution": False,
                "blocksplitting": True,
                "useblockettes": False,
                "equationtype": "Euler",
                "equationmode": "time spectral",
                "mgcycle": "sg",
                "l2convergence": 1e-15,
                "ncycles": 200000,
                "monitorvariables": ["resrho", "cl"],
                "usenksolver": True,
                "nkswitchtol": 1e-4,
                "NKSubSpaceSize": 400,
                "applypcsubspacesize": 400,
                "useanksolver": True,
                "ankswitchtol": 1e-2,
                "anksubspacesize": 50,
                "alphafollowing": False,
                "timeintervals": ntimeintervalsspectral,
                "useexternaldynamicmesh": True,
                "usetsinterpolatedgridvelocity": True,
            }
        )

        # Grid option
        meshOptions = {
            "gridFile": gridFile,
        }

        # Setup aeroproblem
        self.ap = copy.copy(ap_naca64A010_time_spectral)

        # Motion history
        alpha_0 = 1.01
        deltaAlpha = -alpha_0 * numpy.pi / 180.0
        alpha = numpy.linspace(0.0, 2.0 * numpy.pi, ntimeintervalsspectral + 1)[:-1]
        alpha = -numpy.sin(alpha)
        alpha *= deltaAlpha

        # Create the solver
        self.CFDSolver = ADFLOW(options=options, debug=False)
        # self.CFDSolver.addSlices("z", [0.5])

        # Deform the mesh
        mesh = USMesh(options=meshOptions)
        self.CFDSolver.setMesh(mesh)

        # deformation
        xRot = 0.25  # Hard copied from the reference file.
        TSTransfer = Transfer(alpha, xRot, self.CFDSolver)
        TSTransfer.getUndeformedSurfaceNodes()
        TSTransfer.setDisplacements()
        TSTransfer.setVolumeMesh()

    def test_solve(self):

        # do the solve
        self.CFDSolver(self.ap)

        # check if the solution failed
        self.assert_solution_failure()

        # check its accuracy
        utils.assert_functions_allclose(self.handler, self.CFDSolver, self.ap, tol=1e-8)
Пример #5
0
class PlateComponent(om.ExplicitComponent):
    """Deterministic Bump Flow Problem"""
    def initialize(self):
        # Need to modify this dictionary when we change the SA constants
        sys.stdout = open(os.devnull, "w")
        self.aoptions = aeroOptions
        self.woptions = warpOptions
        self.ooptions = optOptions

        # Generate FFD and DVs
        self.DVGeo = pf.createFFD()

        # starting flat mesh
        meshname = self.aoptions['gridFile']
        gridFile = meshname
        
        # flow characteristics
        alpha = 0.0
        mach = self.ooptions['mach']#0.95
        Re = self.ooptions['Re']#50000
        Re_L = 1.0
        temp = 540
        arearef = 2.0
        chordref = 1.0

        # Spalart Allmaras model constants, to be changed in UQ
        saconstsm = [0.41, 0.1355, 0.622, 0.66666666667, 7.1, 0.3, 2.0]
        self.saconsts = saconstsm + [1.0, 2.0, 1.2, 0.5, 2.0]
        self.aoptions['SAConsts'] = self.saconsts
        #self.gridSol = f'{meshname}_{saconstsm}_sol'
        solname = self.ooptions['prob_name']
        self.gridSol = f'{solname}_sol'

        # Aerodynamic problem description
        self.ap = AeroProblem(name=self.gridSol, alpha=alpha, mach=mach, reynolds=Re, reynoldsLength=Re_L, T=temp, areaRef=arearef, chordRef=chordref, 
        evalFuncs=['cd'])

        # Create solver
        self.CFDSolver = ADFLOW(options=self.aoptions, comm=MPI.COMM_WORLD)
        self.CFDSolver.setDVGeo(self.DVGeo)

        # Set up mesh warping
        self.mesh = USMesh(options=self.woptions, comm=MPI.COMM_WORLD)
        self.CFDSolver.setMesh(self.mesh)

        # Try setting the DVGeo coordinates here
        coords = self.CFDSolver.getSurfaceCoordinates(groupName=self.CFDSolver.allWallsGroup)
        self.CFDSolver.DVGeo.addPointSet(coords, 'coords')
        self.CFDSolver.DVGeo.getFlattenedChildren()[1].writePlot3d("ffdp_opt_def.xyz")


        # Set constraints
        self.DVCon = DVConstraints()
        self.DVCon2 = DVConstraints()
        self.DVCon.setDVGeo(self.CFDSolver.DVGeo.getFlattenedChildren()[1])
        self.DVCon2.setDVGeo(self.CFDSolver.DVGeo)

        self.DVCon.setSurface(self.CFDSolver.getTriangulatedMeshSurface(groupName='allSurfaces'))
        # set extra group for surface area condition
        self.DVCon2.setSurface(self.CFDSolver.getTriangulatedMeshSurface(), name='wall')

        # DV should be same into page (not doing anything right now)
        #import pdb; pdb.set_trace()
        lIndex = self.CFDSolver.DVGeo.getFlattenedChildren()[1].getLocalIndex(0)
        indSetA = []
        indSetB = []
        nXc = optOptions['NX']
        self.NC = math.trunc(((1.0 - self.ooptions['DVFraction'])*self.ooptions['NX']))
        ind = [int(nXc/2) - int(self.NC/2), int(nXc/2) + int(self.NC/2)]
        for i in range(ind[0], ind[1]):
            indSetA.append(lIndex[i, 0, 1])
            indSetB.append(lIndex[i, 1, 1])
        # for i in range(lIndex.shape[0]):
        #     indSetA.append(lIndex[i, 0, 1])
        #     indSetB.append(lIndex[i, 1, 1])
        self.DVCon.addLinearConstraintsShape(indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0, name='eqs')

        # Thickness constraints (one for each active DV)
        #import pdb; pdb.set_trace()

        # Maximum thickness of the domain, translates to minimum thickness of bump
        ub = 1.0 - self.ooptions['DCMinThick']
        tcf = self.ooptions['DCThickFrac']
        ra = self.ooptions['bumpBounds']
        lim = self.ooptions['DCMinArea']
        span = numpy.linspace(0, 1, nXc)
        xc = span * (ra[1] - ra[0]) + ra[0]
        #ind = range(int(nXc/2) - int(self.NC/2), int(nXc/2) + int(self.NC/2)))
        ind = [int(nXc/2) - int(tcf*self.NC/2), int(nXc/2) + int(tcf*self.NC/2)]
        ptList = numpy.zeros([2, 3])
        ptList[:,0] = xc[ind]
        ptList[:,1] = 0.5
        ptList[:,2] = 0.5

        if self.ooptions['use_area_con']:
            self.DVCon2.addSurfaceAreaConstraint(lower=lim, upper=10., name='sas', surfaceName='wall')
        else:
            self.DVCon2.addThicknessConstraints1D(ptList, self.NC, [0,0,1], lower=0.5, upper=ub, name='tcs')

        sys.stdout = sys.__stdout__

    def setup(self):
        #initialize shape and set deformation points as inputs
        a_init = self.CFDSolver.DVGeo.getValues()
        a_init['pnts'][:] = self.ooptions['DVInit']
        # mult = numpy.linspace(1.0,1.5,num=int(0.5*len(a_init['pnts'])))
        # mult = numpy.concatenate((mult, mult))
        # a_init['pnts'] = numpy.multiply(mult, a_init['pnts'])
        #if self.ooptions['run_once']:
        #    a_init['pnts'] = self.ooptions['ro_shape']
        self.add_input('a', a_init['pnts'], desc="Bump Shape Control Points")
        #self.add_input('a', 0.2, desc="Bump Shape Control Points")

        if self.ooptions['use_area_con']:
            self.add_output('SA', 1.0, desc='Surface Area Constraint')
        else:
            self.add_output('TC', numpy.zeros(self.NC), desc='Thickness Constraints')
        self.add_output('Cd', 0.0, desc="Drag Coefficient")
        self.add_output('EQ', numpy.zeros(int(len(a_init['pnts'])/2)), desc="Control Point Symmetry")


    
    def setup_partials(self):
        self.declare_partials('Cd','a', method='exact')
        if self.ooptions['use_area_con']:
            self.declare_partials('SA','a', method='exact')
        else:
            self.declare_partials('TC','a', method='exact')
        self.declare_partials('EQ','a', method='exact')
    
    def compute(self, inputs, outputs):
        # run the bump shape model

        # move the mesh
        #import pdb; pdb.set_trace()
        dvdict = {'pnts':inputs['a']}
        self.CFDSolver.DVGeo.setDesignVars(dvdict)
        self.ap.setDesignVars(dvdict)

        #self.CFDSolver.DVGeo.update("coords")

        # Solve and evaluate functions
        funcs = {}
        self.CFDSolver(self.ap)
        self.DVCon.evalFunctions(funcs, includeLinear=True)
        self.DVCon2.evalFunctions(funcs, includeLinear=True)
        self.CFDSolver.evalFunctions(self.ap, funcs)

        str = self.gridSol + '_cd'
        outputs['Cd'] = funcs[str]
        if self.ooptions['use_area_con']:
            outputs['SA'] = funcs['sas']
        else:
            outputs['TC'] = funcs['tcs']
        
        outputs['EQ'] = funcs['eqs']

        #outputs['Cd'] = inputs['a']*inputs['a']

    def compute_partials(self, inputs, J):

        # move the mesh
        #import pdb; pdb.set_trace()
        dvdict = {'pnts':inputs['a']}
        self.CFDSolver.DVGeo.setDesignVars(dvdict)
        self.ap.setDesignVars(dvdict)
        #self.CFDSolver.DVGeo.update("coords")
 
 
        funcSens = {}
        #self.CFDSolver(self.ap) #ASSUME WE ALREADY COMPUTED THE SOLUTION
        self.DVCon.evalFunctionsSens(funcSens, includeLinear=True)
        self.DVCon2.evalFunctionsSens(funcSens, includeLinear=True)
        self.CFDSolver.evalFunctionsSens(self.ap, funcSens, ['cd'])
 
        str = self.gridSol + '_cd'
        J['Cd','a'] = funcSens[str]['pnts']
        if self.ooptions['use_area_con']:
            J['SA','a'] = funcSens['sas']['pnts']
        else:
            J['TC','a'] = funcSens['tcs']['pnts']
        J['EQ','a'] = funcSens['eqs']['pnts']