示例#1
0
    def execute(self):

        if False == self.mInitialized:
            raise ThermError("IndivNetworkBuilder (%s) not initialized." % self.mNetwork)
        
        try:
            ## Read the TdNetworkConfig file. 
            tdData = self.readThermalDesktopData()
            
            ## Parse and analyze ThermRegistry.
            self.readThermRegistry()
            
            ## Perform Mass Analysis.
            self.performMassAnalysis()           
            
            ## Append ThermalDesktop data to the end of the xml config-files.
            self.appendThermalDesktopData(tdData)
            
            ## Heaters and panels are both derived from GunnsThermalSource, and they both have very
            ## similar registry schemas. They can be parsed with the same function.
            self.readThermSourceFile("heater", self.mHtrFile, self.mHtrList)
            self.readThermSourceFile("panel", self.mPanFile, self.mPanList)
            self.readThermSourceFile("source", self.mHtrFile, self.mSrcList)

            ## Write XML trees to file.
            self.mPrinter.printThermXml(self.mNodeXml, self.mNodeFile, self.mCallingScript)
            self.mPrinter.printThermXml(self.mCondXml, self.mCondFile, self.mCallingScript)
            self.mPrinter.printThermXml(self.mRadXml, self.mRadFile, self.mCallingScript)
            self.mPrinter.printThermXml(self.mEtcXml, self.mEtcFile, self.mCallingScript)
            
        except ThermError, e:
            print e,
            raise ThermError("Error executing network (%s)." % self.mNetwork)
示例#2
0
    def execute(self):
        if False == self.mInitialized:
            raise ThermError("ThermAspectBuilder not initialized.")

        ## Instantiate a ThermPrinter object.
        myPrinter = ThermPrinter()

        ## Open enum and icd files.
        try:
            f_enum = myPrinter.openFileForWriting(self.mEnumFile)
            f_icd = myPrinter.openFileForWriting(self.mIcdFile)

            ## Write enum headers.
            f_enum.write(ThermHeaders().enum % self.mCallingScript)
            guard = os.path.basename(self.mEnumFile).replace('.hh', '_')
            f_enum.write("#ifndef %sEXISTS\n" % guard)
            f_enum.write("#define %sEXISTS\n\n" % guard)

            ## Write icd header.
            f_icd.write(ThermHeaders().icd %
                        (self.mRegisDir, self.mCallingScript))

        except ThermError, e:
            print e
            raise ThermError("Error setting up PTCS enum/icd files.")
示例#3
0
    def registerNode(self, entryObj):

        ## Check for repeated node name.
        if entryObj.mName in self.regisNodeList:
            raise ThermError("Node previously defined in ThermRegistry.")

        ## Raise error if editGroup not defined in the header at the top of the registry.
        if None != entryObj.mEditGroup and entryObj.mEditGroup not in self.mEditCapGroupList:
            raise ThermError("editGroup not defined in <capEditing> (%s)." %
                             entryObj.mEditGroup)

        ## Append or Overwrite node's mass in the dictionary.
        self.mMassDict[entryObj.mName] = entryObj.mMass

        ## Find the enumIndex of this node.
        enumIndex = len(self.regisNodeList)

        ## If no initial temperature given, default to either the value from Thermal Desktop or just
        ## a neutral value.
        if -1 == entryObj.mInitTemp:
            try:
                entryObj.mInitTemp = self.mTempDict[entryObj.mName]
            except:
                entryObj.mInitTemp = 296.0

        ## Create <node> element.
        n = self.mParser.newElement("node", self.mNodeXml)
        self.mParser.newElement("enum", n).text = str(enumIndex)
        self.mParser.newElement("name", n).text = entryObj.mName
        self.mParser.newElement("mass", n, {"units": "kg"}).text = \
                                self.mParser.roundValue(entryObj.mMass, 2)
        self.mParser.newElement("temperature", n, {"units": "K"}).text = \
                                self.mParser.roundValue(entryObj.mInitTemp, 2)
        self.mParser.newElement("capacitance", n, {"units": "J/K"}).text = \
                                self.mParser.roundValue(entryObj.mCapacitance, 2)

        ## Create an <editGroup> subelement if applicable.
        if None != entryObj.mEditGroup:
            ## Create element for editGroup.
            self.mParser.newElement("editGroup", n).text = entryObj.mEditGroup

        ## Add node to nodeLists for enumeration.
        self.regisNodeList.append(entryObj.mName)
        ## Check if the registry node has a duplicate in ThermalDesktop.
        if entryObj.mName in self.tdNodeList:
            self.isRegistered[entryObj.mName] = True
        else:
            self.masterNodeList.append(entryObj.mName)

        ## Process ICD jobs contained in the entryObj.
        self.mIcdBuilder.extractAndProcessIcd(entryObj, "capacitor", enumIndex)
