def test_linear_analysis_error(self):

        # test fwd mode
        prob = om.Problem()
        model = prob.model

        # takes 6 iterations normally
        linear_solver = om.LinearBlockGS(maxiter=2, err_on_non_converge=True)

        model.add_subsystem(
            'sub',
            SellarDerivatives(nonlinear_solver=om.NonlinearRunOnce(),
                              linear_solver=linear_solver))
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)

        prob.setup(mode='fwd')
        prob.set_solver_print(level=2)

        # test if the analysis error is raised properly on all procs
        try:
            prob.run_model()
        except om.AnalysisError as err:
            self.assertEqual(
                str(err),
                "Solver 'LN: LNBGS' on system 'sub' failed to converge in 2 iterations."
            )
        else:
            self.fail("expected AnalysisError")

        # test rev mode
        prob = om.Problem()
        model = prob.model

        # takes 6 iterations normally
        linear_solver = om.LinearBlockGS(maxiter=2, err_on_non_converge=True)

        model.add_subsystem(
            'sub',
            SellarDerivatives(nonlinear_solver=om.NonlinearRunOnce(),
                              linear_solver=linear_solver))
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)

        prob.setup(mode='rev')
        prob.set_solver_print(level=2)

        # test if the analysis error is raised properly on all procs
        try:
            prob.run_model()
        except om.AnalysisError as err:
            self.assertEqual(
                str(err),
                "Solver 'LN: LNBGS' on system 'sub' failed to converge in 2 iterations."
            )
        else:
            self.fail("expected AnalysisError")
    def test_circuit_voltage_source(self):
        import openmdao.api as om
        from openmdao.test_suite.scripts.circuit_analysis import Circuit

        p = om.Problem()
        model = p.model

        model.add_subsystem('ground', om.IndepVarComp('V', 0., units='V'))

        # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source
        # model.add_subsystem('source', om.IndepVarComp('I', 0.1, units='A'))
        model.add_subsystem('batt', om.IndepVarComp('V', 1.5, units='V'))
        bal = model.add_subsystem('batt_balance', om.BalanceComp())
        bal.add_balance('I', units='A', eq_units='V')

        model.add_subsystem('circuit', Circuit())
        model.add_subsystem('batt_deltaV', om.ExecComp('dV = V1 - V2', V1={'units':'V'},
                                                       V2={'units':'V'}, dV={'units':'V'}))

        # current into the circuit is now the output state from the batt_balance comp
        model.connect('batt_balance.I', 'circuit.I_in')
        model.connect('ground.V', ['circuit.Vg','batt_deltaV.V2'])
        model.connect('circuit.n1.V', 'batt_deltaV.V1')

        # set the lhs and rhs for the battery residual
        model.connect('batt.V', 'batt_balance.rhs:I')
        model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

        p.setup()

        ###################
        # Solver Setup
        ###################

        # change the circuit solver to RunOnce because we're
        # going to converge at the top level of the model with newton instead
        p.model.circuit.nonlinear_solver = om.NonlinearRunOnce()
        p.model.circuit.linear_solver = om.LinearRunOnce()

        # Put Newton at the top so it can also converge the new BalanceComp residual
        newton = p.model.nonlinear_solver = om.NewtonSolver()
        p.model.linear_solver = om.DirectSolver()
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 20
        newton.options['solve_subsystems'] = True
        newton.linesearch = om.ArmijoGoldsteinLS()
        newton.linesearch.options['maxiter'] = 10
        newton.linesearch.options['iprint'] = 2

        # set initial guesses from the current source problem
        p['circuit.n1.V'] = 9.8
        p['circuit.n2.V'] = .7

        p.run_model()

        assert_near_equal(p['circuit.n1.V'], 1.5, 1e-5)
        assert_near_equal(p['circuit.n2.V'], 0.65113362, 1e-5)
        assert_near_equal(p['circuit.R1.I'], 0.015, 1e-5)
        assert_near_equal(p['circuit.R2.I'], 8.48866375e-05, 1e-5)
        assert_near_equal(p['circuit.D1.I'], 8.48866375e-05, 1e-5)
    def test_aitken(self):
        prob = om.Problem()
        model = prob.model

        aitken = om.LinearBlockGS()
        aitken.options['use_aitken'] = True
        aitken.options['err_on_non_converge'] = True

        # It takes 6 iterations without Aitken.
        aitken.options['maxiter'] = 4

        sub = model.add_subsystem(
            'sub',
            SellarDerivatives(nonlinear_solver=om.NonlinearRunOnce(),
                              linear_solver=aitken))
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)

        prob.setup(mode='fwd')
        prob.set_solver_print(level=0)
        prob.run_model()

        assert_near_equal(prob.get_val('sub.y1'), 25.58830273, .00001)
        assert_near_equal(prob.get_val('sub.y2'), 12.05848819, .00001)

        prob = om.Problem()
        model = prob.model

        aitken = om.LinearBlockGS()
        aitken.options['use_aitken'] = True
        aitken.options['err_on_non_converge'] = True

        # It takes 6 iterations without Aitken.
        aitken.options['maxiter'] = 4

        sub = model.add_subsystem(
            'sub',
            SellarDerivatives(nonlinear_solver=om.NonlinearRunOnce(),
                              linear_solver=aitken))
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)

        prob.setup(mode='rev')
        prob.set_solver_print(level=0)
        prob.run_model()

        assert_near_equal(prob.get_val('sub.y1'), 25.58830273, .00001)
        assert_near_equal(prob.get_val('sub.y2'), 12.05848819, .00001)
    def test_converge_diverge_groups(self):
        # Test derivatives for converge-diverge-groups topology.
        prob = om.Problem()
        model = prob.model = ConvergeDivergeGroups()

        model.linear_solver = om.ScipyKrylov()
        model.nonlinear_solver = om.NonlinearRunOnce()

        model.g1.nonlinear_solver = om.NonlinearRunOnce()
        model.g1.g2.nonlinear_solver = om.NonlinearRunOnce()
        model.g3.nonlinear_solver = om.NonlinearRunOnce()

        prob.set_solver_print(level=0)
        prob.setup(check=False, mode='fwd')
        prob.run_model()

        # Make sure value is fine.
        assert_rel_error(self, prob['c7.y1'], -102.7, 1e-6)
