Ejemplo n.º 1
0
 def parse_output(self):
     """Parses the PCYL output file and extracts data."""
     
     infile = FileParser()
     infile.set_file(self.stdout)
     
     self.wwingt = infile.transfer_keyvar("Total Wing Structural Weight", 1)
     self.wfuselaget = infile.transfer_keyvar("Fuselage Total Structural Weight", 1)
Ejemplo n.º 2
0
    def execute(self):

        lenght = self.lenght
        radius_2 = self.radius_2
        radius_4 = self.radius_4
        alpha = self.alpha
        beta = self.beta

        # Prepare the input file

        system('del ark_stent.py')  # deletes previous input file

        parser = InputFileGenerator()
        parser.set_template_file('template.py')
        parser.set_generated_file('ark_stent.py')

        parser.reset_anchor()
        parser.mark_anchor("lenght")
        parser.transfer_var(lenght, 0, 2)

        parser.reset_anchor()
        parser.mark_anchor("radius_2")
        parser.transfer_var(radius_2, 0, 2)

        parser.reset_anchor()
        parser.mark_anchor("radius_4")
        parser.transfer_var(radius_4, 0, 2)

        parser.reset_anchor()
        parser.mark_anchor("alpha")
        parser.transfer_var(alpha, 0, 2)

        parser.reset_anchor()
        parser.mark_anchor("beta")
        parser.transfer_var(beta, 0, 2)

        parser.generate()

        #Run Abaqus vi External's code execute function

        super(WrapAbaqus_stent, self).execute()

        #Parse the output files from abaqus

        parser = FileParser()
        parser.set_file('output.txt')

        parser.reset_anchor()
        parser.mark_anchor("max_mises")
        var = parser.transfer_var(1, 1)
        self.max_mises = var

        parser.reset_anchor()
        parser.mark_anchor("minus_max_displacement")
        var = parser.transfer_var(1, 1)
        self.minus_max_displacement = var

        print self.return_code
Ejemplo n.º 3
0
 def parse_output(self):
     """Parses the PCYL output file and extracts data."""
     
     infile = FileParser()
     infile.set_file(self.stdout)
     
     self.wwingt = infile.transfer_keyvar("Total Wing Structural Weight", 1)
     self.wfuselaget = infile.transfer_keyvar("Fuselage Total Structural Weight", 1)
Ejemplo n.º 4
0
    def load_model(self, filename):
        """Reads in an existing PDCYL input file and populates the variable
        tree with its values."""

        infile = FileParser()
        infile.set_file(filename)

        # Title is a string
        self.title = infile.transfer_line(2)

        # Print flag becomes a Bool
        if infile.transfer_var(4, 1) == 3:
            self.icalc = True
        else:
            self.icalc = False

        # Named variables in dictionary
        for key, val in self._fields.iteritems():
            self.set(val, infile.transfer_var(key, 1))
Ejemplo n.º 5
0
    def load_model(self, filename):
        """Reads in an existing PDCYL input file and populates the variable
        tree with its values."""
        
        infile = FileParser()
        infile.set_file(filename)
        
        # Title is a string
        self.title = infile.transfer_line(2)

        # Print flag becomes a Bool
        if infile.transfer_var(4, 1) == 3:
            self.icalc = True
        else:
            self.icalc = False
        
        # Named variables in dictionary
        for key, val in self._fields.iteritems():
            self.set(val, infile.transfer_var(key, 1))
