class ExtendedFinancialAnalysis_Example(Assembly):
    """ Extended financial analysis assembly for coupling models to get a full wind plant cost of energy estimate as well as provides a detailed cost breakdown for the plant.    """

    # Inputs
    turbine_number = Int(iotype='in', desc='number of turbines at plant')

    #Outputs
    turbine_cost = Float(iotype='out', desc='A Wind Turbine Capital _cost')
    bos_costs = Float(iotype='out',
                      desc='A Wind Plant Balance of Station _cost Model')
    avg_annual_opex = Float(iotype='out',
                            desc='A Wind Plant Operations Expenditures Model')
    net_aep = Float(iotype='out',
                    desc='A Wind Plant Annual Energy Production Model',
                    units='kW*h')
    coe = Float(iotype='out',
                desc='Levelized cost of energy for the wind plant')
    opex_breakdown = VarTree(OPEXVarTree(), iotype='out')
    bos_breakdown = VarTree(BOSVarTree(),
                            iotype='out',
                            desc='BOS cost breakdown')

    def configure(self):

        configure_extended_financial_analysis(self)

        self.replace('tcc_a', BaseTurbineCostModel_Example())
        self.replace('aep_a', BaseAEPModel_Example())
        self.replace('fin_a', BaseFinancialModel_Example())
        self.replace('bos_a', ExtendedBOSCostModel_Example())
        self.replace('opex_a', ExtendedOPEXModel_Example())
Esempio n. 2
0
class ModifyBladePlanformBase(Component):
    """
    Base for classes that modify a blade planform object
    """

    pfIn = VarTree(BladePlanformVT(), iotype='in')
    pfOut = VarTree(BladePlanformVT(), iotype='out')
Esempio n. 3
0
class FstInputBuilder(Component):
    """
    base class for setting up HAWC2 input data

    add additional design variables and methods in derived classes
    """

    fstIn = VarTree(FstModel(), iotype='in')
    fstS = VarTree(FstModel(), iotype='in')
    fstOut = VarTree(FstModel(), iotype='out')
    
    def __init__(self):
        
        super(FstInputBuilder,self).__init__()

    def initialize_inputs(self):

        self._logger.info('dublicating inputs')
        self.fstS = self.fstIn.copy()

    def execute(self):

        self._logger.info('updating inputs')
        # update outputs
        self.fstOut = self.fstS.copy()
class RotorAeroCode(Component):
    """
    Wrapper for a code capable of predicting the distributed loads
    on a rotor
    """

    pf = VarTree(BladePlanformVT(),
                 iotype='in',
                 desc='Blade geometric definition')
    inflow = VarTree(TurbineEnvironmentVT(),
                     iotype='in',
                     desc='Rotor inflow conditions')

    oper = VarTree(RotorOperationalData(),
                   iotype='out',
                   desc='Operational data')
    rotor_loads = VarTree(RotorLoadsVT(),
                          iotype='out',
                          desc='Rotor torque, power, and thrust')
    blade_loads = VarTree(DistributedLoadsExtVT(),
                          iotype='out',
                          desc='Spanwise load distributions')

    def execute(self):

        print 'perform analysis here'
Esempio n. 5
0
class IECRunCaseBaseVT(VariableTree):

    # General conditions needed
    case_name = Str(
        'IEC_case',
        desc='Name of the specific case passed to the aeroelastic code')
    simulation = VarTree(
        AeroElasticSimulationSetup(), desc='Basic simulation input settings'
    )  # 4/28/2015 kld: should move elsewhere but leaving in for debugging
    environment = VarTree(OffshoreTurbineEnvironmentVT(),
                          desc='Inflow conditions to the turbine simulation')
    basic_turbine = VarTree(
        BasicTurbineVT(),
        desc='Basic turbine variables already defined in fusedwind')
    rotor = VarTree(RotorOperationalData(),
                    desc='Rotor variables already defined in fusedwind')
    pitch = VarTree(
        FixedSpeedFixedPitch(),
        desc='Pitch already defined in fusedwind')  # should probably move
    init_conditions = VarTree(FASTInitialConditions(),
                              desc='Initial conditions needed to run FAST')
    simulation_specs = VarTree(
        FASTSimulationSpecs(),
        desc='Basic simulation input settings')  #mb: also shouldn't be here
    aero_inputs = VarTree(AerodynInputs(),
                          desc='Wind and airfoil files to run Aerodyn')
    fst_inputs = VarTree(FASTInputs(), desc='FAST model variables')
    ptfm_inputs = VarTree(PtfmInputs(), desc='Platform model variables')