示例#5
0
def initialize_problem(Analysis_Level):
    
    # Initialize blade design
    refBlade = ReferenceBlade()
    refBlade.verbose  = True
    refBlade.NINPUT       = 200
    Nsection_Tow          = 19
    refBlade.NPTS         = 200
    refBlade.spar_var     = ['Spar_cap_ss', 'Spar_cap_ps'] # SS, then PS
    refBlade.te_var       = 'TE_reinforcement'
    refBlade.validate     = False
    refBlade.fname_schema = fname_schema
    blade = refBlade.initialize(fname_input)
    
    FASTpref                        = {}
    FASTpref['Analysis_Level']      = Analysis_Level
    # Set FAST Inputs
    if Analysis_Level >= 1:
        # File management
        FASTpref['FAST_ver']            = 'OpenFAST'
        FASTpref['dev_branch']          = True
        FASTpref['FAST_exe']            = '~/local/bin/openfast'
        FASTpref['FAST_directory']      = '../OpenFAST'   # Path to fst directory files
        FASTpref['FAST_InputFile']      = 'IEA-15-240-RWT.fst' # FAST input file (ext=.fst)
        FASTpref['Turbsim_exe']         = '~/local/bin/turbsim'
        FASTpref['FAST_namingOut']      = 'IEA-15-240-RWT'
        FASTpref['FAST_runDirectory']   = 'temp/' + FASTpref['FAST_namingOut']
        
        # Run Settings
        FASTpref['cores']               = 1
        FASTpref['debug_level']         = 2 # verbosity: set to 0 for quiet, 1 & 2 for increasing levels of output

        # DLCs
        FASTpref['DLC_gust']            = None      # Max deflection
        # FASTpref['DLC_gust']            = RotorSE_DLC_1_4_Rated       # Max deflection    ### Not in place yet
        FASTpref['DLC_extrm']           = None      # Max strain
        # FASTpref['DLC_extrm']           = RotorSE_DLC_7_1_Steady      # Max strain        ### Not in place yet
        FASTpref['DLC_turbulent']       = None
        # FASTpref['DLC_turbulent']       = RotorSE_DLC_1_1_Turb      # Alternate turbulent case, replacing rated and extreme DLCs for calculating max deflection and strain
        FASTpref['DLC_powercurve']      = None      # AEP
        # FASTpref['DLC_powercurve']      = None      # AEP

        # Initialize, read initial FAST files to avoid doing it iteratively
        fast = InputReader_OpenFAST(FAST_ver=FASTpref['FAST_ver'], dev_branch=FASTpref['dev_branch'])
        fast.FAST_InputFile = FASTpref['FAST_InputFile']
        fast.FAST_directory = FASTpref['FAST_directory']
        fast.execute()
        fst_vt = fast.fst_vt
    else:
        fst_vt = {}

    prob = om.Problem()
    prob.model=MonopileTurbine(RefBlade=blade, Nsection_Tow=Nsection_Tow, VerbosityCosts=False, FASTpref=FASTpref)
    prob.model.nonlinear_solver = om.NonlinearRunOnce()
    prob.model.linear_solver    = om.DirectSolver()

    return prob, blade, fst_vt
    def test_undeclared_options(self):
        # Test that using options that should not exist in class cause an error
        solver = om.NonlinearRunOnce()

        msg = "\"NonlinearRunOnce: Option '%s' cannot be set because it has not been declared.\""

        for option in ['atol', 'rtol', 'maxiter', 'err_on_maxiter']:
            with self.assertRaises(KeyError) as context:
                solver.options[option] = 1

            self.assertEqual(str(context.exception), msg % option)
    def test_feature_solver(self):

        prob = om.Problem()
        model = prob.model

        model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy'])

        model.nonlinear_solver = om.NonlinearRunOnce()

        prob.setup(check=False, mode='fwd')

        prob.set_val('x', 4.0)
        prob.set_val('y', 6.0)

        prob.run_model()

        assert_near_equal(prob.get_val('f_xy'), 122.0)
    def test_feature_solver(self):
        import openmdao.api as om
        from openmdao.test_suite.components.paraboloid import Paraboloid

        prob = om.Problem()
        model = prob.model

        model.add_subsystem('p1', om.IndepVarComp('x', 0.0), promotes=['x'])
        model.add_subsystem('p2', om.IndepVarComp('y', 0.0), promotes=['y'])
        model.add_subsystem('comp', Paraboloid(), promotes=['x', 'y', 'f_xy'])

        model.nonlinear_solver = om.NonlinearRunOnce()

        prob.setup(check=False, mode='fwd')

        prob['x'] = 4.0
        prob['y'] = 6.0

        prob.run_model()

        assert_rel_error(self, prob['f_xy'], 122.0)