示例#4
0
    def registerRad(self, entryObj):
        ## Loop through all radiation links in the radiation map.
        for (radName, toNode, coeff, element) in entryObj.mRadiationList:
            try:
                ## Verify not previously added.
                if radName in self.mRadList:
                    raise ThermError("Radiation link previously defined.")

                ## Check that the <to> nodes are valid.
                self.validateNode(toNode, "to")

                ## Create <radiation> element.
                r = self.mParser.newElement("radiation", self.mRadXml)
                self.mParser.newElement("node0", r).text = entryObj.mName
                self.mParser.newElement("node1", r).text = toNode
                self.mParser.newElement("coefficient", r, {
                    "units": "m2"
                }).text = self.mParser.roundValue(coeff, 6)

                ## Find the enumIndex of this radiation link.
                enumIndex = len(self.mRadList)

                ## Add radName to radList for enumeration.
                self.mRadList.append(radName)

                ## Build Icd jobs.
                self.mIcdBuilder.processIcd(element, radName, "radiation",
                                            enumIndex, entryObj.mDescription)

            ## Do not write data if <to> tag not found or node not registered.
            except (ThermError, TagNotFound), e:
                print e, "Radiation link \"%s\" will be skipped (for entry %s)." % (
                    radName, entryObj.mName)
示例#5
0
    def loadConduction(self):

        ## Loop through all <cond> tags.
        for condElement in self.mParser.getElements(self.mEntry, "conduction"):
            try:
                ## Make sure the cond value, defined with symbols, can be properly evaluated.
                conductivity = self.mParser.getChildText(
                    condElement, "conductivity", self.mName)
                conductivity = self.getValidatedValue(conductivity, self.mName)

                ## The conduction will be skipped unless exactly one <to> tag is found.
                toNodeElems = self.mParser.getElements(condElement, "to", True,
                                                       self.mName)
                if 1 == len(toNodeElems):
                    toNode = self.mParser.getText(toNodeElems[0])
                else:
                    raise ThermError("Must provide exactly one <to> node.")

                ## Define the conductor using a map that provides {toNode : conductivity}
                self.mConductionList.append((toNode, conductivity))

            ## Do not write data if <to> tag not found or node not registered.
            except (ThermError, TagNotFound), e:
                print e,
                print "Conduction link will be skipped (%s)." % self.mName
示例#6
0
 def loadFile(self, xmlFile):
     # Get root from the xml.
     try:
         root = ET.parse(xmlFile, parser = CommentedTreeBuilder()).getroot()
     except IOError, e:
         print e
         raise ThermError("Error opening file: %s" % xmlFile)
示例#7
0
    def registerPot(self, entryObj):

        ## Loop through all potential links in the radiation map.
        for (potName, conductivity, element) in entryObj.mPotentialList:
            try:
                ## Create <potential> element.
                p = self.mParser.newElement("potential", self.mEtcXml)
                self.mParser.newElement("name", p).text = potName
                self.mParser.newElement("node", p).text = entryObj.mName
                self.mParser.newElement("temperature", p, {"units": "K"}).text = \
                                        self.mParser.roundValue(entryObj.mInitTemp,2)
                self.mParser.newElement("conductivity", p, {"units": "W/K"}).text = \
                                        self.mParser.roundValue(conductivity,6)

                ## Find the enumIndex of this potential.
                enumIndex = len(self.mPotList)

                ## Process ICD jobs contained in the entryObj.
                self.mIcdBuilder.extractAndProcessIcd(entryObj, "potential",
                                                      enumIndex)

                ## Add potential to mPotList for enumeration.
                self.mPotList.append(potName)

            except (ThermError, TagNotFound), e:
                print e,
                raise ThermError("Error in <potential>.")
