示例#1
0
    def get_moments(self, Cp):
        pInf = self.pInf
        qInf = self.qInf
        momentCenter = array([self.xref, 0., 0.])
        sumMoments = array([0., 0., 0.])
        sumForces = array([0., 0., 0.])

        for (key, cp) in self.Cps.items():  # centroidal based Cp
            area = self.areas[key]
            centroid = self.centroids[key]
            normal = self.normals[key]
            p = cp * qInf + pInf
            F = area * normal * p  # negative sign is b/c the normals are flipped...
            r = momentCenter - centroid

            sumForces += F
            sumMoments += cross(r, F)
            #break
        log.info("pInf=%s [psi]; qInf= %s [psi]" % (pInf, qInf))

        log.info("sumForcesCFD  [lb]    = %s" % ListPrint(sumForces))
        log.info("sumMomentsCFD [ft-lb] = %s" % ListPrint(sumMoments / 12.))
        Cf = sumForces / (self.Sref * qInf)
        Cm = sumMoments / (self.Sref * qInf * self.Lref) * 12.
        log.info("Cf = %s" % ListPrint(Cf))
        log.info("Cm = %s" % ListPrint(Cm))
        return (sumForces, sumMoments / 12.)
示例#2
0
    def mapDeflection(self, A, d1, d2, d3, d4, i, aeroNode, dType='x'):
        """
        see mapDeflections...
        based on the posiition matrix, finds the ith deflection component

        Then we ratios the new deflection diMax and compares it to the nearby points to 'test'.
        """
        di = array([d1[i], d2[i], d3[i], d4[i]])
        diMax = max(abs(di))  # L1 norm
        log.info("d%s = %s" % (dType, ListPrint(di)))

        abcd = solve(A, di)

        #ui = abcd*aeroNode # element-wise multiplication...faster, cant make it work; tried dot & transpose too...
        (a, b, c, d) = abcd
        ui = a + b * aeroNode[0] + c * aeroNode[1] + d * aeroNode[2]
        isRanged = is_list_ranged(0., abcd, 1.)
        log.info('isRanged=%s  u%sRatio=%g - a=%g b=%g c=%g d=%g' %
                 (isRanged, dType, abs(ui / diMax), a, b, c, d))
        return ui
示例#3
0
    def poor_mans_mapping(self, aCentroid, aEID, pSource, normal):
        """
        distributes load without piercing elements
        based on distance
        """
        (sElements, sDists) = self.centroidTree.getCloseElementIDs(aCentroid)
        log.debug("aCentroid = %s" % aCentroid)
        log.debug("sElements = %s" % sElements)
        log.debug("sDists    = %s" % ListPrint(sDists))

        setNodes = set([])
        sModel = self.structuralModel
        for sEID in sElements:
            sNodes = sModel.get_element_nodes(sEID)
            setNodes.union(set(sNodes))

        nIDs = list(setNodes)
        sNodes = sModel.getNodeIDLocations(nIDs)
        weights = self.get_weights(closePoint, sNodes)
        distribution = self.create_distribution(nIDs, weights)
        return distribution