示例#9
0
            def setup(self):

                ivc = self.add_subsystem('ivc',
                                         om.IndepVarComp(),
                                         promotes_outputs=['*'])

                ivc.add_output('time',
                               val=np.array([
                                   0.00, 0.25, 0.25, 0.50, 0.50, 0.75, 0.75,
                                   1.00, 1.00, 1.25, 1.25, 1.50, 1.50, 1.75,
                                   1.75, 2.00
                               ]),
                               units='s')

                ivc.add_output('h',
                               val=np.array([0.5, 0.5, 0.5, 0.5]),
                               units='s')

                self.add_subsystem('cnty_iter_group',
                                   RungeKuttaStateContinuityIterGroup(
                                       num_segments=num_seg,
                                       method='RK4',
                                       state_options=state_options,
                                       time_units='s',
                                       ode_class=TestODE,
                                       ode_init_kwargs={},
                                       k_solver_class=om.NonlinearRunOnce),
                                   promotes_outputs=['states:*'])

                self.connect('h', 'cnty_iter_group.h')
                self.connect('time', 'cnty_iter_group.ode.t')

                src_idxs = np.arange(16, dtype=int).reshape((num_seg, 4, 1))
                self.connect('cnty_iter_group.ode.ydot',
                             'cnty_iter_group.k_comp.f:y',
                             src_indices=src_idxs,
                             flat_src_indices=True)

                self.nonlinear_solver = om.NonlinearRunOnce()
                self.linear_solver = om.DirectSolver()
示例#10
0
    model.connect('ground.V', ['circuit.Vg', 'batt_deltaV.V2'])
    model.connect('circuit.n1.V', 'batt_deltaV.V1')

    # set the lhs and rhs for the battery residual
    model.connect('batt.V', 'batt_balance.rhs:I')
    model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

    p.setup()

    ###################
    # Solver Setup
    ###################

    # change the circuit solver to RunOnce because we're
    # going to converge at the top level of the model with newton instead
    p.model.circuit.nonlinear_solver = om.NonlinearRunOnce()
    p.model.circuit.linear_solver = om.LinearRunOnce()

    # Put Newton at the top so it can also converge the new BalanceComp residual
    newton = p.model.nonlinear_solver = om.NewtonSolver()
    p.model.linear_solver = om.DirectSolver()
    newton.options['iprint'] = 2
    newton.options['maxiter'] = 20
    newton.options['solve_subsystems'] = True
    newton.linesearch = om.ArmijoGoldsteinLS()
    newton.linesearch.options['maxiter'] = 10
    newton.linesearch.options['iprint'] = 2

    # set initial guesses from the current source problem
    p['circuit.n1.V'] = 9.8
    p['circuit.n2.V'] = .7
示例#11
0
    def test_continuity_comp_connected_scalar_no_iteration_fwd(self):
        num_seg = 4
        state_options = {
            'y': {
                'shape': (1, ),
                'units': 'm',
                'targets': ['y'],
                'defect_scaler': None,
                'defect_ref': None,
                'lower': None,
                'upper': None,
                'connected_initial': True
            }
        }

        p = om.Problem(model=om.Group())

        ivc = p.model.add_subsystem('ivc',
                                    om.IndepVarComp(),
                                    promotes_outputs=['*'])
        ivc.add_output('initial_states:y', units='m', shape=(1, 1))

        p.model.add_subsystem('continuity_comp',
                              RungeKuttaStateContinuityComp(
                                  num_segments=num_seg,
                                  state_options=state_options),
                              promotes_inputs=['*'],
                              promotes_outputs=['*'])

        p.model.nonlinear_solver = om.NonlinearRunOnce()
        p.model.linear_solver = om.DirectSolver()

        p.setup(check=True, force_alloc_complex=True)

        p['initial_states:y'] = 0.5

        p['states:y'] = np.array([[0.50000000], [1.425130208333333],
                                  [2.639602661132812], [4.006818970044454],
                                  [5.301605229265987]])

        p['state_integrals:y'] = np.array([[1.0], [1.0], [1.0], [1.0]])

        p.run_model()
        p.model.run_apply_nonlinear()

        # Test that the residuals of the states are the expected values
        outputs = p.model.list_outputs(print_arrays=True,
                                       residuals=True,
                                       out_stream=None)

        y_f = p['states:y'][1:, ...]
        y_i = p['states:y'][:-1, ...]
        dy_given = y_f - y_i
        dy_computed = p['state_integrals:y']

        expected_resids = np.zeros((num_seg + 1, 1))
        expected_resids[1:, ...] = dy_given - dy_computed

        op_dict = dict([op for op in outputs])
        assert_near_equal(op_dict['continuity_comp.states:y']['resids'],
                          expected_resids)

        # Test the partials
        cpd = p.check_partials(method='cs')

        J_fwd = cpd['continuity_comp']['states:y',
                                       'state_integrals:y']['J_fwd']
        J_fd = cpd['continuity_comp']['states:y', 'state_integrals:y']['J_fd']

        J_fwd = cpd['continuity_comp']['states:y', 'states:y']['J_fwd']
        J_fd = cpd['continuity_comp']['states:y', 'states:y']['J_fd']

        J_fd[0, 0] = -1.0

        assert_near_equal(J_fwd, J_fd)