Esempio n. 6
0
class AeroelasticHAWTVT(BasicTurbineVT):

    tilt_angle = Float(units='deg', desc='Rotor tilt angle')
    cone_angle = Float(units='deg', desc='Rotor cone angle')
    hub_radius = Float(units='m', desc='Hub radius')
    blade_length = Float(units='m', desc='blade length')
    tower_height = Float(units='m', desc='Tower height')
    towertop_length = Float(units='m', desc='Nacelle Diameter')
    shaft_length = Float(units='m', desc='Shaft length')

    airfoildata = VarTree(AirfoilDatasetVT(), desc='Airfoil Aerodynamic characteristics')

    drivetrain_performance = VarTree(DrivetrainPerformanceVT(), desc='drivetrain performance VT')

    bodies = List()

    def add_main_body(self, name, body=None):

        if body is None:

            body = MainBody()
            
            if 'blade' in name:
                body.remove('geom')
                body.add('geom', VarTree(BladePlanformVT()))
            if 'tower' in name:
                body.remove('geom')
                body.add('geom', VarTree(TubularTowerGeometryVT()))

        self.add(name, VarTree(body))
        self.bodies.append(name)

        return getattr(self, name)

    def get_main_body(self, name):

        return getattr(self, name)

    def remove_main_body(self, name):

        self.delete(name)

    def set_machine_type(self, machine_type):

        self.remove('controls')

        if machine_type == 'FixedSpeedFixedPitch':
            self.add('controls', VarTree(FixedSpeedFixedPitch()))
        if machine_type == 'FixedSpeedVarPitch':
            self.add('controls', VarTree(FixedSpeedVarPitch()))
        if machine_type == 'VarSpeedFixedPitch':
            self.add('controls', VarTree(VarSpeedFixedPitch()))
        if machine_type == 'VarSpeedVarPitch':
            self.add('controls', VarTree(VarSpeedVarPitch()))

        return self.controls
Esempio n. 7
0
class InandOutTree(Component):

    ins = VarTree(InVtree(), iotype="in")

    outs = VarTree(OutVtree(), iotype="out")

    def execute(self):

        self.outs.x = 2 * self.ins.a
        self.outs.y = 2 * self.ins.a + self.ins.b
Esempio n. 8
0
class IECRunCaseBaseVT(VariableTree):

    case_name = Str(
        'IEC_case',
        desc='Name of the specific case passed to the aeroelastic code')
    simulation = VarTree(
        AeroElasticSimulationSetup(), desc='Basic simulation input settings'
    )  # 4/28/2015 kld: should move elsewhere but leaving in for debugging
    environment = VarTree(TurbineEnvironmentVT(),
                          desc='Inflow conditions to the turbine simulation')
class RotorAeroBase(Component):
    """
    Base class for models that can predict the power and thrust of wind turbine rotor
    for a single inflow case
    """

    pf = VarTree(BladePlanformVT(), iotype='in', desc='Blade geometric definition')
    inflow = VarTree(TurbineEnvironmentVT(), iotype='in', desc='Rotor inflow conditions')

    oper = VarTree(RotorOperationalData(), iotype='out', desc='Operational data')
    rotor_loads = VarTree(RotorLoadsVT(), iotype='out', desc='Rotor torque, power, and thrust')
Esempio n. 10
0
class MainBody(VariableTree):

    body_name = Str('body')
    subsystem = Enum('Tower', ('Rotor', 'Nacelle', 'Tower', 'Foundation'))

    beam_structure = VarTree(BeamStructureVT(), desc='Structural beam properties of the body')
    geom = VarTree(BeamGeometryVT(), desc='Beam geometry')
    mass = Float(desc='mass of the body')

    damping_posdef = Array(np.zeros(6))
    concentrated_mass = List(Array())