Ejemplo n.º 6
0
    def execute(self):
        """Runs the NastranComponent.

        We are overiding ExternalCode's execute function. First, we
        setup the input file (by running NastranReplacer and then
        NastranMaker). Next, we run Nastran by calling our
        parent's execute function. Finally, we parse the data
        and set the output variables given to us.

        RuntimeError
            The component relies on ExternalCode which can throw all
            sorts of RuntimeError-like exceptions (RunStopped,
            RunInterrupted also included).
            
        Filesystem-type Errors
            NastranComponent makes a temporary directory with mkdtemp
            in the temp module. If that fails, the error just
            propagates up.


        While there are no explicit parameters or return values for this
        function, it gets all the input it needs from the design
        variables that are connected to the subclass of NastranComponent.
        This should be described pretty well in the :ref:`documentation<NastranComponent>`.

        """
        # We are going to keep track of all the ways we
        # can manage input/output:
        #  - the crude way (NastranReplacer, NastranOutput)
        #    correspond to input_variables, output_variables
        #  - the better way (NastranMaker, NastranParser)
        #    correspond to smart_replacements and grid_outputs

        # all of these are {"traitname" : trait}
        input_variables = {}
        smart_replacements = {}
        output_variables = {}
        grid_outputs = {}

        for name, trait in self.traits().iteritems():
            if trait.iotype == "in":
                # nastran_var is a variable that should be replaced
                if trait.nastran_var:
                    # if the variable is longer than seven characters
                    # it won't fit in the nastran file, since the limit
                    # there is 8 characters (%xxxxxxx)
                    if len(trait.nastran_var) > 7:
                        raise ValueError("The variable " + trait.nastran + \
                                         " is too long to be a variable")
                    input_variables[name] = trait

                # it could also be a smart replacement, but we'll have
                # to specify the card, id, and fieldnum
                if trait.nastran_card and trait.nastran_id and trait.nastran_fieldnum:
                    smart_replacements[name] = trait

                elif trait.nastran_card or trait.nastran_id or trait.nastran_fieldnum:
                    raise RuntimeError("You specified at least one of " + \
                                    "nastran_card, nastran_id, and " + \
                                    "nastran_fieldnum, but you did " + \
                                    "not specify all of them. You " + \
                                    "most probably mistyped.")

            elif trait.iotype == "out":
                # if we want to supply a function that will parse
                # out the wanted information from the output object
                # and the fileparser, then this
                if trait.nastran_func:
                    output_variables[name] = trait

                # this is the grid method of accessing. We have to
                # specify a header, row, and attribute and
                # the output variable will be set to that value
                if trait.nastran_header and trait.nastran_constraints and trait.nastran_columns:
                    grid_outputs[name] = trait
                elif trait.nastran_header or trait.nastran_constraints or trait.nastran_columns:
                    raise RuntimeError("You specified at least one of " + \
                                    "nastran_header, nastran_constrains"+\
                                    ", and nastran_columns, but you " + \
                                    "did not specify all them. You " + \
                                    "most probably mistyped")

        # let's do our work in a tmp dir
        # let's do our work in a tmp dir
        tmpdir = mkdtemp(dir = self.output_tempdir_dir)
        tmppath = path.join(tmpdir, "input.bdf")
        tmpfh = open(tmppath, "w")

        # raw nastran file supplied by user
        fh = open(self.nastran_filename, "r")

        # note: fh.readlines() won't work because it doesn't
        # strip the newline at the end for you. So whatever,
        # we'll just use split on newlines.
        nastran_text = fh.read().split("\n")
        fh.close()

        # replace the variables in the nastran text using Replacer
        replacer = NastranReplacer(nastran_text)
        varname2value = {}
        for name, trait in input_variables.iteritems():
            varname2value[trait.nastran_var] = getattr(self, name)
        replacer.replace(varname2value)
        nastran_text = replacer.text

        # use nastran maker to intelligently replace
        # values in cards
        maker = NastranMaker(nastran_text)
        for name, trait in smart_replacements.iteritems():
            value = getattr(self, name)
            maker.set(trait.nastran_card,
                      trait.nastran_id,
                      trait.nastran_fieldnum, value)
        self.nastran_maker_hook(maker)
        maker.write_to_file(tmpfh, 10001)

        tmpfh.close()

        # what is the new file called?
        self.output_filename = path.join(tmpdir, "input.out")

        # perhaps this should be logged, or something
        print self.output_filename

        # Then we run the nastran file
        self.command = self.nastran_command + " " + \
                       tmppath + " " + self.nastran_command_args + \
                       " batch=no out=" + tmpdir + \
                       " dbs=" + tmpdir

        # This calls ExternalCode's execute which will run
        # the nastran command via subprocess
        super(NastranComponent, self).execute()

        # And now we parse the output

        filep = FileParser()
        filep.set_file(self.output_filename)
        filep.set_delimiters(" ")

        # Before we start, we want to make sure we aren't
        # dealing with a failed run. So we search for "FATAL"
        for line in filep.data:
            if "FATAL" in line:
                raise RuntimeError("There was a problem with " + \
                                   "Nastran. It failed to run " + \
                                   "correctly. If you want to see " +\
                                   "the output, check out " + \
                                   self.output_filename)


        for output_name, output_trait in output_variables.iteritems():
            # We run trait.nastran_func on filep and get the
            # final value we want
            setattr(self, output_name,
                    output_trait.nastran_func(filep))


        # This is the grid parser.
        self.parser = NastranParser(filep.data)
        self.parser.parse()

        for name, trait in grid_outputs.iteritems():
            header = trait.nastran_header
            subcase = trait.nastran_subcase
            constraints = trait.nastran_constraints
            columns = trait.nastran_columns
            result = self.parser.get(header, subcase, \
                                     constraints, columns)

            # nastran_{row,column} might be kinda silly
            # in most cases, the user will probably just call
            # self.parser.get on her own
            nastran_row = trait.nastran_row
            nastran_column = trait.nastran_column
            row = nastran_row or 0
            col = nastran_column or 0

            # Now we'll try to guess the conversion we should
            # perform by inspecting the type of trait that
            # is requesting this value
            converter = lambda x: x
            type_understood_as = "unsure"
            if isinstance(trait.trait_type, Float):
                converter = float
                type_understood_as = "float"
            elif isinstance(trait.trait_type, Int):
                converter = lambda x: int(float(x))
                type_understood_as = "int"
            elif isinstance(trait.trait_type, Array):
                # we aren't actually going to return the entire
                # grid because you should use parser if you
                # want to do that.
                converter = lambda x: [x]
                type_understood_as = "array"

            try:
                setattr(self, name, converter(result[row][col]))
            except ValueError, ve:
                print >> sys.stderr, "Unable to convert string " + \
                      result[row][col] +  " to " + type_understood_as
                raise
Ejemplo n.º 7
0
    def parse_output(self):
        """Parses the HSRNOISE output file and extracts data."""

        outfile = FileParser()
        outfile.set_file('test.output')

        outfile.mark_anchor("JN8C4 JET NOISE MODULE")
        outfile.mark_anchor("TOTAL")
        self.thetas = outfile.transfer_array(4, 2, 4, 18)
        self.Freq = outfile.transfer_2Darray(7, 1, 30, 1)
        self.SPL = outfile.transfer_2Darray(7, 2, 30, 18)
        outfile.mark_anchor("DBA")
        self.OASPL = outfile.transfer_array(-1, 2, -1, 18)
        self.OASPL30 = outfile.transfer_var(-1, 4)
        self.OASPL60 = outfile.transfer_var(-1, 7)
        self.OASPL90 = outfile.transfer_var(-1, 10)
        self.OASPL120 = outfile.transfer_var(-1, 13)
        self.OASPL150 = outfile.transfer_var(-1, 16)

        outfile.mark_anchor("EPNL SUMMARY")
        self.TotalEPNL = outfile.transfer_var(9, 2)
        self.TotalMaxPNLT = outfile.transfer_var(9, 5)
        self.JetEPNL = outfile.transfer_var(8, 2)
Ejemplo n.º 8
0
    def test_more_delims(self):

        data = "anchor,1.0,2.0\n" + \
               "abc=123.456\n" + \
               "c=1,2,Word,6\n" + \
               "d=C:/abc/def,a+b*c^2,(%#%),!true\n" + \
               "a^33 1.#QNAN^#$%^"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        op = FileParser()
        op.set_file(self.filename)

        olddelims = op.delimiter
        op.set_delimiters(' \t,=')

        op.mark_anchor('anchor')

        val = op.transfer_var(0, 1)
        self.assertEqual(val, 'anchor')
        val = op.transfer_var(0, 2)
        self.assertEqual(val, 1.0)
        val = op.transfer_var(1, 1)
        self.assertEqual(val, 'abc')
        val = op.transfer_var(1, 2)
        self.assertEqual(val, 123.456)
        val = op.transfer_var(2, 4)
        self.assertEqual(val, 'Word')
        val = op.transfer_var(2, 5)
        self.assertEqual(val, 6)
        val = op.transfer_var(3, 2)
        self.assertEqual(val, 'C:/abc/def')
        val = op.transfer_var(3, 3)
        self.assertEqual(val, 'a+b*c^2')
        val = op.transfer_var(3, 4)
        self.assertEqual(val, '(%#%)')
        val = op.transfer_var(3, 5)
        self.assertEqual(val, '!true')

        op.set_delimiters(' \t^')
        val = op.transfer_var(4, 1)
        self.assertEqual(val, 'a')
        val = op.transfer_var(4, 2)
        self.assertEqual(val, 33)
        val = op.transfer_var(4, 3)
        self.assertEqual(isnan(val), True)
        val = op.transfer_var(4, 4)
        self.assertEqual(val, '#$%')