示例#8
0
 def evaluateExpression(self, name, expr, symMap):
     try:
         return eval(expr, globals(), symMap)
     except (SyntaxError), e:
         print e
         print "***File: %s." % self.mCurrentFile
         print "***Symbol: %s." % name
         print "***Expression: %s." % expr
         raise ThermError("Cannot evaluate symbol expression.")
示例#9
0
    def roundValue(self, val, dec):
        ## Default code to floating point notation.
        code = "f"
        try:
            rnd = round(float(val),dec)
            
            ## If the number is large, use scientific notation.
            if abs(rnd) > 1e9:
                code = "e"

            format = "%." + str(dec) + code;
            return (format % rnd)
        
        except ValueError, e:
            raise ThermError("Cannot be coverted to a float: %s" % val)
示例#10
0
class XmlParser:
    #===============================================================================================
    ## @brief:
    ## Open an xml document and return the entire data tree.
    ## @param[in]: xmlFile  file name of well-formed xml document to parse
    ## @return:    root     ElementTree of entire xml data structure
    def loadFile(self, xmlFile):
        # Get root from the xml.
        try:
            root = ET.parse(xmlFile, parser = CommentedTreeBuilder()).getroot()
        except IOError, e:
            print e
            raise ThermError("Error opening file: %s" % xmlFile)
        except ExpatError, e:
            print e
            raise ThermError("Error parsing file: %s" % xmlFile)
示例#11
0
 def initialize(self, thermAspectConfig):
     
     ## Initialize members.
     self.mCallingScript = thermAspectConfig.cCallingScript
     self.mHome = thermAspectConfig.cHome
     self.mIcdFile = thermAspectConfig.cIcdFile
     self.mEnumFile = thermAspectConfig.cEnumFile
     self.mSymFiles = thermAspectConfig.cSymFiles
     
     ## Load symbols dictionary from symbol xml files.
     print "Loading symbols."
     try:
         symMap = self.loadSymbols()
     except ThermError, e:
         print e
         raise ThermError("Error while loading symbols.")
示例#12
0
    def initialize(self, linkType, entry, symMap={}):
        ## The initial temperature of the node.
        self.mLinkType = linkType.lower()

        if self.mLinkType != "heater" and \
           self.mLinkType != "source" and \
           self.mLinkType != "panel":
            raise ThermError("Link type does not exist (%s)." % self.mLinkType)

        ## Base class initializer
        XmlEntryAnalyzer.initialize(self, entry, symMap)

        ## Initialize properties specific to ThermalSource entries.
        self.loadData()

        ## Raise the flag only if we've made it this far.
        self.mIsInitialized = True
示例#13
0
    def createIcdExchange(self, id, linkType, enumIndex, category, iter, writeElement, readElements,\
                          pui, subsys, varType, comments):

        ## Create a default Ptcs icd job.
        ptcsIcdElement = self.mParser.newElement("icd", None,
                                                 {"isReadyForIcd": 'true'})
        self.mParser.newElement(
            "rate", ptcsIcdElement).text = self.mIcdSettings.mPtcsRate
        self.mParser.newElement(
            "simObject",
            ptcsIcdElement).text = self.mIcdSettings.mPtcsSimObject
        self.mParser.newElement("simVarName",
                                ptcsIcdElement).text = "[not set]"

        ## If no writeElement passed, then Ptcs does the writing.
        if None == writeElement:
            ## Substitute the simVarName for Ptcs writes.
            ptcsIcdElement.find(
                "simVarName"
            ).text = self.mNetwork + self.mIcdSettings.mSvnWrite[linkType] % id
            writeElement = ptcsIcdElement

        ## If no readElements passed, then Ptcs does the reading.
        elif None == readElements:
            ## Substitute the simVarName for Ptcs reads.
            simVarName = self.mNetwork + self.mIcdSettings.mSvnRead[
                linkType].replace("%i", iter)
            ptcsIcdElement.find("simVarName").text = simVarName % id
            readElements = [ptcsIcdElement]

        else:  # We have a problem.
            raise ThermError(
                "At least one element (read or write) must be None. (%s)" % id)

        ## Instantiate newIcdExchange
        newIcdExchange = IcdExchange()

        ## Set units for Exchange.
        units = self.mIcdSettings.mUnitsMap[category]
        varName = id + "_" + self.getVarNameSuffix(category, iter)

        ## Initialize IcdExchange object with tailored data.
        newIcdExchange.initialize(id, enumIndex, varName, writeElement, readElements,\
                                                pui, subsys, varType, units, comments)
        ## Append to list of jobs.
        self.mListOfExchanges.append(newIcdExchange)