Esempio n. 11
0
class MEflows(VariableTree):
    """Container of variables defining the flow properties of the mixer-ejector nozzle"""

    # Primary and Secondary Streams
    pri = VarTree(Stream(), iotype='in')
    sec = VarTree(Stream(), iotype='in')

    gamma = Float(1.4, desc='Ratio of specific heats')
    Pstatic = Float(2116.8,
                    units='lbf/ft**2',
                    desc='Freestream static pressure')
Esempio n. 12
0
class ModifyBladeStructureBase(Component):

    st3dIn = VarTree(
        BladeStructureVT3D(),
        iotype='in',
        desc='Vartree containing initial discrete definition of blade structure'
    )
    st3dOut = VarTree(
        BladeStructureVT3D(),
        iotype='out',
        desc=
        'Vartree containing modified discrete definition of blade structure')
class RotorAero(Component):
    """
    Class that extends the TurbineAeroBase with distributed blade
    loads for a single inflow case
    """

    pf = VarTree(BladePlanformVT(), iotype='in', desc='Blade geometric definition')
    inflow = VarTree(TurbineEnvironmentVT(), iotype='in', desc='Rotor inflow conditions')

    oper = VarTree(RotorOperationalData(), iotype='out', desc='Operational data')
    rotor_loads = VarTree(RotorLoadsVT(), iotype='out', desc='Rotor torque, power, and thrust')
    blade_loads = VarTree(DistributedLoadsExtVT(), iotype='out', desc='Spanwise load distributions')