示例#4
0
    def mapLoads(self):
        """
        Loops thru the unitLoad mappingMatrix and multiplies by the
        total force F on each panel to calculate the PLOAD that will be
        printed to the output file.
        Also, performs a sum of Forces & Moments to verify the aero loads.
        """
        log.info("---starting mapLoads---")
        self.bdf = open(self.bdffile, 'wb')
        #self.buildMappingMatrix()
        log.info("self.loadCase = %s" % self.loadCase)
        self.loadCases = {self.loadCase:{}}

        #self.loadCases = {self.loadCase={}, }
        momentCenter = array([self.xref, 0., 0.])
        sumMoments = array([0., 0., 0.])
        sumForces  = array([0., 0., 0.])
        sys.stdout.flush()
        for aEID, distribution in iteritems(self.mappingMatrix):
            #print "aEID = ",aEID
            #print "***distribution = ", distribution
            sumLoad = 0.
            area   = self.aeroModel.Area(aEID)
            normal = self.aeroModel.Normal(aEID)
            Cp     = self.aeroModel.Cp(aEID)
            #print "Cp = ",Cp
            #print "area[%s]=%s" % (aEID, area)

            p = self.getPressure(Cp)
            centroid = self.aeroModel.Centroid(aEID)
            r = momentCenter - centroid
            F = area * p
            Fn = F * normal
            sumMoments += cross(r, Fn)
            sumForces  += Fn
            for sNID, percentLoad in sorted(iteritems(distribution)):
                sumLoad += percentLoad

                Fxyz = Fn * percentLoad  # negative sign is to be consistent with nastran
                self.addForce(sNID, Fxyz)

                #print("Fxyz = ",Fxyz)
                #print("type(structuralModel) = ", type(self.structuralModel))

                #comment = 'percentLoad=%.2f' % percentLoad
                #self.structuralModel.writeLoad(self.bdf, self.loadCase, sNID,
                #                               Fxyz[0], Fxyz[1], Fxyz[2], comment)

            #msg = '$ End of aEID=%s sumLoad=%s p=%s area=%s F=%s normal=%s\n' % (aEID, sumLoad, p, area, F, normal)
            #self.bdf.write(msg)

        self.writeLoads()  # short version of writing loads...
        self.bdf.close()

        log.info("pInf=%g [psi]; qInf= %g [psi]" % (self.pInf, self.qInf))
        log.info("sumForcesFEM  [lb]    = %s" % ListPrint(sumForces))
        log.info("sumMomentsFEM [lb-ft] = %s" % ListPrint(sumMoments/12.))  # divided by 12 to have moments in lb-ft

        Cf = sumForces /(self.Sref * self.qInf)
        log.info("Cf = %s" % ListPrint(Cf))

        Cm = sumMoments / (self.Sref * self.qInf * self.Lref)
        log.info("Cm = %s" % ListPrint(Cm*12.)) # multiply by 12 to nondimensionalize ???  maybe 144...

        #self.bdf.write('$***********\n')
        log.info("wrote loads to %r" % self.bdffile)
        log.info("---finished mapLoads---")
示例#5
0
    def distribute_unit_load(self, aEID, piercedElements, nPiercings):
        """
        distribute unit loads to nearby nodes
        piercedElements is a list of piercings
        piercing = [sEID,P,u,v] or [sEID]
        where
          sEID - the structural element ID
          P    - point p was pierced
          u    - u coordinate
          v    - v coordinate
        if nPiercings==0, all the nearby nodes will recieve load
        """
        aModel = self.aeroModel
        sModel = self.structuralModel
        #print("piercedElements = ", piercedElements)
        nIDs = []
        if nPiercings == 0:
            #assert len(nPiercings)==1,'fix me...'
            #print("nPiercings=0 distributing load to closest nodes...u=%g v=%g" %(-1,-1))
            log.debug("nPiercings=0 distributing load to closest nodes...")
            for sEID in piercedElements:
                nIDs += sModel.get_element_node_ids(sEID)
            #print "nIDs1 = ",nIDs
            nIDs = list(set(nIDs))
            log.debug("nIDs2 = %s" % nIDs)
            aCentroid = aModel.Centroid(aEID)
            nodes = sModel.getNodeIDLocations(nIDs)

            #print "nodes = ", nodes
            weights = self.get_weights(aCentroid, nodes)
            distribution = self.create_distribution(nIDs, weights)

            log.debug("element aEID=%s sEID=%s weights=%s" % (aEID, sEID, ListPrint(weights)))
            #print("distribution = ", distribution)
            #print("nIDs         = ", nIDs)
            #print("weights      = ", weights)
            #print("nodes = ", nodes)
            #print("nPiercings = ", nPiercings)
        else:
            log.info("mapping load to actual element...")
            nClose = 3  # number of elements to map to
            closeElements = piercedElements[:nClose]

            setCloseNodes = set([])
            for closeElement in reversed(closeElements):
                log.info("closeElement = %s" % closeElement)
                #sEID, pIntersect, u1, v1, sDist
                (sEID, P, u, v, sDist) = closeElement  # TODO:  bug here...???

                #closePoint = closeElement[1]
                #closeElement = sEID
                closePoint = P

                # get list of nearby structural nodes
                setElementNodes = set(sModel.get_element_node_ids(sEID))
                setCloseNodes = setCloseNodes.union(setElementNodes)

            # setup for weighted average
            nIDs = list(setCloseNodes)
            sNodes = sModel.getNodeIDLocations(nIDs)
            weights = self.get_weights(closePoint, sNodes)
            distribution = self.create_distribution(nIDs, weights)

            log.info("element aEID=%s sEID=%s weights=%s" %(aEID, sEID, ListPrint(weights)))
        log.info("-------------------------\n")
        sys.stdout.flush()
        return (distribution)