Ejemplo n.º 9
0
    def test_comment_char(self):

        # Check to see if the use of the comment
        #   characters works
        data = "Junk\n" + \
                   "CAnchor\n" + \
                   " Z 11, 22 344, Test 1e65\n" + \
                   " B 4 Stuff\n" + \
                   "  $ Anchor\n" + \
                   " Q 1, 2 34, Test 1e65\n" + \
                   " B 4 Stuff\n" + \
                   "Anchor\n" + \
                   " A 1, 2 34, Test 1e65\n" + \
                   " B 4 Stuff\n" + \
                   "Anchor\n" + \
                   " C 77 False NaN 333.444\n" + \
                   " 1,2,3,4,5\n" + \
                   " Inf 1.#QNAN -1.#IND\n"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        # Test full line comments
        gen = FileParser(full_line_comment_char="C")
        gen.set_file(self.filename)
        gen.set_delimiters(' ')
        gen.mark_anchor('Anchor')
        val = gen.transfer_var(1, 1)
        self.assertEqual(val, 'A')

        # Test end of line comments also
        gen = FileParser(full_line_comment_char="C", end_of_line_comment_char="$")
        gen.set_file(self.filename)
        gen.set_delimiters(' ')
        gen.mark_anchor('Anchor')
        val = gen.transfer_var(1, 1)
        self.assertEqual(val, 'A')
Ejemplo n.º 10
0
    def test_output_parse_2Darray(self):

        data = '''
        Anchor
            FREQ  DELTA  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5  -8.5
             Hz
             50.   1.0   30.0  34.8  36.3  36.1  34.6  32.0  28.4  23.9  18.5  12.2   5.0  -3.1 -12.3 -22.5 -34.0 -47.2 -63.7
             63.   1.0   36.5  41.3  42.8  42.6  41.1  38.5  34.9  30.4  25.0  18.7  11.5   3.4  -5.8 -16.0 -27.5 -40.7 -57.2
             80.   1.0   42.8  47.6  49.1  48.9  47.4  44.8  41.2  36.7  31.3  25.0  17.8   9.7   0.5  -9.7 -21.2 -34.4 -50.9
            100.   1.0   48.4  53.1  54.7  54.5  53.0  50.4  46.8  42.3  36.9  30.6  23.3  15.2   6.1  -4.2 -15.7 -28.9 -45.4
            125.   1.0   53.6  58.3  59.9  59.6  58.1  55.5  52.0  47.5  42.0  35.7  28.5  20.4  11.2   1.0 -10.5 -23.7 -40.2
            160.   1.0   58.9  63.7  65.2  65.0  63.5  60.9  57.3  52.8  47.4  41.0  33.8  25.7  16.5   6.3  -5.2 -18.4 -34.9
            200.   1.0   63.4  68.1  69.6  69.4  67.9  65.3  61.7  57.2  51.8  45.5  38.3  30.1  21.0  10.7  -0.8 -14.0 -30.5
            250.   1.0   67.5  72.2  73.7  73.5  72.0  69.4  65.8  61.3  55.9  49.5  42.3  34.2  25.0  14.8   3.3 -10.0 -26.5
            315.   1.0   71.3  76.1  77.6  77.4  75.8  73.2  69.7  65.1  59.7  53.4  46.1  38.0  28.8  18.6   7.1  -6.2 -22.7
            400.   1.0   74.9  79.7  81.2  81.0  79.4  76.8  73.2  68.7  63.2  56.9  49.7  41.5  32.4  22.1  10.6  -2.7 -19.2
            500.   1.0   77.9  82.7  84.2  83.9  82.4  79.8  76.2  71.6  66.2  59.8  52.6  44.4  35.3  25.0  13.5   0.2 -16.3
            630.   1.0   80.7  85.4  86.9  86.6  85.1  82.4  78.8  74.3  68.8  62.5  55.2  47.0  37.9  27.6  16.1   2.8 -13.7
            800.   1.0   83.1  87.8  89.2  89.0  87.4  84.8  81.2  76.6  71.1  64.8  57.5  49.3  40.1  29.9  18.3   5.0 -11.5
           1000.   1.0   84.9  89.6  91.1  90.8  89.2  86.6  82.9  78.4  72.9  66.5  59.2  51.0  41.8  31.5  20.0   6.6  -9.9
           1250.   1.0   86.4  91.1  92.5  92.2  90.7  88.0  84.3  79.7  74.2  67.8  60.5  52.3  43.1  32.8  21.2   7.9  -8.7
           1600.   1.0   87.6  92.3  93.7  93.4  91.8  89.1  85.4  80.8  75.2  68.8  61.5  53.3  44.0  33.7  22.1   8.7  -7.9
           2000.   1.0   88.4  93.0  94.4  94.0  92.4  89.6  85.9  81.3  75.7  69.3  61.9  53.7  44.4  34.0  22.4   9.0  -7.6
           2500.   1.0   88.7  93.3  94.6  94.2  92.6  89.8  86.1  81.4  75.8  69.3  61.9  53.6  44.3  33.9  22.2   8.8  -7.9
           3150.   1.0   88.7  93.2  94.5  94.1  92.4  89.5  85.7  81.0  75.4  68.8  61.4  53.0  43.7  33.3  21.5   8.1  -8.6
           4000.   1.0   88.3  92.7  94.0  93.5  91.7  88.8  85.0  80.2  74.5  67.9  60.4  52.0  42.5  32.0  20.2   6.7 -10.0
           5000.   1.0   87.5  91.9  93.1  92.5  90.7  87.7  83.8  78.9  73.2  66.5  58.9  50.4  40.9  30.4  18.5   4.9 -11.9
           6300.   1.0   86.5  90.8  91.9  91.2  89.3  86.2  82.2  77.3  71.4  64.6  57.0  48.4  38.8  28.1  16.2   2.5 -14.5
           8000.   1.0   85.3  89.5  90.4  89.6  87.6  84.4  80.2  75.2  69.2  62.3  54.5  45.8  36.1  25.3  13.2  -0.6 -17.7
          10000.   1.0   84.2  88.2  89.0  88.1  85.9  82.5  78.3  73.0  66.9  59.9  51.9  43.1  33.2  22.3  10.1  -3.9 -21.1
        '''

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        gen = FileParser()
        gen.set_file(self.filename)

        # whitespace delim; with end field
        gen.set_delimiters(' \t')
        gen.mark_anchor('Anchor')
        val = gen.transfer_2Darray(3, 2, 26, 19)
        self.assertEqual(val[0, 1], 30.0)
        self.assertEqual(val[0, 17], -63.7)
        self.assertEqual(val[1, 17], -57.2)
        self.assertEqual(val[23, 17], -21.1)
        self.assertEqual(val.shape[0], 24)
        self.assertEqual(val.shape[1], 18)

        # whitespace delim; no end field
        val = gen.transfer_2Darray(3, 2, 26)
        self.assertEqual(val[0, 1], 30.0)
        self.assertEqual(val[23, 17], -21.1)
        self.assertEqual(val.shape[0], 24)
        self.assertEqual(val.shape[1], 18)

        # column delim; with end field
        gen.set_delimiters('columns')
        val = gen.transfer_2Darray(3, 19, 26, 125)
        self.assertEqual(val[0, 1], 30.0)
        self.assertEqual(val[0, 17], -63.7)
        self.assertEqual(val[1, 17], -57.2)
        self.assertEqual(val[23, 17], -21.1)
        self.assertEqual(val.shape[0], 24)
        self.assertEqual(val.shape[1], 18)

        # column delim; no end field
        val = gen.transfer_2Darray(3, 19, 26)
        self.assertEqual(val[0, 1], 30.0)
        self.assertEqual(val[0, 17], -63.7)
        self.assertEqual(val[1, 17], -57.2)
        self.assertEqual(val[23, 17], -21.1)
        self.assertEqual(val.shape[0], 24)
        self.assertEqual(val.shape[1], 18)

        # make sure single line works
        gen.set_delimiters(' \t')
        val = gen.transfer_2Darray(5, 3, 5, 5)
        self.assertEqual(val[0, 2], 49.1)

        # Small block read
        val = gen.transfer_2Darray(7, 3, 9, 6)
        self.assertEqual(val[0, 0], 53.6)
        self.assertEqual(val[2, 0], 63.4)

        # Error messages for bad values
        try:
            gen.transfer_2Darray(7, 3, 9, 1)
        except ValueError, err:
            msg = "fieldend must be greater than fieldstart"
            self.assertEqual(str(err), msg)