Esempio n. 14
0
    def __init__(self, Ns):
        super(Failures, self).__init__()

        # inputs
        self.add('flags', VarTree(Flags(), iotype='in'))

        self.add('yN', Array(np.zeros(Ns + 1), iotype='in', desc=''))

        self.add('Finternal', Array(np.zeros((6, Ns + 1)),
                                    iotype='in',
                                    desc=''))

        self.add('strain', VarTree(Strain(Ns), iotype='in'))

        self.add('d', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('theta', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('nTube', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('nCap', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('yWire', Array([0], iotype='in', desc=''))
        self.add('zWire', Float(0., iotype='in', desc=''))

        self.add('EIxJ', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('EIzJ', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('lBiscuit', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('dQuad', Float(0., iotype='in', desc=''))
        self.add('thetaQuad', Float(0., iotype='in', desc=''))
        self.add('nTubeQuad', Float(0., iotype='in', desc=''))
        self.add('lBiscuitQuad', Float(0., iotype='in', desc=''))
        self.add('RQuad', Float(0., iotype='in', desc=''))
        self.add('hQuad', Float(0., iotype='in', desc=''))

        self.add('EIQuad', Array(np.zeros(Ns), iotype='in', desc=''))
        self.add('GJQuad', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add('tWire', Float(0., iotype='in', desc=''))
        self.add('TWire', Array([0], iotype='in', desc=''))
        self.add('TEtension', Float(0., iotype='in', desc=''))

        # all this to get TQuad... maybe should be split out
        self.add('b', Int(0, iotype='in', desc='number of blades'))
        self.add('fblade', VarTree(Fblade(Ns), iotype='in'))
        self.add('mSpar', Array(np.zeros(Ns),
                                iotype='in',
                                desc='mass of spars'))
        self.add('mChord',
                 Array(np.zeros(Ns), iotype='in', desc='mass of chords'))
        self.add('mElseRotor', Float(0., iotype='in', desc=''))

        # outputs
        self.add('fail', VarTree(Failure(Ns), iotype='out'))
class CS2Dsolver(Component):

    cs2d = List(CrossSectionStructureVT, iotype='in', desc='Blade cross sectional structure geometry')
    pf = VarTree(BladePlanformVT(), iotype='in', desc='Blade planform discretized according to'
                                                      'the structural resolution')

    beam_structure = VarTree(BeamStructureVT(), iotype='out', desc='Structural beam properties')

    def execute(self):

        print ''
        for i, cs in enumerate(self.cs2d):
            print 'processing cross section %i' % i
class ComputeHAWC2BeamProps(Component):
    """
    Component that postprocesses the individual outputs from the
    BECAS case runs returning a BeamStructureVT, mass and mass moment.
    """

    pf = VarTree(BladePlanformVT(), iotype='in')
    hub_radius = Float(iotype='in')
    cs2d_cases = List(iotype='in')
    g = Float(9.81, iotype='in')
    beam_structure = VarTree(BeamStructureVT(), iotype='out')
    mass = Float(iotype='out')
    mass_moment = Float(iotype='out')

    def execute(self):

        self.beam_structure = self.beam_structure.copy()

        ni = len(self.cs2d_cases)

        for name in self.beam_structure.list_vars():
            var = getattr(self.beam_structure, name)
            if name == 'J':
                nname = 'K'
            else:
                nname = name
            if isinstance(var, np.ndarray):
                var = np.zeros(ni)
                for i, h2d in enumerate(self.cs2d_cases):
                    try:
                        var[i] = getattr(h2d, nname)
                    except:
                        pass

            setattr(self.beam_structure, name, var)

        self.beam_structure.s = self.pf.s * self.pf.smax * self.pf.blade_length
        self.mass = np.trapz(self.beam_structure.dm, self.beam_structure.s)
        self.mass_moment = np.trapz(
            self.g * self.beam_structure.dm *
            (self.beam_structure.s + self.hub_radius), self.beam_structure.s)

        print 'Mass: ', self.mass
        print 'Mass moment: ', self.mass_moment

        self.beam_structure.x_e += (
            0.5 - self.pf.p_le) * self.pf.chord * self.pf.blade_length
        self.beam_structure.x_cg += (
            0.5 - self.pf.p_le) * self.pf.chord * self.pf.blade_length
        self.beam_structure.x_sh += (
            0.5 - self.pf.p_le) * self.pf.chord * self.pf.blade_length
Esempio n. 17
0
    def set_machine_type(self, machine_type):

        self.remove('controls')

        if machine_type == 'FixedSpeedFixedPitch':
            self.add('controls', VarTree(FixedSpeedFixedPitch()))
        if machine_type == 'FixedSpeedVarPitch':
            self.add('controls', VarTree(FixedSpeedVarPitch()))
        if machine_type == 'VarSpeedFixedPitch':
            self.add('controls', VarTree(VarSpeedFixedPitch()))
        if machine_type == 'VarSpeedVarPitch':
            self.add('controls', VarTree(VarSpeedVarPitch()))

        return self.controls
Esempio n. 18
0
class Failure(VariableTree):
    top = VarTree(MaterialFailure())
    bottom = VarTree(MaterialFailure())
    back = VarTree(MaterialFailure())
    front = VarTree(MaterialFailure())

    buckling = VarTree(BucklingFailure())

    quad_buckling = Float(desc='Quad Buckling failure')
    quad_bend = Float(desc='Quad bending moment failure')
    quad_torsion = Float(desc='Quad torsional material failure')
    quad_torbuck = Float(desc='Quad torsional buckling failure')

    wire = Array(desc='Wire tensile failure')
Esempio n. 19
0
class FUSEDAssembly(Assembly):
    """
    Base class for all FUSED-Wind assemblies which extends OpenMDAO's Assembly
    with dedicated slots for I/O and methods for recording runs.
    """

    inputs = VarTree(
        CaseInputsBase(),
        iotype='in',
        desc='Placeholder for FUSED-Wind inputs to a simulation code')
    outputs = VarTree(CaseOutputsBase(),
                      iotype='out',
                      desc='Placeholder for FUSED-Wind outputs generated by a'
                      'simulation code')
Esempio n. 20
0
class HAWC2PostPowerCurve(Component):

    cases = Slot(ICaseIterator, iotype='in')

    rotor_loads = VarTree(RotorLoadsArrayVT(), iotype='out')
    nraverage = Int(200)

    def execute(self):

        wsp = []
        P = []
        T = []
        Q = []
        for case in self.cases:
            wsp.append(case.get_input('builder.Ps.wind.wsp'))
            out = case.get_output('wrapper.output')
            data = out.datasets[0].get_channels([10, 11, 12])
            Q.append(np.average(data[-self.nraverage:, 0]))
            P.append(np.average(data[-self.nraverage:, 1]))
            T.append(np.average(data[-self.nraverage:, 2]))

        # sort the cases to make sure they are stored with increasing wsp
        zipped = zip(wsp, T, Q, P)
        zipped.sort()
        wsp, T, Q, P = zip(*zipped)

        self.rotor_loads.wsp = wsp
        self.rotor_loads.T = np.array(T) * 1000.
        self.rotor_loads.Q = np.array(Q) * 1000.
        self.rotor_loads.P = np.array(P) * 1000.
class Builder(Component):
    st3d = VarTree(BladeVT(), iotype='in')

    def execute(self):
        for region in self.st3d.section0.regions:
            # print region, getattr(self.st3d.section0, region)
            getattr(self.st3d.section0, region)
class SplinedRegion(Component):
    region = VarTree(RegionVT(), iotype='out')

    def execute(self):
        # print 'computing splines for c0 and c1'
        self.region.c0 = 1.0  # np.sin(np.linspace(0,1,10))
        self.region.c1 = 2.0  # np.cos(np.linspace(0,1,10))
Esempio n. 23
0
class GenericWindFarm(Component):

    # Inputs:
    wind_speed = Float(iotype='in',
                       low=0.0,
                       high=100.0,
                       units='m/s',
                       desc='Inflow wind speed at hub height')
    wind_direction = Float(iotype='in',
                           low=0.0,
                           high=360.0,
                           units='deg',
                           desc='Inflow wind direction at hub height')
    wt_layout = VarTree(GenericWindFarmTurbineLayout(),
                        iotype='in',
                        desc='wind turbine properties and layout')

    # Outputs:
    power = Float(iotype='out',
                  units='kW',
                  desc='Total wind farm power production')
    thrust = Float(iotype='out', units='N', desc='Total wind farm thrust')
    wt_power = Array([],
                     iotype='out',
                     desc='The power production of each wind turbine')
    wt_thrust = Array([], iotype='out', desc='The thrust of each wind turbine')
Esempio n. 24
0
    def add_dll(self, dll_name, b):

        b.dll_name = dll_name
        if not hasattr(self, dll_name):
            self.add(dll_name, VarTree(b))
        else:
            print 'dll: %s already added' % dll_name
Esempio n. 25
0
    def add_case(self, obj, wsp=None, case_name=None):
        """
        Add a BeamDisplacementsVT

        Specify either wsp or a user specified case name

        Parameters
        ----------
        obj: BeamDisplacementsVT object 
            case to be added
        wsp: float
            optional wind speed
        case_name: str
            custom case name
        """

        if wsp == None and case_name == None:
            raise RuntimeError('Expected either wsp or case_name, got ' %
                               (wsp, case_name))
        if wsp is not None:
            name = 'loads%2.2f' % wsp
        elif case_name is not None:
            name = case_name

        self.add(name, VarTree(obj))
        self.loads_array.append(name)

        return getattr(self, name)
Esempio n. 26
0
class WTPC(GenericWindTurbinePowerCurveVT):
    """ A GenericWindTurbinePowerCurveVT with a name, position and wind rose
    """
    # GenericWindTurbineVT
    hub_height = Float(desc='Machine hub height', units='m')
    rotor_diameter = Float(desc='Machine rotor diameter', units='m')
    power_rating = Float(desc='Machine power rating', units='W')

    # GenericWindTurbinePowerCurveVT
    c_t_curve = Array(desc='Machine thrust coefficients by wind speed at hub')
    power_curve = Array(desc='Machine power output [W] by wind speed at hub')
    cut_in_wind_speed = Float(4.,
                              desc='The cut-in wind speed of the wind turbine',
                              units='m/s')
    cut_out_wind_speed = Float(
        25., desc='The cut-out wind speed of the wind turbine', units='m/s')
    rated_wind_speed = Float(desc='The rated wind speed of the wind turbine',
                             units='m/s')
    air_density = Float(desc='The air density the power curve are valid for',
                        units='kg/(m*m*m)')

    # WTPC
    name = Str(desc='The wind turbine name')
    position = Array(shape=(2, ),
                     desc='The UTM position of the turbine',
                     units='m')
    wind_rose = VarTree(GenericWindRoseVT(), desc='The wind turbine wind rose')

    def __init__(self, **kwargs):
        """Initialise the variable tree with the right inputs"""
        super(WTPC, self).__init__()
        for k, v in kwargs.iteritems():
            if k in self.list_vars():
                setattr(self, k, v)
Esempio n. 27
0
class BladePlanformWriter(Component):

    filebase = Str('blade')
    pf = VarTree(BladePlanformVT(), iotype='in')

    def execute(self):

        name = self.filebase + self.itername + '.pfd'

        try:
            if '-fd' in self.itername or '-fd' in self.parent.itername:
                name = self.filebase + '.pfd'
        except:
            pass

        data = np.array([
            self.pf.x, self.pf.y, self.pf.z, self.pf.rot_x, self.pf.rot_y,
            self.pf.rot_z, self.pf.chord, self.pf.rthick, self.pf.p_le
        ]).T
        fid = open(name, 'w')
        header = [
            'main_axis_x', 'main_axis_y', 'main_axis_z', 'rot_x', 'rot_y',
            'rot_z', 'chord', 'rthick', 'p_le'
        ]

        exp_prec = 10  # exponential precesion
        col_width = exp_prec + 8  # column width required for exp precision
        header_full = '# ' + ''.join([(hh + ' [%i]').center(col_width + 2) % i
                                      for i, hh in enumerate(header)]) + '\n'

        fid.write(header_full)
        np.savetxt(fid, data, fmt='%' + ' %i.%ie' % (col_width, exp_prec))
        fid.close()
Esempio n. 28
0
    def __init__(self, Ns):
        super(Strains, self).__init__()

        # inputs
        self.add('yN', Array(np.zeros(Ns + 1), iotype='in', desc=''))
        self.add('d', Array(np.zeros(Ns), iotype='in', desc=''))

        self.add(
            'k',
            Array(np.zeros((Ns + 2, Ns + 2, Ns)),
                  iotype='in',
                  desc='Local elastic stiffness matrix'))

        self.add(
            'F',
            Array(np.zeros((6 * (Ns + 1), 1)),
                  iotype='in',
                  desc='global force vector'))
        self.add(
            'q',
            Array(np.zeros((6 * (Ns + 1), 1)), iotype='in',
                  desc='deformation'))

        # outputs
        self.add(
            'Finternal',
            Array(np.zeros((6, Ns + 1)), iotype='out', desc='internal forces'))

        self.add('strain', VarTree(Strain(Ns), iotype='out', desc='strains'))
class RotorStructureBase(Component):
    """
    Base class for models that can predict blade deflections
    based on load distribution
    """

    blade_disps = VarTree(BeamDisplacementsVT(), iotype='out', desc='Blade deflections and rotations')
Esempio n. 30
0
class BoxParametricGeometry(Component):
    """A simple parametric geometry (a box)"""

    height = Float(2, iotype="in")
    volume = Float(8, iotype="in")

    geom_data = VarTree(GeomData(n_point=8, n_facet=6, facet_size=4),
                        iotype="out")

    def __init__(self):
        super(BoxParametricGeometry, self).__init__()

        # color array.  one color per face in this case
        self.colors = array(
            [
                [0, 0, 255],  # v0-v1-v2-v3
                [255, 0, 0],  # v0-v3-v4-v5
                [0, 255, 0],  # v0-v5-v6-v1
                [255, 255, 0],  # v1-v6-v7-v2
                [255, 0, 255],  # v7-v4-v3-v2
                [0, 255, 255],  # v4-v7-v6-v5
            ],
            dtype=float32)

        # index array
        # each face has 2 triangles
        self.triangles = array([0, 1, 2, 0, 2, 3], dtype=int32)

        self.bbox = [-1., -1., -1., 1., 1., 1.]

        self.geom_data.facets = array(
            [
                [0, 1, 2, 3],  #front
                [0, 3, 4, 5],  #right
                [0, 5, 6, 1],  #top
                [1, 6, 7, 2],  #left
                [7, 4, 3, 2],  #bottom
                [4, 7, 6, 5],  #back
            ],
            dtype="int")

    def execute(self):
        h = self.height
        x = h / 2.

        self.bbox = [-1, -1, -x, 1, 1, x]
        self.volume = 2 * 2 * h

        self.geom_data.points = array(
            [
                [1, 1, x],
                [-1, 1, x],
                [-1, -1, x],
                [1, -1, x],  # v0, v1, v2, v3
                [1, -1, -x],
                [1, 1, -x],
                [-1, 1, -x],
                [-1, -1, -x],  # v4, v5, v6, v7
            ],
            dtype=float32)