示例#14
0
    def registerSrc(self, entryObj, theType, srcList):

        ## Verify not previously added.
        if entryObj.mName in srcList:
            raise ThermError("Link previously defined.")

        ## Find the enumIndex of this source.
        enumIndex = len(srcList)
        
        ## Check that the <to> nodes are valid.
        for node in entryObj.mNodeList:
            self.validateNode(node, "node")
                
        ## Append source to list of successfully-build sources.
        srcList.append(entryObj.mName)
        
        ## Build Icd jobs.
        self.mIcdBuilder.processIcd(entryObj.mEntry, entryObj.mName, theType, enumIndex, entryObj.mDescription)
示例#15
0
    def initialize(self, entry, symMap={}):

        ## An xml entry from a registry file. This object is only associated with a single entry.
        self.mEntry = entry
        ## A dictionary with the definitions of symbols used in the registries
        self.mSymMap = symMap
        ## Name of the Thermal Gunns node/link, as read from the registry entry.
        self.mName = entry.get("name")

        ## The node entry must have a name. Raise exception if otherwise.
        if None == self.mName:
            raise ThermError("Must have a name attribute.")

        ## The link's description as read from registry entry.
        try:
            self.mDescription = self.mParser.getChildText(entry, "des")
        except TagNotFound:
            self.mDescription = ""
示例#16
0
    def defineSymbols(self, nameList, expList, localVars, attemptsMax=5):

        try:
            ## Initialize.
            symMap = {}
            all_defined = False
            attempts = 0

            ## Loop until all symbols have been resolved.
            while False == all_defined:

                ## If not all symbols are resolved after so many attempts, raise exception.
                if attempts > attemptsMax:
                    raise StopIteration(undefined)

                ## Reset define info.
                all_defined = True
                undefined = []

                ## Loop over symbol names in list.
                for name, exp in zip(nameList, expList):
                    ## To save time, skip those symbols who are already defined in the symMap.
                    if name in symMap:
                        continue

                    ## Try to evaluate the expression. A NameError is raised and caught if the
                    ## a symbol contained in the expression has not been defined yet.
                    try:
                        symMap[name] = self.evaluateExpression(
                            name, exp, symMap)

                    ## If a symbol name is not recognized, then not all symbols are defined yet.
                    except NameError, detail:
                        all_defined = False
                        undefined.append(str(detail))

                ## Monitor attempts. This is to make sure you don't get stuck in infinite loop.
                attempts = attempts + 1

        except StopIteration, e:
            undefined = e.args[0]
            for u in undefined:
                print "    ", u
            raise ThermError("Cannot resolve symbols.")