Ejemplo n.º 11
0
    def test_output_parse_array(self):

        data = "Anchor\n" + \
               "10 20 30 40 50 60 70 80\n" + \
               "11 21 31 41 51 61 71 81\n" + \
               "Key a b c d e\n"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        gen = FileParser()
        gen.set_file(self.filename)
        gen.set_delimiters(' ')

        gen.mark_anchor('Anchor')
        val = gen.transfer_array(1, 1, 1, 8)
        self.assertEqual(val[0], 10)
        self.assertEqual(val[7], 80)
        val = gen.transfer_array(1, 5, 2, 6)
        self.assertEqual(val[0], 50)
        self.assertEqual(val[9], 61)
        gen.mark_anchor('Key')
        val = gen.transfer_array(0, 2, 0, 6)
        self.assertEqual(val[4], 'e')
        val = gen.transfer_array(0, 2, fieldend=6)
        self.assertEqual(val[4], 'e')

        # Now, let's try column delimiters
        gen.reset_anchor()
        gen.mark_anchor('Anchor')
        gen.set_delimiters('columns')
        val = gen.transfer_array(1, 7, 1, 15)
        self.assertEqual(val[0], 30)
        self.assertEqual(val[2], 50)
        val = gen.transfer_array(1, 10, 2, 18)
        self.assertEqual(val[0], 40)
        self.assertEqual(val[5], 61)
        val = gen.transfer_array(3, 5, 3, 10)
        self.assertEqual(val[0], 'a b c')

        try:
            gen.transfer_array(1, 7, 1)
        except ValueError, err:
            msg = "fieldend is missing, currently required"
            self.assertEqual(str(err), msg)
