class BECASCSStressRecovery(Component):
    """
    component for calling BECAS on individual sections to
    compute stresses and strains.
    """
    def __init__(self, name, config, s, ncases):
        super(BECASCSStressRecovery, self).__init__()

        self.name = name
        self.s = s
        self.basedir = os.getcwd()

        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is generated in the upstream BECASBeamStructure class
        self.add_param(name + ':hash', 0.)

        self.add_param('load_cases_%s' % name, np.zeros((ncases, 6)))
        self.add_output('blade_failure_index_%s' % name, np.zeros(ncases))

        self.becas = BECASWrapper(s, **config['BECASWrapper'])
        self.becas.analysis_mode = 'stress_recovery'

    def solve_nonlinear(self, params, unknowns, resids):

        becas_hash = params[self.name + ':hash']
        workdir = 'becas_%s_%i' % (self.name, int(becas_hash))
        print 'workdir', workdir
        os.chdir(workdir)
        self.becas.load_cases = params['load_cases_%s' % self.name]
        self.becas.compute()
        unknowns['blade_failure_index_%s' %
                 self.name] = self.becas.max_failure_ks

        os.chdir(self.basedir)
Esempio n. 2
0
class BECASCSStructureKM(Component):
    def __init__(self, name, becas_hash, config, input_folder, s):
        """
        parameters
        ----------
        config: dict
            dictionary with inputs to BECASWrapper
        input_folder: list
            list with becas input folders
        s: array
            spanwise location of the cross-section
        """

        super(BECASCSStructureKM, self).__init__()

        self.basedir = os.getcwd()
        self.becas_hash = becas_hash

        # add outputs
        self.add_output('%s:k_matrix' % name, shape=(6, 6))
        self.add_output('%s:m_matrix' % name, shape=(6, 6))

        self.workdir = 'becas_%s_%i' % (name, self.becas_hash)
        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is passed to downstream BECASStressRecovery class
        self.add_output(name + ':hash', float(self.becas_hash))

        config['BECASWrapper']['path_input'] = os.path.join(
            self.basedir, input_folder)

        self.becas = BECASWrapper(s, **config['BECASWrapper'])
        self.s = s

    def solve_nonlinear(self, params, unknowns, resids):
        """
        calls BECAS to compute the stiffness and mass terms
        """

        try:
            os.mkdir(self.workdir)
        except:
            pass
        os.chdir(self.workdir)

        self.becas.compute()
        self.unknowns['%s:k_matrix' % self.name] = self.becas.k_matrix
        self.unknowns['%s:m_matrix' % self.name] = self.becas.m_matrix

        #remove becas output files and folders related to hash
        #         os.remove('becas_section.m')
        #         os.remove('BECAS_SetupPath.m')
        #         os.remove('becas_utils%.3f.mat' % self.s)
        #         os.rmdir(os.getcwd())

        os.chdir(self.basedir)
class BECASCSStructureKM(Component):

    def __init__(self, name, becas_hash, config, input_folder, s):
        """
        parameters
        ----------
        config: dict
            dictionary with inputs to BECASWrapper
        input_folder: list
            list with becas input folders
        s: array
            spanwise location of the cross-section
        """

        super(BECASCSStructureKM, self).__init__()

        self.basedir = os.getcwd()
        self.becas_hash = becas_hash

        # add outputs
        self.add_output('%s:k_matrix' % name, shape=(6,6))
        self.add_output('%s:m_matrix' % name, shape=(6,6))

        self.workdir = 'becas_%s_%i' % (name, self.becas_hash)
        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is passed to downstream BECASStressRecovery class
        self.add_output(name + ':hash', float(self.becas_hash))

        config['BECASWrapper']['path_input'] = os.path.join(self.basedir, input_folder)

        self.becas = BECASWrapper(s, **config['BECASWrapper'])
        self.s = s

    def solve_nonlinear(self, params, unknowns, resids):
        """
        calls BECAS to compute the stiffness and mass terms
        """

        try:
            os.mkdir(self.workdir)
        except:
            pass
        os.chdir(self.workdir)

        self.becas.compute()
        self.unknowns['%s:k_matrix' % self.name] = self.becas.k_matrix
        self.unknowns['%s:m_matrix' % self.name] = self.becas.m_matrix

        #remove becas output files and folders related to hash
