Skip to content
Snippets Groups Projects
spacing_component.py 3.57 KiB
from openmdao.core.explicitcomponent import ExplicitComponent
import numpy as np

class SpacingComp(ExplicitComponent):
    """
    Calculates inter-turbine spacing for all turbine pairs.
    Code from wake-exchange module
    """

    def __init__(self, nTurbines):

        super(SpacingComp, self).__init__()
        self.nTurbines = nTurbines

    def setup(self):

        # set finite difference options (fd used for testing only)
        #self.deriv_options['check_form'] = 'central'
        #self.deriv_options['check_step_size'] = 1.0e-5
        #self.deriv_options['check_step_calc'] = 'relative'

        # Explicitly size input arrays
        self.add_input('turbineX', val=np.zeros(self.nTurbines),
                       desc='x coordinates of turbines in wind dir. ref. frame', units='m')
        self.add_input('turbineY', val=np.zeros(self.nTurbines),
                       desc='y coordinates of turbines in wind dir. ref. frame', units='m')

        # Explicitly size output array
        self.add_output('wtSeparationSquared', val=np.zeros(int((self.nTurbines - 1) * self.nTurbines / 2)),
                        desc='spacing of all turbines in the wind farm')

        #self.declare_partials('wtSeparationSquared', ['turbineX', 'turbineY'], method='fd')
        self.declare_partials('wtSeparationSquared', ['turbineX', 'turbineY'])

    def compute(self, inputs, outputs):
        # print 'in dist const'

        turbineX = inputs['turbineX']
        turbineY = inputs['turbineY']
        nTurbines = self.nTurbines
        separation_squared = np.zeros(int((nTurbines - 1) * nTurbines / 2))

        k = 0
        for i in range(0, nTurbines):
            for j in range(i + 1, nTurbines):
                separation_squared[k] = (turbineX[j] - turbineX[i])**2 + (turbineY[j] - turbineY[i])**2
                k += 1
        outputs['wtSeparationSquared'] = separation_squared
#         print("wt sep")
#         print(separation_squared)
#         print()

    def compute_partials(self, inputs, J):

        # obtain necessary inputs
        turbineX = inputs['turbineX']
        turbineY = inputs['turbineY']

        # get number of turbines
        nTurbines = self.nTurbines

        # initialize gradient calculation array
#        dS = np.zeros((int((nTurbines - 1.) * nTurbines / 2.), 2 * nTurbines))
        dSdx = np.zeros((int((nTurbines - 1.) * nTurbines / 2.),  nTurbines)) #col: dx_1-dx_n, row: d12, d13,..,d1n, d23..d2n,..
        dSdy = np.zeros((int((nTurbines - 1.) * nTurbines / 2.),  nTurbines))

        # set turbine pair counter to zero
        k = 0

        # calculate the gradient of the distance between each pair of turbines w.r.t. turbineX and turbineY
        for i in range(0, nTurbines):
            for j in range(i + 1, nTurbines):
                # separation wrt Xj
#                dS[k, j] = 2 * (turbineX[j] - turbineX[i])
                dSdx[k,j]= 2 * (turbineX[j] - turbineX[i])
                # separation wrt Xi
#                dS[k, i] = -2 * (turbineX[j] - turbineX[i])
                dSdx[k, i] = -2 * (turbineX[j] - turbineX[i])
                # separation wrt Yj
#                dS[k, j + nTurbines] = 2 * (turbineY[j] - turbineY[i])
                dSdy[k, j] = 2 * (turbineY[j] - turbineY[i])
                # separation wrt Yi
#                dS[k, i + nTurbines] = -2 * (turbineY[j] - turbineY[i])
                dSdy[k, i] = -2 * (turbineY[j] - turbineY[i])
                # increment turbine pair counter
                k += 1

        # populate Jacobian dict
        J['wtSeparationSquared', 'turbineX'] = dSdx
        J['wtSeparationSquared', 'turbineY'] = dSdy