示例#12
0
    refBlade.NINPUT = 8
    refBlade.NPTS = 50
    refBlade.spar_var = ['Spar_Cap_SS', 'Spar_Cap_PS']  # SS, then PS
    refBlade.te_var = 'TE_reinforcement'
    refBlade.validate = False
    refBlade.fname_schema = fname_schema
    blade = refBlade.initialize(fname_input)
    # Initialize tower design
    Nsection_Tow = 6

    # Create a problem for our LandBasedTurbine
    prob = om.Problem()
    prob.model = LandBasedTurbine(RefBlade=blade,
                                  Nsection_Tow=Nsection_Tow,
                                  VerbosityCosts=True)
    prob.model.nonlinear_solver = om.NonlinearRunOnce()
    prob.model.linear_solver = om.DirectSolver()
    #prob.model.approx_totals()
    prob.setup()

    prob = Init_LandBasedAssembly(prob, blade, Nsection_Tow)

    prob.run_model()

    # landbosse_costs_by_module_type_operation = prob['landbosse_costs_by_module_type_operation']
    # print('###### LandBOSSE Costs ########################################')
    # for cost in landbosse_costs_by_module_type_operation:
    #     print(cost)
    # print('###############################################################')
    #
    # landbosse_details_by_module = prob['landbosse_details_by_module']