Ejemplo n.º 12
0
    def execute(self):
        """Runs the NastranComponent.

        We are overiding ExternalCode's execute function. First, we
        setup the input file (by running NastranReplacer and then
        NastranMaker). Next, we run Nastran by calling our
        parent's execute function. Finally, we parse the data
        and set the output variables given to us.

        RuntimeError
            The component relies on ExternalCode which can throw all
            sorts of RuntimeError-like exceptions (RunStopped,
            RunInterrupted also included).
            
        Filesystem-type Errors
            NastranComponent makes a temporary directory with mkdtemp
            in the temp module. If that fails, the error just
            propagates up.


        While there are no explicit parameters or return values for this
        function, it gets all the input it needs from the design
        variables that are connected to the subclass of NastranComponent.
        This should be described pretty well in the :ref:`documentation<NastranComponent>`.

        """
        # We are going to keep track of all the ways we
        # can manage input/output:
        #  - the crude way (NastranReplacer, NastranOutput)
        #    correspond to input_variables, output_variables
        #  - the better way (NastranMaker, NastranParser)
        #    correspond to smart_replacements and grid_outputs

        # all of these are {"traitname" : trait}
        input_variables = {}
        smart_replacements = {}
        output_variables = {}
        grid_outputs = {}

        for name, trait in self.traits().iteritems():
            if trait.iotype == "in":
                # nastran_var is a variable that should be replaced
                if trait.nastran_var:
                    # if the variable is longer than seven characters
                    # it won't fit in the nastran file, since the limit
                    # there is 8 characters (%xxxxxxx)
                    if len(trait.nastran_var) > 7:
                        raise ValueError("The variable " + trait.nastran + \
                                         " is too long to be a variable")
                    input_variables[name] = trait

                # it could also be a smart replacement, but we'll have
                # to specify the card, id, and fieldnum
                if trait.nastran_card and trait.nastran_id and trait.nastran_fieldnum:
                    smart_replacements[name] = trait

                elif trait.nastran_card or trait.nastran_id or trait.nastran_fieldnum:
                    raise RuntimeError("You specified at least one of " + \
                                    "nastran_card, nastran_id, and " + \
                                    "nastran_fieldnum, but you did " + \
                                    "not specify all of them. You " + \
                                    "most probably mistyped.")

            elif trait.iotype == "out":
                # if we want to supply a function that will parse
                # out the wanted information from the output object
                # and the fileparser, then this
                if trait.nastran_func:
                    output_variables[name] = trait

                # this is the grid method of accessing. We have to
                # specify a header, row, and attribute and
                # the output variable will be set to that value
                if trait.nastran_header and trait.nastran_constraints and trait.nastran_columns:
                    grid_outputs[name] = trait
                elif trait.nastran_header or trait.nastran_constraints or trait.nastran_columns:
                    raise RuntimeError("You specified at least one of " + \
                                    "nastran_header, nastran_constrains"+\
                                    ", and nastran_columns, but you " + \
                                    "did not specify all them. You " + \
                                    "most probably mistyped")

        # let's do our work in a tmp dir
        tmpdir = mkdtemp(dir=self.output_tempdir_dir)
        tmppath = path.join(tmpdir, "input.bdf")
        tmpfh = open(tmppath, "w")

        # raw nastran file supplied by user
        fh = open(self.nastran_filename, "r")

        # note: fh.readlines() won't work because it doesn't
        # strip the newline at the end for you. So whatever,
        # we'll just use split on newlines.
        nastran_text = fh.read().split("\n")
        fh.close()

        # replace the variables in the nastran text using Replacer
        replacer = NastranReplacer(nastran_text)
        varname2value = {}
        for name, trait in input_variables.iteritems():
            varname2value[trait.nastran_var] = getattr(self, name)
        replacer.replace(varname2value)
        nastran_text = replacer.text

        # use nastran maker to intelligently replace
        # values in cards
        maker = NastranMaker(nastran_text)
        for name, trait in smart_replacements.iteritems():
            value = getattr(self, name)
            maker.set(trait.nastran_card, trait.nastran_id,
                      trait.nastran_fieldnum, value)
        self.nastran_maker_hook(maker)
        maker.write_to_file(tmpfh, 10001)

        tmpfh.close()

        # what is the new file called?
        self.output_filename = path.join(tmpdir, "input.out")

        # perhaps this should be logged, or something
        print self.output_filename

        # Then we run the nastran file
        if self.nastran_command == 'python':  # True when using fake_nastran.py
            self.command = [
                self.nastran_command, self.nastran_command_args[0], tmppath
            ]
            self.command.extend(self.nastran_command_args[1:])
        else:
            self.command = [self.nastran_command, tmppath]
            self.command.extend(self.nastran_command_args)
        self.command.extend(["batch=no", "out=" + tmpdir, "dbs=" + tmpdir])

        # This calls ExternalCode's execute which will run
        # the nastran command via subprocess
        super(NastranComponent, self).execute()

        # And now we parse the output

        filep = FileParser()
        filep.set_file(self.output_filename)
        filep.set_delimiters(" ")

        # Before we start, we want to make sure we aren't
        # dealing with a failed run. So we search for "FATAL"
        for line in filep.data:
            if "FATAL" in line:
                raise RuntimeError("There was a problem with " + \
                                   "Nastran. It failed to run " + \
                                   "correctly. If you want to see " +\
                                   "the output, check out " + \
                                   self.output_filename)

        for output_name, output_trait in output_variables.iteritems():
            # We run trait.nastran_func on filep and get the
            # final value we want
            setattr(self, output_name, output_trait.nastran_func(filep))

        # This is the grid parser.
        self.parser = NastranParser(filep.data)
        self.parser.parse()

        for name, trait in grid_outputs.iteritems():
            header = trait.nastran_header
            subcase = trait.nastran_subcase
            constraints = trait.nastran_constraints
            columns = trait.nastran_columns
            result = self.parser.get(header, subcase, \
                                     constraints, columns)

            # nastran_{row,column} might be kinda silly
            # in most cases, the user will probably just call
            # self.parser.get on her own
            nastran_row = trait.nastran_row
            nastran_column = trait.nastran_column
            row = nastran_row or 0
            col = nastran_column or 0

            # Now we'll try to guess the conversion we should
            # perform by inspecting the type of trait that
            # is requesting this value
            converter = lambda x: x
            type_understood_as = "unsure"
            if isinstance(trait.trait_type, Float):
                converter = float
                type_understood_as = "float"
            elif isinstance(trait.trait_type, Int):
                converter = lambda x: int(float(x))
                type_understood_as = "int"
            elif isinstance(trait.trait_type, Array):
                # we aren't actually going to return the entire
                # grid because you should use parser if you
                # want to do that.
                converter = lambda x: [x]
                type_understood_as = "array"

            try:
                setattr(self, name, converter(result[row][col]))
            except ValueError, ve:
                print >> sys.stderr, "Unable to convert string " + \
                      result[row][col] +  " to " + type_understood_as
                raise
Ejemplo n.º 13
0
    def test_output_parse_same_anchors(self):

        data = "CQUAD4 1 3.456\n" + \
               "CQUAD4 2 4.123\n" + \
               "CQUAD4 3 7.222\n" + \
               "CQUAD4 4\n"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        gen = FileParser()
        gen.set_file(self.filename)
        gen.set_delimiters(' ')

        gen.mark_anchor('CQUAD4')
        val = gen.transfer_var(0, 3)
        self.assertEqual(val, 3.456)

        gen.mark_anchor('CQUAD4')
        val = gen.transfer_var(0, 3)
        self.assertEqual(val, 4.123)

        gen.mark_anchor('CQUAD4', 2)
        val = gen.transfer_var(0, 2)
        self.assertEqual(val, 4)

        gen.reset_anchor()

        gen.mark_anchor('CQUAD4', -1)
        val = gen.transfer_var(0, 2)
        self.assertEqual(val, 4)

        gen.mark_anchor('CQUAD4', -1)
        val = gen.transfer_var(0, 3)
        self.assertEqual(val, 7.222)

        gen.mark_anchor('CQUAD4', -2)
        val = gen.transfer_var(0, 3)
        self.assertEqual(val, 4.123)