#         os.remove('becas_section.m')
#         os.remove('BECAS_SetupPath.m')
#         os.remove('becas_utils%.3f.mat' % self.s)
#         os.rmdir(os.getcwd())

        os.chdir(self.basedir)
class BECASCSStressRecovery(Component):
    """
    component for calling BECAS on individual sections to
    compute stresses and strains.
    """

    def __init__(self, name, config, s, ncases):
        super(BECASCSStressRecovery, self).__init__()

        self.name = name
        self.s = s
        self.basedir = os.getcwd()

        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is generated in the upstream BECASBeamStructure class
        self.add_param(name + ':hash', 0.)

        self.add_param('load_cases_%s' % name, np.zeros((ncases, 6)))
        self.add_output('blade_failure_index_%s' % name, np.zeros(ncases))

        self.becas = BECASWrapper(s, **config['BECASWrapper'])
        self.becas.analysis_mode = 'stress_recovery'

    def solve_nonlinear(self, params, unknowns, resids):


        becas_hash = params[self.name + ':hash']
        workdir = 'becas_%s_%i' % (self.name, int(becas_hash))
        print 'workdir', workdir
        os.chdir(workdir)
        self.becas.load_cases = params['load_cases_%s' % self.name]
        self.becas.compute()
        unknowns['blade_failure_index_%s' % self.name] = self.becas.max_failure_ks

        os.chdir(self.basedir)