示例#6
0
    def pierce_elements(self, aCentroid, aEID, pSource, normal):
        """
        Pierces *1* element with a ray casted from the centroid/pSource
        in the direction of the normal vector of an aerodynamic triangle

         A  1
          \/ \
          / * \
         2---\-3
               \
                B

        *P = A+(B-A)*t
        """
        #direction = -1. # TODO: direction of normal...?
        (sElements, sDists) = self.centroidTree.getCloseElementIDs(aCentroid)
        log.info("aCentroid = %s" % aCentroid)
        log.info("sElements = %s" % sElements)
        log.info("sDists    = %s" % ListPrint(sDists))
        #(nearbySElements, nearbyDistances) = sElements
        piercedElements = []

        for sEID, sDist in zip(sElements, sDists):
            #print "aEID=%s sEID=%s" % (aEID, sEID)
            (sArea, sNormal, sCentroid) = self.structuralModel.get_element_properties(sEID)
            sNodes = self.structuralModel.get_element_nodes(sEID)
            nNodes = len(sNodes)

            pEnd = pSource + normal * 10.
            #pEnd2 = pSource - normal * 10.
            if nNodes == 3:  # TODO:  is this enough of a breakdown?
                (sA, sB, sC) = sNodes
                #pEnd = pSource+normal*10.
                tuv  = pierce_plane_vector(sA, sB, sC, pSource, pEnd, piercedElements)
                #tuv2= pierce_plane_vector(sA, sB, sC, pSource, pEnd2, piercedElements)
            elif nNodes == 4:
                (sA, sB, sC, sD) = sNodes
                tuv  = pierce_plane_vector(sA, sB, sC, pSource, pEnd,  piercedElements)
                #tuv2= pierce_plane_vector(sA, sB, sC, pSource, pEnd2, piercedElements)
                #self.pierceTriangle(sA, sB, sC, sCentroid, sNormal, piercedElements)
                #self.pierceTriangle(sA, sC, sD, sCentroid, sNormal, piercedElements)
            else:
                raise RuntimeError('invalid element; nNodes=%s' % nNodes)

            t1, u1, v1 = tuv
            #t2, u2, v2 = tuv2

            isInside = False
            #if self.isInside(u1, v1) or self.isInside(u2, v2):
            if self.is_inside(u1, v1):
                isInside = True
                #pIntersect = pSource + (pEnd - pSource) * t1
                pIntersect = pEnd * t1 +pSource * (1 - t1)
                #P = A + (B - A) * t
                tuv  = pierce_plane_vector(sA, sB, sC, pSource, pIntersect, piercedElements)
                #print "t,u,v=", tuv

                piercedElements.append([sEID, pIntersect, u1, v1, sDist])

            #t = min(t1, t2)
            #print "t1=%6.3g t2=%6.3g" % (t1, t2)
            #if isInside:
                #print "*t[%s]=%6.3g u1=%6.3g v1=%6.3g u2=%6.3g v2=%6.3g" %(sEID,t,u1,v1,u2,v2)
            #else:
                #print " t[%s]=%6.3g u1=%6.3g v1=%6.3g u2=%6.3g v2=%6.3g" %(sEID,t,u1,v1,u2,v2)

            #if isInside:
                #print "*t[%s]=%6.3g u1=%6.3g v1=%6.3g d=%g" %(sEID,t1,u1,v1,sDist)
            #else:
                #print " t[%s]=%6.3g u1=%6.3g v1=%6.3g d=%g" %(sEID,t1,u1,v1,sDist)

        log.info("avgDist = %g" % mean(sDists))
        (piercedElements, nPiercings) = self.fix_piercings(sElements, piercedElements)
        distribution = self.distribute_unit_load(aEID, piercedElements, nPiercings)

        return (distribution)