示例#17
0
    def loadRadiation(self):

        ## Loop through all <radiation> tags.
        radElements = self.mParser.getElements(self.mEntry, "radiation")
        for i in range(0, len(radElements)):

            ## Set name.
            radName = "rad%i_%s" % (i, self.mName)

            try:
                ## Make sure the coeff value, defined with symbols, can be properly evaluated.
                coeff = self.mParser.getChildText(radElements[i],
                                                  "coefficient", radName)

            ## If no <coefficient> is found, we will default to the TD value. Store a 0.0 for now.
            except TagNotFound, e:
                coeff = "0.0"

            try:
                ## Verify coefficient value found above.
                coeff = self.getValidatedValue(coeff, radName)

                ## The radiation will be skipped unless exactly one <to> tag is found.
                toNodeElems = self.mParser.getElements(radElements[i], "to",
                                                       True, self.mName)
                if 1 == len(toNodeElems):
                    toNode = self.mParser.getText(toNodeElems[0])
                else:
                    raise ThermError("Must provide exactly one <to> node.")

                ## Define the radiation link using a map that provides:
                ## {radName : (toNode, coefficient, element)}
                self.mRadiationList.append(
                    (radName, toNode, coeff, radElements[i]))

            ## Do not write data if <to> tag not found or node not registered.
            except (ThermError, TagNotFound), e:
                print e, "Radiation link \"%s\" will be skipped (%s)." % (
                    radName, self.mName)
                continue
示例#18
0
    def loadNode(self):
        ## Get capacitor data
        capacitors = self.mParser.getElements(self.mEntry, "capacitor")

        ## Make sure only zero or one <capacitor> is given.
        if 0 == len(capacitors):
            self.mMass = 0
            self.mCapacitance = 0
            return
        elif len(capacitors) > 1:
            raise ThermError("Can only have one <capacitor> per node.")

        ## Read capacitor's editGroup if found. Otherwise, leave it as None.
        try:
            self.mEditGroup = self.mParser.getChildText(
                capacitors[0], "editGroup", self.mName)
        except TagNotFound:
            pass

        ## Make sure the cap value, defined with symbols, can be properly evaluated.
        capExpr = self.mParser.getChildText(capacitors[0], "capacitance",
                                            self.mName)
        capacitance = self.getValidatedValue(capExpr, self.mName)
        ## Default the mass to an estimation based on an assumed specific heat.
        mass = capacitance / self.mAssumedCp

        ## The capacitance expression is typically just a previously defined symbol.
        ## If so, and its properly prefixed with "cap_", then a "mass_" symbol will also exist.
        if "cap_" in capExpr:
            try:
                massSym = capExpr.replace("cap_", "mass_")
                mass = self.getValidatedValue(massSym, self.mName)

            ## If there's an error, like a negative mass, just use the previous estimation.
            except ThermError:
                pass

        ## Set the entry's mass and capacitance.
        self.mMass = mass
        self.mCapacitance = capacitance
示例#19
0
    def loadPotential(self):
        ## Get potential data
        potentials = self.mParser.getElements(self.mEntry, "potential")

        ## Set name.
        potName = 'pot_' + self.mName

        ## Make sure only zero or one <potential> is given.
        if 0 == len(potentials):
            return
        elif len(potentials) > 1:
            raise ThermError("Can only have one <potential> per node.")

        ## The conductivity of the link, in this case a value in W/K. Check if tag
        ## <conductivity> is given; if not, set it to a default.
        conductivity = self.getUnrequiredData(potentials[0], "conductivity")
        if None == conductivity:
            conductivity = 1e12

        ## Define the potential using a map that provides:
        ## {potName : (conductivity, element)}
        self.mPotentialList.append((potName, conductivity, potentials[0]))
示例#20
0
 def getText(self, element, info=''):
     text = self.checkForUnicode(element.text, info)
     if None == text or "" == text:
         format = (element.tag, info)
         raise ThermError("No text provided in tag <%s> (%s)." % format )
     return text
示例#21
0
 def checkForUnicode(self, s, info=''):
     if isinstance(s, unicode):
         raise ThermError("Unicode character detected.")
     else:
         return s
示例#22
0
 def validateNode(self, node, tagInfo=''):
     if node not in self.masterNodeList:
         warning = "Node does not exist: <%s>%s</%s>." % (tagInfo, node,
                                                          tagInfo)
         raise ThermError(warning)