示例#13
0
def run_problem(optFlag=False, prob_ref=None):

    # Initialize blade design
    refBlade = ReferenceBlade()
    if rank == 0:
        refBlade.verbose = True
    else:
        refBlade.verbose = False
    refBlade.NINPUT = 8
    Nsection_Tow = 19
    refBlade.NPTS = 30
    refBlade.spar_var = ['Spar_cap_ss', 'Spar_cap_ps']  # SS, then PS
    refBlade.te_var = 'TE_reinforcement'
    refBlade.le_var = 'le_reinf'
    refBlade.validate = False
    refBlade.fname_schema = fname_schema
    blade = refBlade.initialize(fname_input)

    Analysis_Level = 0
    FASTpref = {}
    FASTpref['Analysis_Level'] = Analysis_Level
    fst_vt = {}

    # Initialize and execute OpenMDAO problem with input data
    if MPI:
        num_par_fd = MPI.COMM_WORLD.Get_size()
        prob = om.Problem(model=om.Group(num_par_fd=num_par_fd))
        prob.model.approx_totals(method='fd')
        prob.model.add_subsystem('comp',
                                 Optimize_MonopileTurbine(
                                     RefBlade=blade,
                                     Nsection_Tow=Nsection_Tow,
                                     folder_output=folder_output),
                                 promotes=['*'])
    else:
        prob = om.Problem()
        prob.model = Optimize_MonopileTurbine(RefBlade=blade,
                                              Nsection_Tow=Nsection_Tow,
                                              folder_output=folder_output)

    prob.model.nonlinear_solver = om.NonlinearRunOnce()
    prob.model.linear_solver = om.DirectSolver()

    if optFlag and not prob_ref is None:
        if MPI:
            num_par_fd = MPI.COMM_WORLD.Get_size()
            prob = om.Problem(model=om.Group(num_par_fd=num_par_fd))
            prob.model.approx_totals(method='fd')
            prob.model.add_subsystem('comp',
                                     Optimize_MonopileTurbine(
                                         RefBlade=blade,
                                         Nsection_Tow=Nsection_Tow,
                                         folder_output=folder_output),
                                     promotes=['*'])
        else:
            prob = om.Problem()
            prob.model = Optimize_MonopileTurbine(RefBlade=blade,
                                                  Nsection_Tow=Nsection_Tow,
                                                  folder_output=folder_output)

        # --- Driver ---
        prob.driver = om.pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'CONMIN'
        prob.driver.opt_settings['ITMAX'] = 15
        prob.driver.opt_settings['IPRINT'] = 4
        # ----------------------

        # --- Objective ---
        # prob.model.add_objective('lcoe')
        prob.model.add_objective('AEP', scaler=-1.)
        #prob.model.add_objective('mass_one_blade')
        # ----------------------

        # --- Design Variables ---
        indices_no_root = range(2, refBlade.NINPUT)
        indices_no_root_no_tip = range(2, refBlade.NINPUT - 1)
        indices_no_max_chord = range(3, refBlade.NINPUT)
        prob.model.add_design_var('sparT_in',
                                  indices=indices_no_root_no_tip,
                                  lower=0.001,
                                  upper=0.200)
        prob.model.add_design_var('chord_in',
                                  indices=indices_no_max_chord,
                                  lower=0.5,
                                  upper=7.0)
        prob.model.add_design_var('theta_in',
                                  indices=indices_no_root,
                                  lower=-7.5,
                                  upper=20.0)
        prob.model.add_design_var('teT_in',
                                  lower=prob_ref['teT_in'] * 0.5,
                                  upper=0.1)
        #prob.model.add_design_var('leT_in', lower=prob_ref['leT_in']*0.5, upper=0.1)
        # ----------------------

        # --- Constraints ---
        prob.model.add_subsystem('freq_check',
                                 blade_freq_check(),
                                 promotes=['freq_check_out'])
        prob.model.connect('freq_curvefem',
                           'freq_check.freq_curvefem')  #, src_indices=[0])

        # Rotor
        prob.model.add_constraint('tip_deflection_ratio', upper=1.0)
        # prob.model.add_constraint('no_stall_constraint',      upper=1.0)
        prob.model.add_constraint('freq_check_out', lower=1.1)
        #prob.model.add_constraint('rated_Q',     lower=21.4e6, upper=21.6e6)
        # prob.model.add_constraint('mass_one_blade',           upper=prob_ref['mass_one_blade']*1.02)
        prob.model.add_constraint('AEP', lower=0.99 * prob_ref['AEP'])
        # ----------------------

        # --- Recorder ---
        filename_opt_log = folder_output + 'log_opt_' + blade['config']['name']

        prob.driver.add_recorder(om.SqliteRecorder(filename_opt_log))
        prob.driver.recording_options['includes'] = [
            'AEP', 'total_blade_cost', 'lcoe', 'tip_deflection_ratio',
            'mass_one_blade', 'theta_in'
        ]
        prob.driver.recording_options['record_objectives'] = True
        prob.driver.recording_options['record_constraints'] = True
        prob.driver.recording_options['record_desvars'] = True
        # ----------------------

    # Initialize variable inputs
    prob = initialize_variables(prob, blade, Analysis_Level, fst_vt)

    # Run initial condition no matter what
    print('Running at Initial Position:')
    prob.run_model()

    print('########################################')
    print('')
    print('Control variables')
    print('Rotor diam:    {:8.3f} m'.format(prob['diameter'][0]))
    print('TSR:           {:8.3f} -'.format(prob['control_tsr'][0]))
    print('Rated vel:     {:8.3f} m/s'.format(prob['rated_V'][0]))
    print('Rated rpm:     {:8.3f} rpm'.format(prob['rated_Omega'][0]))
    print('Rated pitch:   {:8.3f} deg'.format(prob['rated_pitch'][0]))
    print('Rated thrust:  {:8.3f} N'.format(prob['rated_T'][0]))
    print('Rated torque:  {:8.3f} N-m'.format(prob['rated_Q'][0]))
    print('')
    print('Constraints')
    print('Max TD:       {:8.3f} m'.format(prob['tip_deflection'][0]))
    print('TD ratio:     {:8.3f} -'.format(prob['tip_deflection_ratio'][0]))
    print('Blade root M: {:8.3f} N-m'.format(prob['root_bending_moment'][0]))
    print('')
    print('Objectives')
    print('AEP:         {:8.3f} GWh'.format(prob['AEP'][0]))
    print('LCoE:        {:8.4f} $/MWh'.format(prob['lcoe'][0]))
    print('')
    print('Blades')
    print('Blade mass:  {:8.3f} kg'.format(prob['mass_one_blade'][0]))
    print('Blade cost:  {:8.3f} $'.format(prob['total_blade_cost'][0]))
    print('Blade freq:  {:8.3f} Hz'.format(prob['freq_curvefem'][0]))
    print('3 blade M_of_I:  ', prob['I_all_blades'], ' kg-m^2')
    print('Hub M:  ', prob['Mxyz_total'], ' kg-m^2')
    print('')
    print('RNA Summary')
    print('RNA mass:    {:8.3f} kg'.format(prob['tow.pre.mass'][0]))
    print('RNA C_of_G (TT):  ', prob['rna_cg'], ' m')
    print('RNA M_of_I:  ', prob['tow.pre.mI'], ' kg-m^2')
    print('')
    print('Tower')
    print('Tower top F: ', prob['tow.pre.rna_F'], ' N')
    print('Tower top M: ', prob['tow.pre.rna_M'], ' N-m')
    print('Tower freqs: ', prob['tow.post.structural_frequencies'], ' Hz')
    print('Tower vel:   {:8.3f} kg'.format(prob['tow.wind.Uref'][0]))
    print('Tower mass:  {:8.3f} kg'.format(prob['tower_mass'][0]))
    print('Tower cost:  {:8.3f} $'.format(prob['tower_cost'][0]))
    print('########################################')

    # Angle of attack and stall angle
    faoa, axaoa = plt.subplots(1, 1, figsize=(5.3, 4))
    axaoa.plot(prob['r'],
               prob['nostallconstraint.aoa_along_span'],
               label='Initial aoa')
    axaoa.plot(prob['r'],
               prob['nostallconstraint.stall_angle_along_span'],
               '.',
               label='Initial stall')
    axaoa.legend(fontsize=12)
    plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold')
    plt.ylabel('Angle [deg]', fontsize=14, fontweight='bold')
    plt.xticks(fontsize=12)
    plt.yticks(fontsize=12)
    plt.grid(color=[0.8, 0.8, 0.8], linestyle='--')
    plt.subplots_adjust(bottom=0.15, left=0.15)
    fig_name = 'aoa.png'
    faoa.savefig(folder_output + fig_name)

    # Complete data dump
    #prob.model.list_inputs(units=True)
    #prob.model.list_outputs(units=True)

    if optFlag:
        if rank == 0:
            print('Running Optimization:')
            print('N design var: ',
                  2 * len(indices_no_root_no_tip) + len(indices_no_root) + 1)
        if not MPI:
            prob.model.approx_totals()
        prob.run_driver()

        if rank == 0:
            # --- Save output .yaml ---
            refBlade.write_ontology(fname_output, prob['blade_out'],
                                    refBlade.wt_ref)

            # --- Outputs plotting ---
            print('AEP:         \t\t\t %f\t%f GWh \t Difference: %f %%' %
                  (prob_ref['AEP'] * 1e-6, prob['AEP'] * 1e-6,
                   (prob['AEP'] - prob_ref['AEP']) / prob_ref['AEP'] * 100.))
            print(
                'LCoE:        \t\t\t %f\t%f USD/MWh \t Difference: %f %%' %
                (prob_ref['lcoe'] * 1.e003, prob['lcoe'] * 1.e003,
                 (prob['lcoe'] - prob_ref['lcoe']) / prob_ref['lcoe'] * 100.))
            print('Blade cost:  \t\t\t %f\t%f USD \t Difference: %f %%' %
                  (prob_ref['total_blade_cost'], prob['total_blade_cost'],
                   (prob['total_blade_cost'] - prob_ref['total_blade_cost']) /
                   prob_ref['total_blade_cost'] * 100.))
            print('Blade mass:  \t\t\t %f\t%f kg  \t Difference: %f %%' %
                  (prob_ref['total_blade_mass'], prob['total_blade_mass'],
                   (prob['total_blade_mass'] - prob_ref['total_blade_mass']) /
                   prob_ref['total_blade_mass'] * 100.))
            print('Tower cost:  \t\t\t %f\t%f USD \t Difference: %f %%' %
                  (prob_ref['tower_cost'], prob['tower_cost'],
                   (prob['tower_cost'] - prob_ref['tower_cost']) /
                   prob_ref['tower_cost'] * 100.))
            print('Tower mass:  \t\t\t %f\t%f kg  \t Difference: %f %%' %
                  (prob_ref['tower_mass'], prob['tower_mass'],
                   (prob['tower_mass'] - prob_ref['tower_mass']) /
                   prob_ref['tower_mass'] * 100.))
            # ----------------------

            # Theta
            ft, axt = plt.subplots(1, 1, figsize=(5.3, 4))
            axt.plot(prob_ref['r'], prob_ref['theta'], label='Initial')
            axt.plot(prob_ref['r_in'], prob_ref['theta_in'], '.')
            axt.plot(prob['r'], prob['theta'], label='Optimized')
            axt.plot(prob['r_in'], prob['theta_in'], '.')
            axt.legend(fontsize=12)
            plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold')
            plt.ylabel('Twist [deg]', fontsize=14, fontweight='bold')
            plt.xticks(fontsize=12)
            plt.yticks(fontsize=12)
            plt.grid(color=[0.8, 0.8, 0.8], linestyle='--')
            plt.subplots_adjust(bottom=0.15, left=0.15)
            fig_name = 'theta.png'
            ft.savefig(folder_output + fig_name)

            # Angle of attack and stall angle
            faoa, axaoa = plt.subplots(1, 1, figsize=(5.3, 4))
            axaoa.plot(prob_ref['r'],
                       prob_ref['nostallconstraint.aoa_along_span'],
                       label='Initial aoa')
            axaoa.plot(prob_ref['r'],
                       prob_ref['nostallconstraint.stall_angle_along_span'],
                       '.',
                       label='Initial stall')
            axaoa.plot(prob['r'],
                       prob['nostallconstraint.aoa_along_span'],
                       label='Optimized aoa')
            axaoa.plot(prob['r'],
                       prob['nostallconstraint.stall_angle_along_span'],
                       '.',
                       label='Optimized stall')
            axaoa.legend(fontsize=12)
            plt.xlabel('Blade Span [m]', fontsize=14, fontweight='bold')
            plt.ylabel('Angle [deg]', fontsize=14, fontweight='bold')
            plt.xticks(fontsize=12)
            plt.yticks(fontsize=12)
            plt.grid(color=[0.8, 0.8, 0.8], linestyle='--')
            plt.subplots_adjust(bottom=0.15, left=0.15)
            fig_name = 'aoa.png'
            ft.savefig(folder_output + fig_name)

            plt.show()

    return prob, blade