Ejemplo n.º 14
0
 def load_model(self, filename="test.input"):
     """Loads an existing HSRNOISE input file."""
    
     infile = FileParser()
     infile.set_file(filename)
     
     infile.mark_anchor('$GEOM')
     self.HMIC = float(infile.transfer_keyvar("HMIC", 2))
     self.SL = float(infile.transfer_keyvar("SL", 2))
     infile.mark_anchor('$FLIPATH')
     self.ALTEVO = float(infile.transfer_keyvar("ALTEVO", 2))
         
     self.HMIC = int(infile.transfer_keyvar("JETMETHOD", 2))
     
     infile.mark_anchor('$JET1IN')
     self.geo_in.Apri = float(infile.transfer_keyvar("APRI", 2))
     self.geo_in.Asec = float(infile.transfer_keyvar("ASEC", 2))
     self.ATHP = float(infile.transfer_keyvar("ATHP", 2))
     self.DELMIX = float(infile.transfer_keyvar("DELMIX", 2))
     self.DELPE = float(infile.transfer_keyvar("DELPE", 2))
     self.DELPI = float(infile.transfer_keyvar("DELPI", 2))
     self.geo_in.ChuteAngles = float(infile.transfer_keyvar("DIVANG", 2))
     self.geo_in.AR = float(infile.transfer_keyvar("EJASP", 2))
     self.EJD = float(infile.transfer_keyvar("EJD", 2))
     self.geo_in.length = float(infile.transfer_keyvar("EJL", 2))
     self.EJLIN = float(infile.transfer_keyvar("EJLIN", 2))
     self.FLIN = float(infile.transfer_keyvar("FLIN", 2))
     self.geo_in.LhMh = float(infile.transfer_keyvar("PEN", 2))
     self.PLUGD = float(infile.transfer_keyvar("PLUGD", 2))
     self.PSI0 = float(infile.transfer_keyvar("PSI0", 2))
     self.SPOKE = float(infile.transfer_keyvar("SPOKE", 2))
     self.flow_in.pri.Tt = float(infile.transfer_keyvar("TPRI", 2))
     self.flow_in.sec.Tt = float(infile.transfer_keyvar("TSEC", 2))
     self.flow_in.pri.Vel = float(infile.transfer_keyvar("VPRI", 2))
     self.flow_in.sec.Vel = float(infile.transfer_keyvar("VSEC", 2))
     self.flow_in.pri.W = float(infile.transfer_keyvar("WPRI", 2))
     self.flow_in.sec.W = float(infile.transfer_keyvar("WSEC", 2))
     self.geo_in.AeAt = float(infile.transfer_keyvar("XMAR", 2))
     
     infile.mark_anchor('$JET2IN')
     self.APT = float(infile.transfer_keyvar("APT", 2))
     self.AS = float(infile.transfer_keyvar("AS", 2))
     self.CER = float(infile.transfer_keyvar("CER", 2))
     self.DHP = float(infile.transfer_keyvar("DHP", 2))
     self.DL = float(infile.transfer_keyvar("DL", 2))
     self.DM = float(infile.transfer_keyvar("DM", 2))
     self.FPK = float(infile.transfer_keyvar("FPK", 2))
     self.GAMMAC = float(infile.transfer_keyvar("GAMMAC", 2))
     self.HEX = float(infile.transfer_keyvar("HEX", 2))
     self.IEX = int(infile.transfer_keyvar("IEX", 2))
     self.ISUPPR = int(infile.transfer_keyvar("ISUPPR", 2))
     self.LBE = float(infile.transfer_keyvar("LBE", 2))
     self.LBS = float(infile.transfer_keyvar("LBS", 2))
     self.LE = float(infile.transfer_keyvar("LE", 2))
     self.LPE = float(infile.transfer_keyvar("LPE", 2))
     self.LPS = float(infile.transfer_keyvar("LPS", 2))
     self.MMC = float(infile.transfer_keyvar("MMC", 2))
     self.MPD = float(infile.transfer_keyvar("MPD", 2))
     self.PC = float(infile.transfer_keyvar("PC", 2))
     self.PEN = float(infile.transfer_keyvar("PEN", 2))
     self.SAR = float(infile.transfer_keyvar("SAR", 2))
     self.SUPPK = float(infile.transfer_keyvar("SUPPK", 2))
     self.TC = float(infile.transfer_keyvar("TC", 2))
     self.TEX = float(infile.transfer_keyvar("TEX", 2))
     self.VEX = float(infile.transfer_keyvar("VEX", 2))
     self.WEX = float(infile.transfer_keyvar("WEX", 2))
     self.WSWP = float(infile.transfer_keyvar("WSWP", 2))
     
     # Set derived values down in the variable trees.
     self.LinFrac = self.EJLIN/self.geo_in.length
     self.phi = degrees(arcsin(0.1*self.SL))
     self.geo_in.Num_Lobes = self.SPOKE
     self.geo_in.Aexit = pi*(0.5*self.EJD)**2
     
     # Where does gamma come from?
     self.flow_in.gamma = 1.4
     
     # use fixed-point iteration to solve for mach 
     mach = 1.0
     gam = self.flow_in.gamma
     apri = self.geo_in.Apri
     athp = self.ATHP
     
     term1 = ((gam+1)/2)**((-gam-1)/(2*(gam-1)))
     exp1 = ((gam+1)/(2*(gam-1)))
     
     for i in range(135):
         mach = athp/(apri/(term1*(1+(gam-1)/2*mach**2)**exp1))
         
     
     self.flow_in.pri.Mach = mach
Ejemplo n.º 15
0
    def execute(self):

        super(Comp_Plate, self).execute()

        parser = FileParser()
        parser.set_file(self.nastran_filename)

        self.comp_elm_dict = {}
        parser.reset_anchor()
        for cquad4 in range(1,26):
            parser.mark_anchor("CQUAD4")
            elmtype = parser.transfer_var(0, 1)
            elmid = parser.transfer_var(0, 2)
            pid = parser.transfer_var(0, 3)

            if pid not in self.comp_elm_dict:
                self.comp_elm_dict[ pid ] = []

            self.comp_elm_dict[pid].append( elmid )

        max_minor_strain_by_pid, max_major_strain_by_pid = self.calculate_max_strains()

        self.property1_max_major_strain = max_major_strain_by_pid[ 801 ]
        self.property2_max_major_strain = max_major_strain_by_pid[ 802 ]
        self.property3_max_major_strain = max_major_strain_by_pid[ 803 ]

        self.property1_max_minor_strain = max_minor_strain_by_pid[ 801 ]
        self.property2_max_minor_strain = max_minor_strain_by_pid[ 802 ]
        self.property3_max_minor_strain = max_minor_strain_by_pid[ 803 ]

        # Calculate the maximum strain (max(major,minor)) for each property 
        self.property1_max_major_minor_strain = max( self.property1_max_major_strain, self.property1_max_minor_strain )
        self.property2_max_major_minor_strain = max( self.property2_max_major_strain, self.property2_max_minor_strain )
        self.property3_max_major_minor_strain = max( self.property3_max_major_strain, self.property3_max_minor_strain )