Esempio n. 5
0
class BECASCSStructure(Component):
    """
    Component for computing beam structural properties
    using the cross-sectional structure code BECAS.

    The code firstly calls CS2DtoBECAS which is a wrapper around
    shellexpander that comes with BECAS, and second
    calls BECAS using a file interface.

    parameters
    ----------
    config: dict
        dictionary of model specific inputs
    coords: array
        cross-sectional shape. size ((ni_chord, 3))
    matprops: array
        material stiffness properties. Size ((10, nmat)).
    failmat: array
        material strength properties. Size ((18, nmat)).
    DPs: array
        vector of DPs. Size: (nDP)
    coords: array
        blade section coordinates. Size: ((ni_chord, 3))
    r<xx><lname>T: float
        layer thicknesses, e.g. r01triaxT.
    r<xx><lname>A: float
        layer angles, e.g. r01triaxA.
    w<xx><lname>T: float
        web thicknesses, e.g. r01triaxT.
    w<xx><lname>A: float
        web angles, e.g. r01triaxA.

    returns
    -------
    cs_props: array
        vector of cross section properties. Size (19) or (30)
        for standard HAWC2 output or the fully populated stiffness
        matrix, respectively.

    csprops_ref: array
        vector of cross section properties as of BECAS output w.r.t BECAS reference
        coordinate system. Size (18).
    """
    def __init__(self, name, becas_hash, config, st3d, s, ni_chord, cs_size,
                 cs_size_ref):
        """
        parameters
        ----------
        config: dict
            dictionary with inputs to CS2DtoBECAS and BECASWrapper
        st3d: dict
            dictionary with blade structural definition
        s: array
            spanwise location of the cross-section
        ni_chord: int
            number of points definiting the cross-section shape
        cs_size: int
            size of blade_beam_structure array (19 or 30)
        cs_size_ref: int
            size of blade_beam_csprops_ref array (18)
        """
        super(BECASCSStructure, self).__init__()

        self.basedir = os.getcwd()
        self.becas_hash = becas_hash
        self.nr = len(st3d['regions'])
        self.ni_chord = ni_chord

        # fix mesh distribution function after first run
        # defaults to True
        try:
            self.fix_mesh_distribution = config['fix_mesh_distribution']
        except:
            self.fix_mesh_distribution = True

        # add materials properties array ((10, nmat))
        self.add_param('matprops', st3d['matprops'])

        # add materials strength properties array ((18, nmat))
        self.add_param('failmat', st3d['failmat'])

        # add DPs array
        self.add_param('%s:DPs' % name, np.zeros(self.nr + 1))

        # add coords coords
        self._varnames = []
        self.add_param('%s:coords' % name, np.zeros((ni_chord, 3)))

        self.cs2di = {}
        self.cs2di['materials'] = st3d['materials']
        self.cs2di['matprops'] = st3d['matprops']
        self.cs2di['failcrit'] = st3d['failcrit']
        self.cs2di['failmat'] = st3d['failmat']
        self.cs2di['web_def'] = st3d['web_def']
        self.cs2di['s'] = s
        self.cs2di['DPs'] = np.zeros(self.nr + 1)
        self.cs2di['regions'] = []
        self.cs2di['webs'] = []
        for ireg, reg in enumerate(st3d['regions']):
            r = {}
            r['layers'] = reg['layers']
            nl = len(reg['layers'])
            r['thicknesses'] = np.zeros(nl)
            r['angles'] = np.zeros(nl)
            self.cs2di['regions'].append(r)
            for i, lname in enumerate(reg['layers']):
                varname = '%s:r%02d%s' % (name, ireg, lname)
                self._varnames.append(varname)
        for ireg, reg in enumerate(st3d['webs']):
            r = {}
            r['layers'] = reg['layers']
            nl = len(reg['layers'])
            r['thicknesses'] = np.zeros(nl)
            r['angles'] = np.zeros(nl)
            self.cs2di['webs'].append(r)
            for i, lname in enumerate(reg['layers']):
                varname = '%s:w%02d%s' % (name, ireg, lname)
                self._varnames.append(varname)
        self.add_param(name + ':tvec', np.zeros(len(self._varnames) * 2))

        # add outputs
        self.add_output('%s:cs_props' % name, np.zeros(cs_size))
        self.add_output('%s:csprops_ref' % name, np.zeros(cs_size_ref))
        self.add_output('%s:k_matrix' % name, shape=(6, 6))
        self.add_output('%s:m_matrix' % name, shape=(6, 6))
        self.cs_props_m1 = np.zeros(cs_size)
        self.csprops_ref_m1 = np.zeros(cs_size_ref)
        self.k_matrix_m1 = np.zeros((6, 6))
        self.m_matrix_m1 = np.zeros((6, 6))

        self.add_output('%s:DPcoords' % name, np.zeros((self.nr + 1, 3)))

        self.workdir = 'becas_%s_%i' % (name, self.becas_hash)
        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is passed to downstream BECASStressRecovery class
        self.add_output(name + ':hash', float(self.becas_hash))

        self.mesher = CS2DtoBECAS(self.cs2di, **config['CS2DtoBECAS'])
        self.becas = BECASWrapper(self.cs2di['s'], **config['BECASWrapper'])
        self.redistribute_flag = True

    def _params2dict(self, params):
        """
        convert the OpenMDAO params dictionary into
        the dictionary format used in CS2DtoBECAS.
        """
        tvec = params[self.name + ':tvec']

        self.cs2d = {}
        # constants
        self.cs2d['s'] = self.cs2di['s']
        self.cs2d['web_def'] = self.cs2di['web_def']
        self.cs2d['failcrit'] = self.cs2di['failcrit']
        self.cs2d['materials'] = self.cs2di['materials']

        # params
        self.cs2d['coords'] = params['%s:coords' % self.name][:, :2]
        self.cs2d['matprops'] = params['matprops']
        self.cs2d['failmat'] = params['failmat']
        self.cs2d['DPs'] = params['%s:DPs' % self.name]
        self.cs2d['regions'] = []
        self.cs2d['webs'] = []
        counter = 0
        nvar = len(self._varnames)
        for ireg, reg in enumerate(self.cs2di['regions']):
            self.cs2d['regions'].append({})
            Ts = []
            As = []
            layers = []
            for i, lname in enumerate(reg['layers']):
                if tvec[counter] > 0.:
                    Ts.append(tvec[counter])
                    As.append(tvec[nvar + counter])
                    layers.append(lname)
                counter += 1
            self.cs2d['regions'][ireg]['thicknesses'] = np.asarray(Ts)
            self.cs2d['regions'][ireg]['angles'] = np.asarray(As)
            self.cs2d['regions'][ireg]['layers'] = layers
        for ireg, reg in enumerate(self.cs2di['webs']):
            self.cs2d['webs'].append({})
            Ts = []
            As = []
            layers = []
            for i, lname in enumerate(reg['layers']):
                if tvec[counter] > 0.:
                    Ts.append(tvec[counter])
                    As.append(tvec[nvar + counter])
                    layers.append(lname)
                counter += 1
            self.cs2d['webs'][ireg]['thicknesses'] = np.asarray(Ts)
            self.cs2d['webs'][ireg]['angles'] = np.asarray(As)
            self.cs2d['webs'][ireg]['layers'] = layers

    def solve_nonlinear(self, params, unknowns, resids):
        """
        calls CS2DtoBECAS/shellexpander to generate mesh
        and BECAS to compute the cs_props and csprops
        """

        try:
            os.mkdir(self.workdir)
        except:
            pass
        os.chdir(self.workdir)

        self._params2dict(params)

        self.mesher.cs2d = self.cs2d

        try:
            self.mesher.compute(self.redistribute_flag)
            self.becas.compute()
            if self.becas.success:
                self.unknowns['%s:DPcoords' % self.name][:, 0:2] = np.array(
                    self.mesher.DPcoords)
                self.unknowns['%s:cs_props' % self.name] = self.becas.cs_props
                self.unknowns['%s:csprops_ref' %
                              self.name] = self.becas.csprops
                self.unknowns['%s:k_matrix' % self.name] = self.becas.k_matrix
                self.unknowns['%s:m_matrix' % self.name] = self.becas.m_matrix
                self.cs_props_m1 = self.becas.cs_props.copy()
                self.csprops_ref_m1 = self.becas.csprops.copy()
                self.k_matrix_m1 = self.becas.k_matrix.copy()
                self.m_matrix_m1 = self.becas.m_matrix.copy()
            else:
                self.unknowns['%s:cs_props' % self.name] = self.cs_props_m1
                self.unknowns['%s:csprops_ref' %
                              self.name] = self.csprops_ref_m1
                self.unknowns['%s:k_matrix' % self.name] = self.k_matrix_m1
                self.unknowns['%s:m_matrix' % self.name] = self.m_matrix_m1
                print('BECAS crashed for section %f' % self.cs2d['s'])
        except:
            self.unknowns['%s:cs_props' % self.name] = self.cs_props_m1
            self.unknowns['%s:csprops_ref' % self.name] = self.csprops_ref_m1
            self.unknowns['%s:k_matrix' % self.name] = self.k_matrix_m1
            self.unknowns['%s:m_matrix' % self.name] = self.m_matrix_m1
            print('BECAS crashed for section %f' % self.cs2d['s'])

        os.chdir(self.basedir)
        if self.fix_mesh_distribution:
            self.redistribute_flag = False