示例#14
0
    def testAssembly(self):
        # Global inputs and outputs
        fname_schema = mydir + os.sep + 'IEAontology_schema.yaml'
        fname_input = mydir + os.sep + 'IEA-15-240-RWT.yaml'

        # Initialize blade design
        refBlade = ReferenceBlade()
        refBlade.verbose = True
        refBlade.NINPUT = 8
        Nsection_Tow = 19
        refBlade.NPTS = 30
        refBlade.spar_var = ['Spar_cap_ss', 'Spar_cap_ps']  # SS, then PS
        refBlade.te_var = 'TE_reinforcement'
        refBlade.validate = False
        refBlade.fname_schema = fname_schema
        blade = refBlade.initialize(fname_input)
        Analysis_Level = 0

        FASTpref = {}
        FASTpref['Analysis_Level'] = Analysis_Level
        fst_vt = {}

        prob = om.Problem()
        prob.model = MonopileTurbine(RefBlade=blade,
                                     Nsection_Tow=Nsection_Tow,
                                     VerbosityCosts=False,
                                     FASTpref=FASTpref)
        prob.model.nonlinear_solver = om.NonlinearRunOnce()
        prob.model.linear_solver = om.DirectSolver()
        prob.setup()

        prob = Init_RotorSE_wRefBlade(prob,
                                      blade,
                                      Analysis_Level=Analysis_Level,
                                      fst_vt=fst_vt)

        # Environmental parameters for the tower
        prob['significant_wave_height'] = 4.52
        prob['significant_wave_period'] = 9.45
        prob['water_depth'] = 30.
        prob['wind_reference_height'] = prob['hub_height'] = 150.
        prob['shearExp'] = 0.11
        prob['rho'] = 1.225
        prob['mu'] = 1.7934e-5
        prob['water_density'] = 1025.0
        prob['water_viscosity'] = 1.3351e-3
        prob['wind_beta'] = prob['wave_beta'] = 0.0

        # Steel properties for the tower
        prob['material_density'] = 7850.0
        prob['E'] = 210e9
        prob['G'] = 79.3e9
        prob['yield_stress'] = 345e6
        prob['soil_G'] = 140e6
        prob['soil_nu'] = 0.4

        # Design constraints
        prob['max_taper_ratio'] = 0.4
        prob['min_diameter_thickness_ratio'] = 120.0

        # Safety factors
        prob['gamma_fatigue'] = 1.755  # (Float): safety factor for fatigue
        prob['gamma_f'] = 1.35  # (Float): safety factor for loads/stresses
        prob['gamma_m'] = 1.3  # (Float): safety factor for materials
        prob[
            'gamma_freq'] = 1.1  # (Float): safety factor for resonant frequencies
        prob['gamma_n'] = 1.0
        prob['gamma_b'] = 1.1

        # Tower
        prob['tower_buckling_length'] = 30.0
        prob['tower_outfitting_factor'] = 1.07
        prob['foundation_height'] = -30.
        prob['suctionpile_depth'] = 45.
        prob['tower_section_height'] = np.array([
            5., 5., 5., 5., 5., 5., 5., 5., 5., 13., 13., 13., 13., 13., 13.,
            13., 13., 13., 12.58244309
        ])
        prob['tower_outer_diameter'] = np.array([
            10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 9.92647687,
            9.44319282, 8.83283769, 8.15148167, 7.38976138, 6.90908962,
            6.74803581, 6.57231775, 6.5
        ])
        prob['tower_wall_thickness'] = np.array([
            0.05534138, 0.05344902, 0.05150928, 0.04952705, 0.04751736,
            0.04551709, 0.0435267, 0.04224176, 0.04105759, 0.0394965,
            0.03645589, 0.03377851, 0.03219233, 0.03070819, 0.02910109,
            0.02721289, 0.02400931, 0.0208264, 0.02399756
        ])
        prob['tower_buckling_length'] = 15.0
        prob['transition_piece_mass'] = 100e3
        prob['transition_piece_height'] = 15.0

        prob['DC'] = 80.0
        prob['shear'] = True
        prob['geom'] = True
        prob['tower_force_discretization'] = 5.0
        prob['nM'] = 2
        prob['Mmethod'] = 1
        prob['lump'] = 0
        prob['tol'] = 1e-9
        prob['shift'] = 0.0

        # Offshore BOS
        prob['wtiv'] = 'example_wtiv'
        prob['feeder'] = 'future_feeder'
        prob['num_feeders'] = 1
        prob['oss_install_vessel'] = 'example_heavy_lift_vessel'
        prob['site_distance'] = 40.0
        prob['site_distance_to_landfall'] = 40.0
        prob['site_distance_to_interconnection'] = 40.0
        prob['plant_turbine_spacing'] = 7
        prob['plant_row_spacing'] = 7
        prob['plant_substation_distance'] = 1
        prob['tower_deck_space'] = 0.
        prob['nacelle_deck_space'] = 0.
        prob['blade_deck_space'] = 0.
        prob['port_cost_per_month'] = 2e6
        prob['monopile_deck_space'] = 0.
        prob['transition_piece_deck_space'] = 0.
        prob['commissioning_pct'] = 0.01
        prob['decommissioning_pct'] = 0.15
        prob['project_lifetime'] = prob['lifetime'] = 20.0
        prob['number_of_turbines'] = 40
        prob['annual_opex'] = 43.56  # $/kW/yr
        #prob['bos_costs']                      = 1234.5 # $/kW

        prob['tower_add_gravity'] = True

        # For turbine costs
        prob['offshore'] = True
        prob['crane'] = False
        prob['bearing_number'] = 2
        prob['crane_cost'] = 0.0
        prob['labor_cost_rate'] = 3.0
        prob['material_cost_rate'] = 2.0
        prob['painting_cost_rate'] = 28.8

        # Drivetrain
        prob['tilt'] = 6.0
        prob['overhang'] = 11.075
        prob['hub_cm'] = np.array([-10.685, 0.0, 5.471])
        prob['nac_cm'] = np.array([-5.718, 0.0, 4.048])
        prob['hub_I'] = np.array(
            [1382171.187, 2169261.099, 2160636.794, 0.0, 0.0, 0.0])
        prob['nac_I'] = np.array(
            [13442265.552, 21116729.439, 18382414.385, 0.0, 0.0, 0.0])
        prob['hub_mass'] = 190e3
        prob['nac_mass'] = 797.275e3 - 190e3
        prob['hss_mass'] = 0.0
        prob['lss_mass'] = 19.504e3
        prob['cover_mass'] = 0.0
        prob['pitch_system_mass'] = 50e3
        prob['platforms_mass'] = 0.0
        prob['spinner_mass'] = 0.0
        prob['transformer_mass'] = 0.0
        prob['vs_electronics_mass'] = 0.0
        prob['yaw_mass'] = 100e3
        prob['gearbox_mass'] = 0.0
        prob['generator_mass'] = 226.7e3 + 145.25e3
        prob['bedplate_mass'] = 39.434e3
        prob['main_bearing_mass'] = 4.699e3

        prob.run_model()
        # Make sure we get here
        self.assertTrue(True)
    def test_continuity_comp_no_iteration(self):
        num_seg = 4
        state_options = {
            'y': {
                'shape': (1, ),
                'units': 'm',
                'targets': ['y'],
                'fix_initial': True,
                'fix_final': False,
                'propagation': 'forward',
                'defect_scaler': None,
                'defect_ref': None,
                'lower': None,
                'upper': None,
                'connected_initial': False
            }
        }

        p = om.Problem(model=om.Group())

        ivc = p.model.add_subsystem('ivc',
                                    om.IndepVarComp(),
                                    promotes_outputs=['*'])

        ivc.add_output('time',
                       val=np.array([
                           0.00, 0.25, 0.25, 0.50, 0.50, 0.75, 0.75, 1.00,
                           1.00, 1.25, 1.25, 1.50, 1.50, 1.75, 1.75, 2.00
                       ]),
                       units='s')

        ivc.add_output('h', val=np.array([0.5, 0.5, 0.5, 0.5]), units='s')

        p.model.add_subsystem('cnty_iter_group',
                              RungeKuttaStateContinuityIterGroup(
                                  num_segments=num_seg,
                                  method='RK4',
                                  state_options=state_options,
                                  time_units='s',
                                  ode_class=TestODE,
                                  ode_init_kwargs={},
                                  k_solver_class=om.NonlinearRunOnce),
                              promotes_outputs=['states:*'])

        p.model.connect('h', 'cnty_iter_group.h')
        p.model.connect('time', 'cnty_iter_group.ode.t')

        src_idxs = np.arange(16, dtype=int).reshape((num_seg, 4, 1))
        p.model.connect('cnty_iter_group.ode.ydot',
                        'cnty_iter_group.k_comp.f:y',
                        src_indices=src_idxs,
                        flat_src_indices=True)

        p.model.nonlinear_solver = om.NonlinearRunOnce()
        p.model.linear_solver = om.DirectSolver()

        p.setup(check=True, force_alloc_complex=True)

        p['states:y'] = np.array([[0.50000000], [1.425130208333333],
                                  [2.639602661132812], [4.006818970044454],
                                  [5.301605229265987]])

        p['cnty_iter_group.k_comp.k:y'] = np.array([[[0.75000000
                                                      ], [0.90625000],
                                                     [0.94531250],
                                                     [1.09765625]],
                                                    [[1.087565104166667],
                                                     [1.203206380208333],
                                                     [1.232116699218750],
                                                     [1.328623453776042]],
                                                    [[1.319801330566406],
                                                     [1.368501663208008],
                                                     [1.380676746368408],
                                                     [1.385139703750610]],
                                                    [[1.378409485022227],
                                                     [1.316761856277783],
                                                     [1.301349949091673],
                                                     [1.154084459568063]]])

        p.run_model()
        p.model.run_apply_nonlinear()

        # Test that the residuals of the states are the expected values
        outputs = p.model.list_outputs(print_arrays=True,
                                       residuals=True,
                                       out_stream=None)

        expected_resids = np.zeros((num_seg + 1, 1))

        op_dict = dict([op for op in outputs])
        assert_rel_error(
            self,
            op_dict['cnty_iter_group.continuity_comp.states:y']['resids'],
            expected_resids)

        # Test the partials
        cpd = p.check_partials(method='cs', out_stream=None)

        J_fwd = cpd['cnty_iter_group.continuity_comp'][
            'states:y', 'state_integrals:y']['J_fwd']
        J_fd = cpd['cnty_iter_group.continuity_comp'][
            'states:y', 'state_integrals:y']['J_fd']
        assert_rel_error(self, J_fwd, J_fd)

        J_fwd = cpd['cnty_iter_group.continuity_comp']['states:y',
                                                       'states:y']['J_fwd']
        J_fd = cpd['cnty_iter_group.continuity_comp']['states:y',
                                                      'states:y']['J_fd']

        J_fd[0, 0] = -1.0

        assert_rel_error(self, J_fwd, J_fd)