Ejemplo n.º 16
0
    def parse_output(self,FabriOrSub):
        """Parses the DREA output file and extracts data."""
        
        infile = FileParser()
        infile.set_file('ejectd.out')
        infile.mark_anchor('EJECTOR SOLUTION')

        if FabriOrSub == 'Fabri':
            self.GrossThrust = infile.transfer_keyvar("SUPERSONIC GROSS THRUST (OVERALL)=", 1)
            self.ExitMassFlow = infile.transfer_keyvar("SUPERSONIC EXIT MASS FLOW RATE=", 1)
            self.ExitVelocity = infile.transfer_keyvar("SUP VELOCITY=", 1)
            self.ExitMach = infile.transfer_keyvar("SUPERSONIC MACH=", 1)
            self.ExitStaticTemp = infile.transfer_keyvar("SUP TEMPERATURE=", 1)
            self.ExitTotalTemp = infile.transfer_keyvar("SUPERSONIC TOTAL TEMPERATURE=", 1)
            self.CFG = infile.transfer_keyvar("SUPERSONIC CFG=", 1)
        if FabriOrSub == 'Subsonic':
            self.GrossThrust = infile.transfer_keyvar("SUBSONIC GROSS THRUST (OVERALL)=", 1)
            self.ExitMassFlow = infile.transfer_keyvar("SUBSONIC EXIT MASS FLOW RATE=", 1)
            self.ExitVelocity = infile.transfer_keyvar("SUB VELOCITY=", 1)
            self.ExitMach = infile.transfer_keyvar("SUBSONIC MACH=", 1)
            self.ExitStaticTemp = infile.transfer_keyvar("SUB TEMPERATURE=", 1)
            self.ExitTotalTemp = infile.transfer_keyvar("SUBSONIC TOTAL TEMPERATURE=", 1)
            self.CFG = infile.transfer_keyvar("SUBSONIC CFG=", 1)
            
        self.flow_out.pri.Vel = infile.transfer_keyvar("U1D=",1)
        self.flow_out.sec.Vel = infile.transfer_keyvar("U2D=",1)
        self.flow_out.pri.W = infile.transfer_keyvar("RMD1D=",1)*2*32.17405 #Doubled since half of the area is used
        self.flow_out.sec.W = infile.transfer_keyvar("RMD2D=",1)*2*32.17405 #Doubled since half of the area is used
        self.PumpingRatio = infile.transfer_keyvar("PUMPING RATIO W2/W1=",1)
        self.flow_out.sec.Mach = infile.transfer_keyvar("RM2=", 1)
        self.DegreeOfMixing = infile.transfer_keyvar("DEGREE OF MIXING IN PRESSURE CONSTRAINT",0,rowoffset=1)
        self.NPR = infile.transfer_keyvar("NPR=",1)
Ejemplo n.º 17
0
    def load_model(self, control_input='control.in',
                         flocond_input='flocond.in',
                         expnd_input='expnd.in',
                         zrdmix_input='zrdmix.in',
                         hwall_input='hwall.in'):
        '''Reads in an existing set of input files and populates the model.'''
        
        ignore = ['ist', 'ifab']
        ct = Namelist(self)
        ct.set_filename(control_input)
        ct.parse_file()
        ct.load_model(ignore=ignore)

        ignore = ['p01d', 'p02d', 't01d', 't02d', 'rm1', 'rm2', 'gam', 'pinf',
                  'a1d', 'a2d', 'a3d']
        fc = Namelist(self)
        fc.set_filename(flocond_input)
        fc.parse_file()
        fc.load_model(ignore=ignore)
        self.flow_in.pri.Pt = fc.find_card('floc', 'p01d')
        self.flow_in.sec.Pt = fc.find_card('floc', 'p02d')
        self.flow_in.pri.Tt = fc.find_card('floc', 't01d')
        self.flow_in.sec.Tt = fc.find_card('floc', 't02d')
        self.flow_in.pri.Mach = fc.find_card('floc', 'rm1')
        self.flow_in.sec.Mach = fc.find_card('floc', 'rm2')
        self.flow_in.gamma = fc.find_card('floc', 'gam')
        self.flow_in.Pstatic = fc.find_card('floc', 'pinf')
        a1d = fc.find_card('floc', 'a1d')
        a2d = fc.find_card('floc', 'a2d')
        a3d = fc.find_card('floc', 'a3d')
        
        ep = Namelist(self)
        ep.set_filename(expnd_input)
        ep.parse_file()
        ep.load_model()
        
        ignore = ['RLD', 'H0LM', 'H0HY', 'ALP1', 'ALP2', 'BWID']
        zr = Namelist(self)
        zr.set_filename(zrdmix_input)
        zr.parse_file()
        zr.load_model(ignore=ignore)
        self.geo_in.length = zr.find_card('zrd', 'RLD')
        self.geo_in.LhWave = zr.find_card('zrd', 'H0LM')
        self.geo_in.LhMh = zr.find_card('zrd', 'H0HY')
        self.geo_in.ChuteAngles = zr.find_card('zrd', 'ALP1')
        #self.geo_in.ChuteAngles = zr.find_card('zrd', 'ALP2')
        BWID = zr.find_card('zrd', 'BWID')

        parser = FileParser()
        parser.set_file(hwall_input)
        parser.set_delimiters(", ")
        nrow = parser.transfer_var(0, 1)
        geom = zeros((nrow, 2), 'd')
        for index in range(nrow):
            geom[index, :] = parser.transfer_array(1+index, 1, 1+index, 2)
            
        self.geom = geom
        
        # Reverse area calculations for AsAp, AeAt and AR
        # Note that DREA only uses half the area as it assumes a plane of symmetry
        self.geo_in.Apri = 2.0*a1d
        self.geo_in.AsAp = 2.0*a2d/self.geo_in.Apri
        self.geo_in.Asec = self.geo_in.AsAp*self.geo_in.Apri
        self.geo_in.AeAt = 2.0*a3d/(self.geo_in.Apri+self.geo_in.Asec)
        self.geo_in.AR = BWID*BWID/(self.geo_in.Apri+self.geo_in.Asec)
        
        #self.geo_in.length = self.geom[-1, 0]
        self.geo_in.width = 0.5*(self.geo_in.Apri + self.geo_in.Asec)/self.geom[0,1]
        self.geo_in.Aexit = 2.0*self.geom[-1,1]*self.geo_in.width  