class BECASCSStructure(Component):
    """
    Component for computing beam structural properties
    using the cross-sectional structure code BECAS.

    The code firstly calls CS2DtoBECAS which is a wrapper around
    shellexpander that comes with BECAS, and second
    calls BECAS using a file interface.

    parameters
    ----------
    config: dict
        dictionary of model specific inputs
    coords: array
        cross-sectional shape. size ((ni_chord, 3))
    matprops: array
        material stiffness properties. Size ((10, nmat)).
    failmat: array
        material strength properties. Size ((18, nmat)).
    DPs: array
        vector of DPs. Size: (nDP)
    coords: array
        blade section coordinates. Size: ((ni_chord, 3))
    r<xx><lname>T: float
        layer thicknesses, e.g. r01triaxT.
    r<xx><lname>A: float
        layer angles, e.g. r01triaxA.
    w<xx><lname>T: float
        web thicknesses, e.g. r01triaxT.
    w<xx><lname>A: float
        web angles, e.g. r01triaxA.

    returns
    -------
    cs_props: array
        vector of cross section properties. Size (19) or (30)
        for standard HAWC2 output or the fully populated stiffness
        matrix, respectively.

    csprops_ref: array
        vector of cross section properties as of BECAS output w.r.t BECAS reference
        coordinate system. Size (18).
    """

    def __init__(self, name, becas_hash, config, st3d, s, ni_chord, cs_size, cs_size_ref):
        """
        parameters
        ----------
        config: dict
            dictionary with inputs to CS2DtoBECAS and BECASWrapper
        st3d: dict
            dictionary with blade structural definition
        s: array
            spanwise location of the cross-section
        ni_chord: int
            number of points definiting the cross-section shape
        cs_size: int
            size of blade_beam_structure array (19 or 30)
        cs_size_ref: int
            size of blade_beam_csprops_ref array (18)
        """
        super(BECASCSStructure, self).__init__()

        self.basedir = os.getcwd()
        self.becas_hash = becas_hash
        self.nr = len(st3d['regions'])
        self.ni_chord = ni_chord

        # add materials properties array ((10, nmat))
        self.add_param('matprops', st3d['matprops'])

        # add materials strength properties array ((18, nmat))
        self.add_param('failmat', st3d['failmat'])

        # add DPs array
        self.add_param('%s:DPs' % name, np.zeros(self.nr + 1))

        # add coords coords
        self._varnames = []
        self.add_param('%s:coords' % name, np.zeros((ni_chord, 3)))

        self.cs2di = {}
        self.cs2di['materials'] = st3d['materials']
        self.cs2di['matprops'] = st3d['matprops']
        self.cs2di['failcrit'] = st3d['failcrit']
        self.cs2di['failmat'] = st3d['failmat']
        self.cs2di['web_def'] = st3d['web_def']
        self.cs2di['s'] = s
        self.cs2di['DPs'] = np.zeros(self.nr + 1)
        self.cs2di['regions'] = []
        self.cs2di['webs'] = []
        for ireg, reg in enumerate(st3d['regions']):
            r = {}
            r['layers'] = reg['layers']
            nl = len(reg['layers'])
            r['thicknesses'] = np.zeros(nl)
            r['angles'] = np.zeros(nl)
            self.cs2di['regions'].append(r)
            for i, lname in enumerate(reg['layers']):
                varname = '%s:r%02d%s' % (name, ireg, lname)
                self._varnames.append(varname)
        for ireg, reg in enumerate(st3d['webs']):
            r = {}
            r['layers'] = reg['layers']
            nl = len(reg['layers'])
            r['thicknesses'] = np.zeros(nl)
            r['angles'] = np.zeros(nl)
            self.cs2di['webs'].append(r)
            for i, lname in enumerate(reg['layers']):
                varname = '%s:w%02d%s' % (name, ireg, lname)
                self._varnames.append(varname)
        self.add_param(name + ':tvec', np.zeros(len(self._varnames)*2))

        # add outputs
        self.add_output('%s:cs_props' % name, np.zeros(cs_size))
        self.add_output('%s:csprops_ref' % name, np.zeros(cs_size_ref))
        self.add_output('%s:k_matrix' % name, shape=(6,6))
        self.add_output('%s:m_matrix' % name, shape=(6,6))
        self.cs_props_m1 = np.zeros(cs_size)
        self.csprops_ref_m1 = np.zeros(cs_size_ref)
        self.k_matrix_m1 = np.zeros((6,6))
        self.m_matrix_m1 = np.zeros((6,6))
        
        self.add_output('%s:DPcoords' % name, np.zeros((self.nr + 1, 3)))

        self.workdir = 'becas_%s_%i' % (name, self.becas_hash)
        # not so nice hack to ensure unique directory names when
        # running parallel FD
        # the hash is passed to downstream BECASStressRecovery class
        self.add_output(name + ':hash', float(self.becas_hash))

        self.mesher = CS2DtoBECAS(self.cs2di, **config['CS2DtoBECAS'])
        self.becas = BECASWrapper(self.cs2di['s'], **config['BECASWrapper'])

    def _params2dict(self, params):
        """
        convert the OpenMDAO params dictionary into
        the dictionary format used in CS2DtoBECAS.
        """
        tvec = params[self.name+':tvec']

        self.cs2d = {}
        # constants
        self.cs2d['s'] = self.cs2di['s']
        self.cs2d['web_def'] = self.cs2di['web_def']
        self.cs2d['failcrit'] = self.cs2di['failcrit']
        self.cs2d['materials'] = self.cs2di['materials']

        # params
        self.cs2d['coords'] = params['%s:coords' % self.name][:, :2]
        self.cs2d['matprops'] = params['matprops']
        self.cs2d['failmat'] = params['failmat']
        self.cs2d['DPs'] = params['%s:DPs' % self.name]
        self.cs2d['regions'] = []
        self.cs2d['webs'] = []
        counter = 0
        nvar = len(self._varnames)
        for ireg, reg in enumerate(self.cs2di['regions']):
            self.cs2d['regions'].append({})
            Ts = []
            As = []
            layers = []
            for i, lname in enumerate(reg['layers']):
                if tvec[counter] > 0.:
                    Ts.append(tvec[counter])
                    As.append(tvec[nvar+counter])
                    layers.append(lname)
                counter += 1
            self.cs2d['regions'][ireg]['thicknesses'] = np.asarray(Ts)
            self.cs2d['regions'][ireg]['angles'] = np.asarray(As)
            self.cs2d['regions'][ireg]['layers'] = layers
        for ireg, reg in enumerate(self.cs2di['webs']):
            self.cs2d['webs'].append({})
            Ts = []
            As = []
            layers = []
            for i, lname in enumerate(reg['layers']):
                if tvec[counter] > 0.:
                    Ts.append(tvec[counter])
                    As.append(tvec[nvar+counter])
                    layers.append(lname)
                counter += 1
            self.cs2d['webs'][ireg]['thicknesses'] = np.asarray(Ts)
            self.cs2d['webs'][ireg]['angles'] = np.asarray(As)
            self.cs2d['webs'][ireg]['layers'] = layers

    def solve_nonlinear(self, params, unknowns, resids):
        """
        calls CS2DtoBECAS/shellexpander to generate mesh
        and BECAS to compute the cs_props and csprops
        """

        try:
            os.mkdir(self.workdir)
        except:
            pass
        os.chdir(self.workdir)

        self._params2dict(params)

        self.mesher.cs2d = self.cs2d
        
        try:
            self.mesher.compute()
            self.becas.compute()
            if self.becas.success:
                self.unknowns['%s:DPcoords' % self.name][:,0:2] = np.array(self.mesher.DPcoords)
                self.unknowns['%s:cs_props' % self.name] = self.becas.cs_props
                self.unknowns['%s:csprops_ref' % self.name] = self.becas.csprops
                self.unknowns['%s:k_matrix' % self.name] = self.becas.k_matrix
                self.unknowns['%s:m_matrix' % self.name] = self.becas.m_matrix
                self.cs_props_m1 = self.becas.cs_props.copy()
                self.csprops_ref_m1 = self.becas.csprops.copy()
                self.k_matrix_m1 = self.becas.k_matrix.copy()
                self.m_matrix_m1 = self.becas.m_matrix.copy()
            else:
                self.unknowns['%s:cs_props' % self.name] = self.cs_props_m1
                self.unknowns['%s:csprops_ref' % self.name] = self.csprops_ref_m1
                self.unknowns['%s:k_matrix' % self.name] = self.k_matrix_m1
                self.unknowns['%s:m_matrix' % self.name] = self.m_matrix_m1
                print('BECAS crashed for section %f' % self.cs2d['s'])
        except:
            self.unknowns['%s:cs_props' % self.name] = self.cs_props_m1
            self.unknowns['%s:csprops_ref' % self.name] = self.csprops_ref_m1
            self.unknowns['%s:k_matrix' % self.name] = self.k_matrix_m1
            self.unknowns['%s:m_matrix' % self.name] = self.m_matrix_m1
            print('BECAS crashed for section %f' % self.cs2d['s'])

        os.chdir(self.basedir)