示例#7
0
    def find_closest_tet(self, m, closestTet=None):
        """
        Finds the closest tet.  Has the potential to fail, but until then, skipping.
        Solution to failure:  brute force method.
        m = aeroNode
        tets =
        """
        if closestTet == None:
            closestTet = tets[1]

        tets = self.tets
        #startingTet = tets[1]
        #closestTet = self.findClosestTet_recursion(m,startingTet,tets)
        #print "found tet = ",closestTet.ID
        #v1 = array([1.,0.,0.])

        #tet,tetID = self.bruteForce(m,tets)
        #return tet
        log.info("starting tet = %s" % (closestTet))
        tetID = closestTet.ID
        excluded = []
        log.info("working on point = %s" % (ListPrint(m)))
        counter = 0
        counterMax = 100
        broken = False

        isInternal, localVol = closestTet.is_internal_node(m)
        if isInternal:
            log.info("***already Internal")
        while isInternal == False:
            log.info("excluding ID=%s" % tetID)
            excluded.append(tetID)
            (newTet, minValue) = self.find_closer_tet(m, closestTet, tets,
                                                      excluded)
            closestTet = copy.deepcopy(newTet)
            tetID = closestTet.ID
            #print("excluded = ", len(excluded))

            counter += 1
            if (counter == counterMax):
                break

            if tetID in excluded:
                log.info("ERROR***ID=%s was already excluded...excluded=%s" %
                         (tetID, excluded))
                broken = True
                break
            else:
                pass
                #print("ID=%s dist=%s" % (tetID, minValue))

            (isInternal, localVol) = closestTet.is_internal_node(m)

        if broken:
            (closestTet, tetID) = self.brute_force(m, tets, excluded)
        else:
            log.info("*findClosestTet worked!!!")

        #print("*tet[%s]=%s" % (tetID, closestTet))
        #print("nodes = ",closestTet.nodes)

        return closestTet, closestTet.ID
示例#8
0
    def map_deflections(self, properTets=None):
        """
        Loops thru all the aero nodes, finds the tet it's in, interpolates
        on the deflections at the nodes and maps the deflection to the aero node
        """
        if properTets is None:
            properTets = {}
        sys.stdout.flush()
        #reader = f06Reader(self.structuralOutfile)
        #d = reader.readDeflections()
        aeroNodes = self.aeroNodes
        #tets = self.tets
        d = self.deflectionReader
        tets = self.tets

        #tets = self.buildTetrahedralization()

        #aeroNodes = [array([0.0,0.,0.])]
        aeroNodes2 = []
        tet = tets[1]
        log.info("-" * 80)
        #print("type(aeroNodes)=%s" % type(aeroNodes))

        for i, aeroNode in iteritems(aeroNodes):
            if aeroNode[1] < 0:
                log.info('skipping aeroNode=%s bc y<0.' % i)
                continue
            log.info("aeroNode[%s]  = %s" % (i, ListPrint(aeroNode)))

            #print("aeroNode  = ",aeroNode)
            #continue

            if properTets.has_key(i):
                tet = tets[properTets[i]]
            else:
                (tet, ID2) = self.find_closest_tet(aeroNode, tet)

            #(isInternal, localVol) = closeTet.isInternalNode(aeroNode)
            #assert isInternal==True
            #print("isInternal?  = %s" % isInternal)

            #print("***tet = %s" % (tet))
            (n0, n1, n2, n3) = tet.nodes
            ID = tet.ID
            deflectionsTet = d.get_deflections(ID, n0, n1, n2, n3)
            aeroNode2 = tet.map_deflections(deflectionsTet, aeroNode)
            log.info("aeroNode2 = %s" % (ListPrint(aeroNode2)))
            properTets[i] = ID
            aeroNodes2.append(aeroNode2)

            #for tet in tets:  # should select in certain order based on centroids
            #    if tet.isInternalNode(aeroNode):
            #        n0,n1,n2,n3 = tet.nodes
            #
            #        deflectionsTet = [ d[n0],d[n1],d[n2],d[n3] ]
            #        aeroNode2 = tet.mapDeflections(deflectionsTet,aeroNode)
            #break # uncomment to run one aeroNode
            log.info("-" * 80)
            sys.stdout.flush()
        #return aeroNode2
        #for key,value in properTets.items():
        #    print("pointID=%s  -> tetID=%s" % (key, value))
        sys.stdout.flush()
        return (aeroNodes2, properTets)