Ejemplo n.º 18
0
    def parse_output(self):
        """Parses the HSRNOISE output file and extracts data."""
        
        outfile = FileParser()
        outfile.set_file('test.output')
        
        outfile.mark_anchor("JN8C4 JET NOISE MODULE")
        outfile.mark_anchor("TOTAL")
        self.thetas = outfile.transfer_array(4,2,4,18)
        self.Freq = outfile.transfer_2Darray(7,1,30,1)        
        self.SPL = outfile.transfer_2Darray(7,2,30,18)
        outfile.mark_anchor("DBA")
        self.OASPL = outfile.transfer_array(-1, 2, -1, 18)
        self.OASPL30 = outfile.transfer_var(-1, 4)
        self.OASPL60 = outfile.transfer_var(-1, 7)
        self.OASPL90 = outfile.transfer_var(-1, 10)
        self.OASPL120 = outfile.transfer_var(-1, 13)
        self.OASPL150 = outfile.transfer_var(-1, 16)

        outfile.mark_anchor("EPNL SUMMARY")
        self.TotalEPNL = outfile.transfer_var(9, 2)
        self.TotalMaxPNLT = outfile.transfer_var(9, 5)
        self.JetEPNL = outfile.transfer_var(8, 2)
Ejemplo n.º 19
0
    def test_output_parse_keyvar(self):

        data = "Anchor\n" + \
               " Key1 1 2 3.7 Test 1e65\n" + \
               " Key1 3 4 3.2 ibg 0.0003\n" + \
               " Key1 5 6 6.7 Tst xxx\n"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        gen = FileParser()
        gen.set_file(self.filename)
        gen.set_delimiters(' ')

        gen.mark_anchor('Anchor')
        val = gen.transfer_keyvar('Key1', 3)
        self.assertEqual(val, 3.7)
        val = gen.transfer_keyvar('Key1', 4, -2)
        self.assertEqual(val, 'ibg')
        val = gen.transfer_keyvar('Key1', 4, -2, -1)
        self.assertEqual(val, 'Test')

        try:
            gen.transfer_keyvar('Key1', 4, 0)
        except ValueError, err:
            msg = "The value for occurrence must be a nonzero integer"
            self.assertEqual(str(err), msg)
Ejemplo n.º 20
0
    def test_output_parse(self):

        data = "Junk\n" + \
                   "Anchor\n" + \
                   " A 1, 2 34, Test 1e65\n" + \
                   " B 4 Stuff\n" + \
                   "Anchor\n" + \
                   " C 77 False NaN 333.444\n" + \
                   " 1,2,3,4,5\n" + \
                   " Inf 1.#QNAN -1.#IND\n"

        outfile = open(self.filename, 'w')
        outfile.write(data)
        outfile.close()

        gen = FileParser()
        gen.set_file(self.filename)
        gen.set_delimiters(' ')

        gen.mark_anchor('Anchor')
        val = gen.transfer_var(1, 1)
        self.assertEqual(val, 'A')
        gen.reset_anchor()
        val = gen.transfer_var(3, 2)
        self.assertEqual(val, 4)
        self.assertEqual(type(val), int)
        gen.mark_anchor('Anchor',2)
        val = gen.transfer_var(1, 4)
        self.assertEqual(isnan(val), True)
        val = gen.transfer_var(3, 1)
        self.assertEqual(isinf(val), True)
        val = gen.transfer_var(3, 2)
        self.assertEqual(isnan(val), True)
        val = gen.transfer_var(3, 3)
        self.assertEqual(isnan(val), True)
        val = gen.transfer_line(-1)
        self.assertEqual(val, ' B 4 Stuff')

        # Now, let's try column delimiters
        gen.set_delimiters('columns')
        gen.mark_anchor('Anchor',-1)
        val = gen.transfer_var(1, 8, 10)
        self.assertEqual(val, 'als')
        val = gen.transfer_var(1, 17)
        self.assertEqual(val, 333.444)

        # Test some errors
        try:
            gen.mark_anchor('C 77', 3.14)
        except ValueError, err:
            msg = "The value for occurrence must be an integer"
            self.assertEqual(str(err), msg)
Ejemplo n.º 21
0
    def parse_output(self, FabriOrSub):
        """Parses the DREA output file and extracts data."""

        infile = FileParser()
        infile.set_file('ejectd.out')
        infile.mark_anchor('EJECTOR SOLUTION')

        if FabriOrSub == 'Fabri':
            self.GrossThrust = infile.transfer_keyvar(
                "SUPERSONIC GROSS THRUST (OVERALL)=", 1)
            self.ExitMassFlow = infile.transfer_keyvar(
                "SUPERSONIC EXIT MASS FLOW RATE=", 1)
            self.ExitVelocity = infile.transfer_keyvar("SUP VELOCITY=", 1)
            self.ExitMach = infile.transfer_keyvar("SUPERSONIC MACH=", 1)
            self.ExitStaticTemp = infile.transfer_keyvar("SUP TEMPERATURE=", 1)
            self.ExitTotalTemp = infile.transfer_keyvar(
                "SUPERSONIC TOTAL TEMPERATURE=", 1)
            self.CFG = infile.transfer_keyvar("SUPERSONIC CFG=", 1)
        if FabriOrSub == 'Subsonic':
            self.GrossThrust = infile.transfer_keyvar(
                "SUBSONIC GROSS THRUST (OVERALL)=", 1)
            self.ExitMassFlow = infile.transfer_keyvar(
                "SUBSONIC EXIT MASS FLOW RATE=", 1)
            self.ExitVelocity = infile.transfer_keyvar("SUB VELOCITY=", 1)
            self.ExitMach = infile.transfer_keyvar("SUBSONIC MACH=", 1)
            self.ExitStaticTemp = infile.transfer_keyvar("SUB TEMPERATURE=", 1)
            self.ExitTotalTemp = infile.transfer_keyvar(
                "SUBSONIC TOTAL TEMPERATURE=", 1)
            self.CFG = infile.transfer_keyvar("SUBSONIC CFG=", 1)

        self.flow_out.pri.Vel = infile.transfer_keyvar("U1D=", 1)
        self.flow_out.sec.Vel = infile.transfer_keyvar("U2D=", 1)
        self.flow_out.pri.W = infile.transfer_keyvar(
            "RMD1D=", 1) * 2  # Doubled since half of the area is used
        self.flow_out.sec.W = infile.transfer_keyvar(
            "RMD2D=", 1) * 2  # Doubled since half of the area is used
        self.PumpingRatio = infile.transfer_keyvar("PUMPING RATIO W2/W1=", 1)
        self.flow_out.sec.Mach = infile.transfer_keyvar("RM2=", 1)
        self.DegreeOfMixing = infile.transfer_keyvar(
            "DEGREE OF MIXING IN PRESSURE CONSTRAINT", 0, rowoffset=1)
        self.NPR = infile.transfer_keyvar("NPR=", 1)