示例#23
0
class XmlEntryAnalyzer:
    ## @brief:
    ## Default constructs the object with default, uninitialized members.
    def __init__(self):
        uninitialized = "[not initialized]"

        ## An XmlParser() object for getting data from xml elements.
        self.mParser = XmlParser()
        ## An xml entry from a registry file. This object is only associated with a single entry.
        self.mEntry = uninitialized
        ## A dictionary with the definitions of symbols used in the registries
        self.mSymMap = uninitialized
        ## Name of the Thermal Gunns link, as read from the registry entry.
        self.mName = uninitialized
        ## The link's number in the network's array. Initialized to an invalid value of -1.
        self.mEnumIndex = -1
        ## The link's description
        self.mDescription = uninitialized
        ## Initialization flag.
        self.mIsInitialized = False

    #===============================================================================================
    ## @brief:
    ## Constructs the class using two arguments.
    ## @param[in]: entry    ElementTree xml-element of data from Thermal, Htr, or Panel registry
    ## @param[in]: symMap   dictionary with the definitions of symbols used in the registries
    def initialize(self, entry, symMap={}):

        ## An xml entry from a registry file. This object is only associated with a single entry.
        self.mEntry = entry
        ## A dictionary with the definitions of symbols used in the registries
        self.mSymMap = symMap
        ## Name of the Thermal Gunns node/link, as read from the registry entry.
        self.mName = entry.get("name")

        ## The node entry must have a name. Raise exception if otherwise.
        if None == self.mName:
            raise ThermError("Must have a name attribute.")

        ## The link's description as read from registry entry.
        try:
            self.mDescription = self.mParser.getChildText(entry, "des")
        except TagNotFound:
            self.mDescription = ""

    #===============================================================================================
    ## @brief:
    ## Evaluate an expression value based on symbols defined in mSymMap.
    ## @param[in]: expr    a mathematical expression that may contain symbols defined in mSymMap
    ## @param[in]: info    optional string used in error reporting
    ## @return:    the evaluated expression in numerical form
    def getValidatedValue(self, expr, info=''):
        try:
            value = eval(expr, globals(), self.mSymMap)
        except (NameError, SyntaxError), e:
            print e,
            raise ThermError("Invalid value: %s (%s)." % (expr, info))

        ## Do not accept negative values.
        if value < 0:
            raise ThermError("Cannot accept a negative. %s = %f" %
                             (expr, value))

        return value
示例#24
0
    def loadSymbolsFrom(self, symFile):

        ## Set current file for error reporting purposes.
        self.mCurrentFile = symFile

        ## Try to open the symbol file. Open it for reading and save its xml data.
        symbols = self.mParser.loadFile(symFile)

        ## Initialize lists.
        nameList = []
        expList = []
        desList = []
        groupList = []

        ## Loop over the symbols.
        for symbol in symbols:
            ## Initialize name for error reporting.
            name = "[error reading name]"

            ## Get data.
            try:
                name = self.mParser.getChildText(symbol, "name")
                expElem = self.mParser.getElements(symbol, "exp", True,
                                                   name)[0]
                expText = self.mParser.getText(expElem, name)

                if name in nameList:
                    ## If the symbol is a mass, it can overwrite a previous instance.
                    if 'mass_' == name[:5]:
                        expList[nameList.index(name)] = expText
                        continue
                    else:
                        raise ThermError("Symbol previously defined (%s)." %
                                         name)

                ## Special instructions for capacitance symbols, for mass accounting purposes.
                if 'cap_' == name[:4]:
                    try:
                        ## Read the given mass from the symbols element.
                        specHeatText = self.mParser.getChildText(
                            expElem, "specHeat", name)
                        massText = self.mParser.getChildText(
                            expElem, "mass",
                            name).replace('%Cp', specHeatText)
                        expText = "(%s) * (%s)" % (massText, specHeatText)

                    except (TagNotFound), e:
                        ## Store a "-1" as an indication that no mass data was provided.
                        massText = "-1"

                    ## Append a symbol for the mass.
                    nameList.append(name.replace("cap_", "mass_"))
                    expList.append(massText)

                ## Append name and expression to list.
                nameList.append(name)
                expList.append(expText)

            except (TagNotFound, ThermError), e:
                print e,
                print "Symbol will be ignored (%s)." % name
                continue
示例#25
0
 def getValidatedValue(self, expr, info=''):
     try:
         value = eval(expr, globals(), self.mSymMap)
     except (NameError, SyntaxError), e:
         print e,
         raise ThermError("Invalid value: %s (%s)." % (expr, info))