예제 #1
0
class CBShortFiber(RF):
    '''
    Micromechanical response of a short fiber bridging a crack
    '''
    implements(IRF)
    xi = Float(distr=['weibull_min', 'uniform'])
    E_f = Float(distr=['uniform', 'norm'])
    r = Float(distr=['uniform', 'norm'])
    le = Float(distr=['uniform'])
    tau = Float(distr=['norm', 'uniform', 'weibull_min'])
    snub = Float(distr=['uniform', 'norm'])
    phi = Float(distr=['sin2x', 'uniform'])
    w = Float
    C_code = ''

    def __call__(self, w, tau, r, E_f, le, phi, snub, xi, epsm_softening):
        T = 2. * tau / r
        # debonding stage
        ef0_deb = np.sqrt(T * w / E_f)
        # crack opening at which debonding is finished
        w0 = le**2 * T / E_f
        # pulling out stage - the fiber is pulled out from the
        # side with the shorter embedded length only
        ef0_pull = (le + w0 - w) * T / E_f
        ef0 = (ef0_deb * (w < w0) + ef0_pull *
               (w > w0)) * np.exp(phi * snub) + epsm_softening
        # include breaking strain
        ef0 = ef0 * (ef0 < xi) * (ef0 > 0.0)
        return ef0
class ConstantFrictionAndFreeLength(RF):
    '''
    '''

    implements(IRF)

    title = Str('pull-out with constant friction and free length ')

    tau = Float(8, auto_set=False, enter_set=True, distr=['uniform'])

    # free length
    l = Float(1, auto_set=False, enter_set=True, distr=['uniform', 'norm'])

    E = Float(70e9, auto_set=False, enter_set=True, distr=['uniform'])

    A = Float(5.30929158457e-10,
              auto_set=False,
              enter_set=True,
              distr=['uniform', 'weibull_min'])

    # waviness in strains
    slack = Float(0.1, auto_set=False, enter_set=True, distr=['uniform'])

    u = Float(auto_set=False, enter_set=True, ctrl_range=(0.0, 1.0, 10))

    def __call__(self, u, tau, l, E, A, slack):
        return -l * (1 + slack) * tau * Heaviside(u - l * (slack)) + \
                + sqrt((l * (1 + slack) * tau) ** 2 \
                + 2 * E * A * (u - (l * slack)) * Heaviside(u - l * (slack)))
예제 #3
0
class fiber_tt_2p(RF):
    ur'''
Response Function with two-parameters.
======================================
    
The function describes a linear dependency with a coefficient :math:`\lambda` 
up to the threshold :math:`\xi` and zero value beyond the threshold: 
    
..    math::
       q( \varepsilon; \theta, \lambda ) = \lambda \varepsilon H( \xi - \varepsilon )

where the variables :math:`\lambda=` stiffness parameter and :math:`\xi=` 
breaking strain are considered random and normally distributed. The function 
:math:`H(\eta)` represents the Heaviside function with values 0 for 
:math:`\eta < 0` and 1 for :math:`\eta > 0`.
   
    '''
    implements(IRF)

    title = Str('brittle filament')

    def __call__(self, e, la, xi):
        ''' Response function of a single fiber '''
        return la * e * Heaviside(xi - e)

    cython_code = '''
            # Computation of the q( ... ) function
            if eps < 0 or eps > xi:
                q = 0.0
            else:
                q = la * eps
            '''

    c_code = '''
예제 #4
0
class POClampedFiber(RF):
    '''
    Pullout of fiber from a stiff matrix;
    stress criterion for debonding, fixed fiber end
    '''

    implements(IRF)

    title = Str('pullout - clamped fiber with constant friction')
    image = Image('pics/cb_short_fiber.jpg', size=2)

    xi = Float(0.0179, auto_set=False, enter_set=True, input=True,
                distr=['weibull_min', 'uniform'])

    tau = Float(2.5, auto_set=False, enter_set=True, input=True,
                distr=['uniform', 'norm'])

    l = Float(0.0, auto_set=False, enter_set=True, input=True,
              distr=['uniform'], desc='free length')

    D_f = Float(26e-3, auto_set=False, input=True,
              enter_set=True, distr=['uniform', 'weibull_min'])

    E_f = Float(72.0e3, auto_set=False, enter_set=True, input=True,
                  distr=['uniform'])

    theta = Float(0.01, auto_set=False, enter_set=True, input=True,
                  distr=['uniform', 'norm'], desc='slack')

    phi = Float(1., auto_set=False, enter_set=True, input=True,
                  distr=['uniform', 'norm'], desc='bond quality')

    L = Float(1., auto_set=False, enter_set=True, input=True,
              distr=['uniform'], desc='embedded length')

    u = Float(auto_set=False, enter_set=True,
               ctrl_range=(0.0, 0.02, 100))

    x_label = Str('displacement [mm]')
    y_label = Str('force [N]')

    C_code = Str('')

    def __call__(self, u, tau, l, D_f, E_f, theta, xi, phi, L):

        A = pi * D_f ** 2 / 4.
        l = l * (1 + theta)
        u = u - theta * l
        T = tau * phi * D_f * pi
        q = (-l * T + sqrt(l ** 2 * T ** 2 + 2 * u * H(u) * E_f * A * T))

        # displacement at which the debonding is finished
        u0 = L * T * (L + 2 * l) / 2 / E_f / A
        q = q * H(T * L - q) + (T * L + (u - u0) / (l + L) * A * E_f) * H(q - T * L)

            # ----------------------------------
        q = q * H(A * E_f * xi - q)
        return q
class ConstantFrictionFreeLengthFiniteFiber(RF):
    '''
    '''

    implements(IRF)

    title = Str('pull-out with constant friction and free length ')

    tau = Float(0.5e6,
                auto_set=False,
                enter_set=True,
                distr=['uniform', 'weibull_min', 'norm'])

    # free length
    l = Float(0.01, auto_set=False, enter_set=True, distr=['uniform', 'norm'])

    E = Float(70e9, auto_set=False, enter_set=True, distr=['uniform'])

    A = Float(5.30929158457e-10,
              auto_set=False,
              enter_set=True,
              distr=['uniform', 'weibull_min'])

    # waviness in strains
    slack = Float(0.0, auto_set=False, enter_set=True, distr=['uniform'])

    # embedded length
    L = Float(0.03, auto_set=False, enter_set=True, distr=['uniform'])

    # breking stress
    sigma_fu = Float(1200.e6,
                     auto_set=False,
                     enter_set=True,
                     distr=['uniform'])

    u = Float(auto_set=False, enter_set=True, ctrl_range=(0.0, 1.0, 10))

    #

    def __call__(self, u, tau, l, E, A, slack, L, sigma_fu):
        ''' method for evaluating the u-F diagram for
        pullout with constant friction at the interface and
        free fiber length sticking out of the matrix '''
        # defining tau as length dependent
        tau = tau * sqrt(4 * A * pi)
        # constitutive law for a pullout without free length
        q = ( -l * ( 1 + slack ) * tau * Heaviside( u / 2 - l * ( slack ) ) + \
                + sqrt( ( l * ( 1 + slack ) * tau ) ** 2 * Heaviside( u / 2 - l * ( slack ) ) \
                + 2 * E * A * ( u / 2 - ( l * slack ) ) * Heaviside( u / 2 - l * ( slack ) ) ) )

        # deformation of the free length added
        continuous = q * Heaviside( L - l - q / tau )\
                + ( L - l ) * tau * Heaviside( l + q / tau - L )

        # a check whether the fiber has reached the breaking stress
        return continuous * Heaviside(sigma_fu - continuous / A)
예제 #6
0
class fiber_tt_2p(RF):
    '''Linear elastic, brittle filament.
    '''
    implements(IRF)

    title = Str('brittle filament')

    def __call__(self, e, la, xi):
        ''' Response function of a single fiber '''
        return la * e * Heaviside(xi - e)

    C_code = '''
예제 #7
0
    class fiber_tt_5p_np(RF):
        ''' Response function of a single fiber '''
        implements(IRF)

        title = Str('brittle filament')

        def __call__(self, eps, lambd, xi, E_mod, theta, A):
            '''
            Implements the response function with arrays as variables.
            first extract the variable discretizations from the orthogonal grid.
            '''
            eps_ = (eps - theta * (1 + lambd)) / ((1 + theta) * (1 + lambd))

            eps_ *= Heaviside(eps_)
            eps_grid = eps_ * Heaviside(xi - eps_)
            q_grid = E_mod * A * eps_grid

            return q_grid
예제 #8
0
    class fiber_tt_5p_ne(RF):
        ''' Response function of a single fiber '''
        implements(IRF)

        title = Str('brittle filament')

        def __call__(self, eps, lambd, xi, E_mod, theta, A):
            '''
            Implements the response function with arrays as variables.
            first extract the variable discretizations from the orthogonal grid.
            '''
            eps_ = ne.evaluate(
                "((eps - theta * (1 + lambd)) / ((1 + theta) * (1 + lambd)))")
            tmp = Heaviside_ne(eps_)
            eps_ = ne.evaluate('eps_*tmp')
            tmp = Heaviside_ne(ne.evaluate("(xi - eps_)"))
            eps_grid = ne.evaluate("eps_ * tmp")
            q_grid = ne.evaluate("E_mod * A * eps_grid")

            return q_grid
예제 #9
0
class fiber_tt_2p(RF):
    '''Linear elastic, brittle filament.
    '''
    implements(IRF)

    title = Str('brittle filament')

    def __call__(self, e, la, xi):
        ''' Response function of a single fiber '''
        return la * e * Heaviside(xi - e)

    cython_code = '''
            # Computation of the q( ... ) function
            if eps < 0 or eps > xi:
                q = 0.0
            else:
                q = la * eps
            '''

    weave_code = '''
예제 #10
0
class CodeGenLangDictC(HasStrictTraits):

    implements(ICodeGenLangDict)

    LD_BEGIN_EPS_LOOP_ACTIVE = 'for( int i_eps = 0; i_eps < %(i)i; i_eps++){\n'
    LD_END_EPS_LOOP_ACTIVE = '};\n'
    LD_ACCESS_EPS_IDX = '\tdouble eps = e_arr( i_eps );\n'
    LD_ACCESS_EPS_PTR = '\tdouble eps = *( e_arr + i_eps );\n'
    LD_ASSIGN_EPS = 'double eps = e;\n'

    LD_LINE_MACRO = '#line 100\n'
    LD_INIT_MU_Q = 'double mu_q=0;\n'
    LD_INIT_Q = 'double q=0;\n'
    LD_EVAL_MU_Q = '\tmu_q +=  q * dG;\n'
    LD_ADD_MU_Q = '\tmu_q += q;\n'
    LD_ASSIGN_MU_Q_IDX = 'mu_q_arr(i_eps) = mu_q;\n'
    LD_ASSIGN_MU_Q_PTR = '*(mu_q_arr + i_eps) = mu_q;\n'
    LD_RETURN_MU_Q = 'return_val = mu_q;'

    LD_INIT_THETA = 'double %s = %g;\n'
    LD_BEGIN_THETA_DEEP_LOOP = '%(t)sfor( int i_%(s)s = 0; i_%(s)s < %(i)i; i_%(s)s++){\n'
    LD_END_THETA_DEEP_LOOP = '};\n'
    LD_ACCESS_THETA_IDX = '\tdouble %s = %s_flat( i_%s );\n'
    LD_ACCESS_THETA_PTR = '\tdouble %s = *( %s_flat + i_%s );\n'

    LD_BEGIN_THETA_FLAT_LOOP = 'for( int i = 0; i < %i; i++){\n'
    LD_ACCESS_THETA_FLAT_IDX = '\tdouble %s = %s_flat( i);\n'
    LD_ACCESS_THETA_FLAT_PTR = '\tdouble %s = *( %s_flat + i );\n'
    LD_END_THETA_FLAT_LOOP = '};\n'

    LD_DECLARE_DG_IDX = '\tdouble dG = dG_grid('
    LD_DECLARE_DG_PTR = '\tdouble dG = '
    LD_ACCESS_DG_IDX = 'i_%s'
    LD_ACCESS_DG_PTR = '*( %s_dG + i_%s)'
    LD_ASSIGN_DG = 'double dG = %.100g;\n'
    LD_END_BRACE = ');\n'
예제 #11
0
class CodeGenLangDictCython(HasStrictTraits):

    implements(ICodeGenLangDict)

    LD_BEGIN_EPS_LOOP_ACTIVE = '\tcdef np.ndarray mu_q_arr = np.zeros_like( e_arr )\n\tfor i_eps from 0 <= i_eps < %(i)i:\n\t\teps = e_arr[i_eps]\n'
    LD_END_EPS_LOOP_ACTIVE = '\n'
    LD_ACCESS_EPS_IDX = ''
    LD_ACCESS_EPS_PTR = ''
    LD_ASSIGN_EPS = ''

    LD_LINE_MACRO = ''
    LD_INIT_MU_Q = ''
    LD_INIT_Q = '\tmu_q = 0\n'
    LD_EVAL_MU_Q = 'mu_q += q * dG\n'
    LD_ADD_MU_Q = 'mu_q += q\n'
    LD_ASSIGN_MU_Q_IDX = '\t\tmu_q_arr[i_eps] = mu_q\n\treturn mu_q_arr\n'
    LD_ASSIGN_MU_Q_PTR = '\t\tmu_q_arr[i_eps] = mu_q\n\treturn mu_q_arr\n'
    LD_RETURN_MU_Q = '\treturn mu_q'

    LD_INIT_THETA = '\t\t%s = %g\n'
    LD_BEGIN_THETA_DEEP_LOOP = '%(t)s\tfor i_%(s)s from 0 <= i_%(s)s <%(i)i:\n'
    LD_END_THETA_DEEP_LOOP = '\n'
    LD_ACCESS_THETA_IDX = '\t\t%s = %s_flat[ i_%s ]\n'
    LD_ACCESS_THETA_PTR = '\t\t%s = %s_flat[ i_%s ]\n'

    LD_BEGIN_THETA_FLAT_LOOP = '\tfor i from 0 <= i < %i:\n'
    LD_ACCESS_THETA_FLAT_IDX = '\t\t%s = %s_flat[i]\n'
    LD_ACCESS_THETA_FLAT_PTR = '\t\t%s = %s_flat[i]\n'
    LD_END_THETA_FLAT_LOOP = '\n'

    LD_DECLARE_DG_IDX = '%(t)s\tdG = dG_grid['
    LD_DECLARE_DG_PTR = '%(t)s\tdG = '
    LD_ACCESS_DG_IDX = 'i_%s'
    LD_ACCESS_DG_PTR = '%s_dG[i_%s]'
    LD_ASSIGN_DG = '\tdG = %.100g\n'
    LD_END_BRACE = ']\n'
예제 #12
0
    class CBClampedFiber(RF):
        '''
        Crack bridged by a short fiber with constant
        frictional interface to the matrix; clamped fiber end
        '''

        implements(IRF)

        title = Str('crack bridge - clamped fiber with constant friction')
        image = Image('pics/cb_short_fiber.jpg')

        xi = Float(0.0179,
                   auto_set=False,
                   enter_set=True,
                   input=True,
                   distr=['weibull_min', 'uniform'])

        tau = Float(2.5,
                    auto_set=False,
                    enter_set=True,
                    input=True,
                    distr=['uniform', 'norm'])

        l = Float(0.0,
                  auto_set=False,
                  enter_set=True,
                  input=True,
                  distr=['uniform'],
                  desc='free length')

        D_f = Float(26e-3,
                    auto_set=False,
                    input=True,
                    enter_set=True,
                    distr=['uniform', 'weibull_min'])

        E_f = Float(72.0e3,
                    auto_set=False,
                    enter_set=True,
                    input=True,
                    distr=['uniform'])

        theta = Float(0.01,
                      auto_set=False,
                      enter_set=True,
                      input=True,
                      distr=['uniform', 'norm'],
                      desc='slack')

        phi = Float(1.,
                    auto_set=False,
                    enter_set=True,
                    input=True,
                    distr=['uniform', 'norm'],
                    desc='bond quality')

        Ll = Float(1.,
                   auto_set=False,
                   enter_set=True,
                   input=True,
                   distr=['uniform'],
                   desc='embedded length - left')

        Lr = Float(.5,
                   auto_set=False,
                   enter_set=True,
                   input=True,
                   distr=['uniform'],
                   desc='embedded length - right')

        w = Float(auto_set=False,
                  enter_set=True,
                  input=True,
                  desc='crack width',
                  ctrl_range=(0, 0.01, 100))

        x_label = Str('crack opening [mm]')
        y_label = Str('force [N]')

        C_code = Str('')

        # TODO: case where Lmin is zero - gives a double sided pullout
        # should be one sided though
        def __call__(self, w, tau, l, D_f, E_f, theta, xi, phi, Ll, Lr):

            A = pi * D_f**2 / 4.
            Lmin = minimum(Ll, Lr)
            Lmax = maximum(Ll, Lr)

            Lmin = maximum(Lmin - l / 2., 0)
            Lmax = maximum(Lmax - l / 2., 0)

            l = minimum(Lr + Ll, l)

            l = l * (1 + theta)
            w = w - theta * l

            T = tau * phi * D_f * pi

            # double sided debonding
            l0 = l / 2.
            q0 = (-l0 * T + sqrt((l0 * T)**2 + w * Heaviside(w) * E_f * A * T))

            # displacement at which the debonding to the closer clamp is finished
            # the closer distance is min(L1,L2)

            w0 = Lmin * T * (Lmin + 2 * l0) / E_f / A

            # debonding from one side; the other side is clamped
            # equal to L1*T + one sided pullout with embedded length Lmax - Lmin and free length 2*L1 + l

            # force at w0
            Q0 = Lmin * T
            l1 = 2 * Lmin + l
            q1 = (-(l1) * T +
                  sqrt((l1 * T)**2 + 2 *
                       (w - w0) * Heaviside(w - w0) * E_f * A * T)) + Q0

            # displacement at debonding finished at both sides
            # equals a force of T*(larger clamp distance)

            # displacement, at which both sides are debonded
            w1 = w0 + (Lmax - Lmin) * T * ((Lmax - Lmin) + 2 *
                                           (l + 2 * Lmin)) / 2 / E_f / A
            # linear elastic response with stiffness EA/(clamp distance)
            q2 = E_f * A * (w - w1) / (Lmin + Lmax + l) + (Lmax) * T

            q0 = q0 * Heaviside(w0 - w)
            q1 = q1 * Heaviside(w - w0) * Heaviside(w1 - w)
            q2 = q2 * Heaviside(w - w1)

            q = q0 + q1 + q2

            # include breaking strain
            q = q * Heaviside(A * E_f * xi - q)
            #return q0, q1, q2 * Heaviside( A * E_f * xi - q2 ), w0 + theta * l, w1 + theta * l
            return q
예제 #13
0
파일: exp_st.py 프로젝트: rosoba/simvisage
class ExpST(ExType):
    '''Experiment: Slab Test
    '''
#    label = Str('slab test')
    implements(IExType)

    #--------------------------------------------------------------------
    # register a change of the traits with metadata 'input'
    #--------------------------------------------------------------------

    input_change = Event
    @on_trait_change('+input, ccs.input_change, +ironing_param')
    def _set_input_change(self):
        self.input_change = True

    #--------------------------------------------------------------------------------
    # specify inputs:
    #--------------------------------------------------------------------------------

    edge_length = Float(1.25, unit='m', input=True, table_field=True,
                           auto_set=False, enter_set=True)
    thickness = Float(0.06, unit='m', input=True, table_field=True,
                           auto_set=False, enter_set=True)

    # age of the concrete at the time of testing
    age = Int(28, unit='d', input=True, table_field=True,
                             auto_set=False, enter_set=True)
    loading_rate = Float(2.0, unit='mm/min', input=True, table_field=True,
                            auto_set=False, enter_set=True)

    #--------------------------------------------------------------------------
    # composite cross section
    #--------------------------------------------------------------------------

    ccs = Instance(CompositeCrossSection)
    def _ccs_default(self):
        '''default settings correspond to
        setup '7u_MAG-07-03_PZ-0708-1'
        '''
        fabric_layout_key = '2D-05-11'
#        fabric_layout_key = 'MAG-07-03'
#        fabric_layout_key = '2D-02-06a'
#        concrete_mixture_key = 'PZ-0708-1'
#        concrete_mixture_key = 'FIL-10-09'
#        concrete_mixture_key = 'barrelshell'
        concrete_mixture_key = 'PZ-0708-1'
#        orientation_fn_key = 'all0'
        orientation_fn_key = '90_0'
        n_layers = 2
        s_tex_z = 0.015 / (n_layers + 1)
        ccs = CompositeCrossSection (
                    fabric_layup_list=[
                            plain_concrete(0.035),
#                            plain_concrete(s_tex_z * 0.5),
                            FabricLayUp (
                                   n_layers=n_layers,
                                   orientation_fn_key=orientation_fn_key,
                                   s_tex_z=s_tex_z,
                                   fabric_layout_key=fabric_layout_key
                                   ),
#                            plain_concrete(s_tex_z * 0.5)
                            plain_concrete(0.5)
                                        ],
                    concrete_mixture_key=concrete_mixture_key
                    )
        return ccs

    #--------------------------------------------------------------------------
    # Get properties of the composite
    #--------------------------------------------------------------------------

    # E-modulus of the composite at the time of testing
    E_c = Property(Float, unit='MPa', depends_on='input_change', table_field=True)
    def _get_E_c(self):
        return self.ccs.get_E_c_time(self.age)

    # E-modulus of the composite after 28 days
    E_c28 = DelegatesTo('ccs', listenable=False)

    # reinforcement ration of the composite
    rho_c = DelegatesTo('ccs', listenable=False)

    #--------------------------------------------------------------------------------
    # define processing
    #--------------------------------------------------------------------------------

    # put this into the ironing procedure processor
    #
    jump_rtol = Float(0.1,
                      auto_set=False, enter_set=True,
                      ironing_param=True)


    data_array_ironed = Property(Array(float),
                                  depends_on='data_array, +ironing_param, +axis_selection')
    @cached_property
    def _get_data_array_ironed(self):
        '''remove the jumps in the displacement curves
        due to resetting the displacement gauges.
        '''
        print '*** curve ironing activated ***'

        # each column from the data array corresponds to a measured parameter
        # e.g. displacement at a given point as function of time u = f(t))
        #
        data_array_ironed = copy(self.data_array)

        for idx in range(self.data_array.shape[1]):

            # use ironing method only for columns of the displacement gauges.
            #
            if self.names_and_units[0][ idx ] != 'Kraft' and \
                self.names_and_units[0][ idx ] != 'Bezugskanal' and \
                self.names_and_units[0][ idx ] != 'Weg':

                # 1d-array corresponding to column in data_array
                data_arr = copy(data_array_ironed[:, idx])

                # get the difference between each point and its successor
                jump_arr = data_arr[1:] - data_arr[0:-1]

                # get the range of the measured data
                data_arr_range = max(data_arr) - min(data_arr)

                # determine the relevant criteria for a jump
                # based on the data range and the specified tolerances:
                jump_crit = self.jump_rtol * data_arr_range

                # get the indexes in 'data_column' after which a
                # jump exceeds the defined tolerance criteria
                jump_idx = where(fabs(jump_arr) > jump_crit)[0]

                print 'number of jumps removed in data_arr_ironed for', self.names_and_units[0][ idx ], ': ', jump_idx.shape[0]
                # glue the curve at each jump together
                for jidx in jump_idx:
                    # get the offsets at each jump of the curve
                    shift = data_arr[jidx + 1] - data_arr[jidx]
                    # shift all succeeding values by the calculated offset
                    data_arr[jidx + 1:] -= shift

                data_array_ironed[:, idx] = data_arr[:]

        return data_array_ironed


    @on_trait_change('+ironing_param')
    def process_source_data(self):
        '''read in the measured data from file and assign
        attributes after array processing.

        NOTE: if center displacement gauge ('WA_M') is missing the measured
        displacement of the cylinder ('Weg') is used instead.
        A minor mistake is made depending on how much time passes
        before the cylinder has contact with the slab.
        '''
        print '*** process source data ***'

        self._read_data_array()
        # curve ironing:
        #
        self.processed_data_array = self.data_array_ironed

        # set attributes:
        #
        self._set_array_attribs()

        if 'WA_M' not in self.factor_list:
            print '*** NOTE: Displacement gauge at center ("WA_M") missing. Cylinder displacement ("Weg") is used instead! ***'
            self.WA_M = self.Weg


    #--------------------------------------------------------------------------------
    # plot templates
    #--------------------------------------------------------------------------------

    plot_templates = {'force / deflection (all)' : '_plot_force_deflection',
#                      'force / average deflection (c; ce; e) interpolated'    : '_plot_force_deflection_avg_interpolated',
#                      'force / deflection (center)'               : '_plot_force_center_deflection',
#                      'smoothed force / deflection (center)'      : '_plot_force_center_deflection_smoothed',
#                      'force / deflection (edges)'                : '_plot_force_edge_deflection',
#                      'force / deflection (center-edges)'         : '_plot_force_center_edge_deflection',
#                      'force / average deflection (edges)'        : '_plot_force_edge_deflection_avg',
#                      'force / average deflection (center-edges)' : '_plot_force_center_edge_deflection_avg',
#                      'force / average deflection (c; ce; e)'     : '_plot_force_deflection_avg',
#                      'force / deflection (center) interpolated'  : '_plot_force_center_deflection_interpolated',
#                      'force / deflection (corner)'               : '_plot_force_corner_deflection',
#                      'edge_deflection_avg (front/back) / edge_deflection_avg (left/right)' : '_plot_edge_deflection_edge_deflection_avg',

                     }

    default_plot_template = 'force / deflection (center)'


    n_fit_window_fraction = Float(0.1)

    # get only the ascending branch of the response curve
    #
    max_force_idx = Property(Int)
    def _get_max_force_idx(self):
        '''get the index of the maximum force'''
        return argmax(-self.Kraft)

    f_asc = Property(Array)
    def _get_f_asc(self):
        '''get only the ascending branch of the response curve'''
        return -self.Kraft[:self.max_force_idx + 1]

    w_asc = Property(Array)
    def _get_w_asc(self):
        '''get only the ascending branch of the response curve'''
        return -self.WA_M[:self.max_force_idx + 1]

    n_points = Property(Int)
    def _get_n_points(self):
        return int(self.n_fit_window_fraction * len(self.w_asc))

    f_smooth = Property()
    def _get_f_smooth(self):
        return smooth(self.f_asc, self.n_points, 'flat')

    w_smooth = Property()
    def _get_w_smooth(self):
        return smooth(self.w_asc, self.n_points, 'flat')

    def _plot_force_deflection(self, axes, offset_w=0., color='blue', linewidth=1.5, linestyle='-'):
        '''plot the F-w-diagramm for all displacement gauges including maschine displacement
        '''
        xkey = 'deflection [mm]'
        ykey = 'force [kN]'

        max_force_idx = self.max_force_idx
#        max_force_idx = -2
        f_asc = -self.Kraft[:max_force_idx + 1]

        print 'self.factor_list', self.factor_list
        header_string = ''
        for i in self.factor_list[2:]:
            header_string = header_string + i + '; '
            T_arr = -getattr(self, i)
            T_asc = T_arr[:max_force_idx + 1]
            axes.plot(T_asc, f_asc, label=i)

        axes.legend()

        img_dir = os.path.join(simdb.exdata_dir, 'img_dir')
        # check if directory exist otherwise create
        #
        if os.path.isdir(img_dir) == False:
            os.makedirs(img_dir)
        test_series_dir = os.path.join(img_dir, 'slab_test_astark')
        # check if directory exist otherwise create
        #
        if os.path.isdir(test_series_dir) == False:
            os.makedirs(test_series_dir)
        out_file = os.path.join(test_series_dir, self.key)

        np.savetxt(out_file, self.processed_data_array, delimiter=';')

        # workaround for old numpy.savetxt version:
        f = open(out_file, 'r')
        temp = f.read()
        f.close()

        f = open(out_file, 'w')
        f.write(header_string)

        f.write(temp)
        f.close()



    def _plot_force_center_deflection(self, axes, offset_w=0., color='blue', linewidth=1.5, linestyle='-'):
        '''plot the F-w-diagramm for the center (c) deflection
        '''
        xkey = 'deflection [mm]'
        ykey = 'force [kN]'
        xdata = -self.WA_M
        ydata = -self.Kraft

        xdata += offset_w
#        axes.set_xlabel('%s' % (xkey,))
#        axes.set_ylabel('%s' % (ykey,))
        axes.plot(xdata, ydata, color=color, linewidth=linewidth, linestyle=linestyle)

    def _plot_force_corner_deflection(self, axes):
        '''plot the F-w-diagramm for the corner deflection (at the center of one of the supports)
        '''
        xkey = 'deflection [mm]'
        ykey = 'force [kN]'
        xdata = -self.WA_Eck
        ydata = -self.Kraft

#        axes.set_xlabel('%s' % (xkey,))
#        axes.set_ylabel('%s' % (ykey,))
        axes.plot(xdata, ydata
                       # color = c, linewidth = w, linestyle = s
                       )

    def _plot_force_center_deflection_smoothed(self, axes):
        '''plot the F-w-diagramm for the center (c) deflection (smoothed curves)
        '''
        axes.plot(self.w_smooth, self.f_smooth, color='blue', linewidth=1)
#        secant_stiffness_w10 = (f_smooth[10] - f_smooth[0]) / (w_smooth[10] - w_smooth[0])
#        w0_lin = array([0.0, w_smooth[10] ], dtype = 'float_')
#        f0_lin = array([0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_')
        # axes.plot( w0_lin, f0_lin, color = 'black' )

    def _plot_force_center_deflection_interpolated(self, axes, linestyle='-', linewidth=1.5, plot_elastic_stiffness=True):
        '''plot the F-w-diagramm for the center (c) deflection (interpolated initial stiffness)
        '''
        # get the index of the maximum stress
        max_force_idx = argmax(-self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = -self.Kraft[:max_force_idx + 1]
        w_m = -self.WA_M[:max_force_idx + 1]

#        w_m -= 0.17
#        axes.plot(w_m, f_asc, color = 'blue', linewidth = 1)

        # move the starting point of the center deflection curve to the point where the force starts
        # (remove offset in measured displacement where there is still no force measured)
        #
        idx_0 = np.where(f_asc > 0.0)[0][0]

        f_asc_cut = np.hstack([f_asc[ idx_0: ]])
        w_m_cut = np.hstack([w_m[ idx_0: ]]) - w_m[ idx_0 ]
#        print 'f_asc_cut.shape', f_asc_cut.shape
#        fw_arr = np.hstack([f_asc_cut[:, None], w_m_cut[:, None]])
#        print 'fw_arr.shape', fw_arr.shape
#        np.savetxt('ST-6c-2cm-TU_bs2_f-w_asc.csv', fw_arr, delimiter=';')
        axes.plot(w_m_cut, f_asc_cut, color='k', linewidth=linewidth, linestyle=linestyle)

        # composite E-modulus
        #
        E_c = self.E_c
        print 'E_c', E_c

        if self.thickness == 0.02 and self.edge_length == 0.80 and plot_elastic_stiffness == True:
            K_linear = E_c / 24900. * 1.056  # [MN/m]=[kN/mm] bending stiffness with respect to center force
            max_f = f_asc_cut[-1]
            w_linear = np.array([0., max_f / K_linear])
            f_linear = np.array([0., max_f])
            axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k')
        if self.thickness == 0.03 and self.edge_length == 1.25 and plot_elastic_stiffness == True:
            K_linear = E_c / 24900. * 1.267  # [MN/m]=[kN/mm] bending stiffness with respect to center force
            max_f = f_asc_cut[-1]
            w_linear = np.array([0., max_f / K_linear])
            f_linear = np.array([0., max_f])
            axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k')
        if self.thickness == 0.06 and self.edge_length == 1.25 and plot_elastic_stiffness == True:
            K_linear = E_c / 24900. * 10.14  # [MN/m]=[kN/mm] bending stiffness with respect to center force
            max_f = f_asc_cut[-1]
            w_linear = np.array([0., max_f / K_linear])
            f_linear = np.array([0., max_f])
            axes.plot(w_linear, f_linear, linewidth=linewidth, linestyle='--', color='k')

    def _plot_force_edge_deflection(self, axes):
        '''plot the F-w-diagramm for the edge (e) deflections
        '''
        max_force_idx = self.max_force_idx
        f_asc = self.f_asc
        w_v_asc = -self.WA_V[:max_force_idx + 1]
        w_h_asc = -self.WA_H[:max_force_idx + 1]
        w_l_asc = -self.WA_L[:max_force_idx + 1]
        w_r_asc = -self.WA_R[:max_force_idx + 1]
        axes.plot(w_v_asc, f_asc, color='blue', linewidth=1)
        axes.plot(w_h_asc, f_asc, color='blue', linewidth=1)
        axes.plot(w_l_asc, f_asc, color='green', linewidth=1)
        axes.plot(w_r_asc, f_asc, color='green', linewidth=1)

    def _plot_force_edge_deflection_avg(self, axes):
        '''plot the average F-w-diagramm for the edge (e) deflections
        '''
        max_force_idx = self.max_force_idx
        f_asc = self.f_asc
        w_v_asc = -self.WA_V[:max_force_idx + 1]
        w_h_asc = -self.WA_H[:max_force_idx + 1]
        w_l_asc = -self.WA_L[:max_force_idx + 1]
        w_r_asc = -self.WA_R[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_vh_asc = (w_v_asc + w_h_asc) / 2
        w_lr_asc = (w_l_asc + w_r_asc) / 2
        axes.plot(w_vh_asc, f_asc, color='blue', linewidth=1, label='w_vh')
        axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr')
        axes.legend()

    def _plot_edge_deflection_edge_deflection_avg(self, axes):
        '''plot the average edge (e) deflections for the front/back and left/right
        '''
        max_force_idx = self.max_force_idx
        w_v_asc = -self.WA_V[:max_force_idx + 1]
        w_h_asc = -self.WA_H[:max_force_idx + 1]
        w_l_asc = -self.WA_L[:max_force_idx + 1]
        w_r_asc = -self.WA_R[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_vh_asc = (w_v_asc + w_h_asc) / 2
        w_lr_asc = (w_l_asc + w_r_asc) / 2
        axes.plot(w_vh_asc, w_lr_asc, color='blue', linewidth=1, label='w_vh / w_lr')
        axes.plot(np.array([0, w_vh_asc[-1]]), np.array([0, w_vh_asc[-1]]), color='k', linewidth=1, linestyle='-')
        axes.legend()

    def _plot_force_center_edge_deflection(self, axes):
        '''plot the F-w-diagramm for the center-edge (ce) deflections
        '''
        max_force_idx = argmax(-self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = -self.Kraft[:max_force_idx + 1]
        w_ml_asc = -self.WA_ML[:max_force_idx + 1]
        w_mr_asc = -self.WA_MR[:max_force_idx + 1]
        axes.plot(w_ml_asc, f_asc, color='blue', linewidth=1, label='w_ml')
        axes.plot(w_mr_asc, f_asc, color='blue', linewidth=1, label='w_mr')
        axes.legend()

    def _plot_force_center_edge_deflection_avg(self, axes):
        '''plot the average F-w-diagramm for the center-edge (ce) deflections
        '''
        # get the index of the maximum stress
        max_force_idx = argmax(-self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = -self.Kraft[:max_force_idx + 1]
        w_ml_asc = -self.WA_ML[:max_force_idx + 1]
        w_mr_asc = -self.WA_MR[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2
        axes.plot(w_mlmr_asc, f_asc, color='blue', linewidth=1)

    def _plot_force_deflection_avg(self, axes):
        '''plot the average F-w-diagramms for the center(c), center-edge (ce) and edge(vh) and edge (lr) deflections
        '''
        # get the index of the maximum stress
        max_force_idx = argmax(-self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = -self.Kraft[:max_force_idx + 1]

        w_m = -self.WA_M[:max_force_idx + 1]
        axes.plot(w_m, f_asc, color='blue', linewidth=1)

        # ## center-edge deflection (ce)
        w_ml_asc = -self.WA_ML[:max_force_idx + 1]
        w_mr_asc = -self.WA_MR[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2
        axes.plot(w_mlmr_asc, f_asc, color='red', linewidth=1)

        # ## edge deflections (e)
        w_v_asc = -self.WA_V[:max_force_idx + 1]
        w_h_asc = -self.WA_H[:max_force_idx + 1]
        w_l_asc = -self.WA_L[:max_force_idx + 1]
        w_r_asc = -self.WA_R[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_vh_asc = (w_v_asc + w_h_asc) / 2
        w_lr_asc = (w_l_asc + w_r_asc) / 2
        axes.plot(w_vh_asc, f_asc, color='green', linewidth=1, label='w_vh')
        axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr')

#        # set axis-labels
#        xkey = 'deflection [mm]'
#        ykey = 'force [kN]'
#        axes.set_xlabel('%s' % (xkey,))
#        axes.set_ylabel('%s' % (ykey,))

    def _plot_force_deflection_avg_interpolated(self, axes, linewidth=1):
        '''plot the average F-w-diagrams for the center(c), center-edge (ce) and edge(vh) and edge (lr) deflections
        NOTE: center deflection curve is cut at its starting point in order to remove offset in the dispacement meassurement
        '''
        # get the index of the maximum stress
        max_force_idx = argmax(-self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = -self.Kraft[:max_force_idx + 1]
        w_m = -self.WA_M[:max_force_idx + 1]

#        w_m -= 0.17
#        axes.plot(w_m, f_asc, color = 'blue', linewidth = 1)

        # move the starting point of the center deflection curve to the point where the force starts
        # (remove offset in measured displacement where there is still no force measured)
        #
        idx_0 = np.where(f_asc > 0.05)[0][0]

        f_asc_cut = f_asc[ idx_0: ]
        w_m_cut = w_m[ idx_0: ] - w_m[ idx_0 ]
        axes.plot(w_m_cut, f_asc_cut, color='k', linewidth=linewidth)

        # plot machine displacement (hydraulic cylinder)
        #
#        Weg_asc = -self.Weg[ :max_force_idx + 1 ]
#        axes.plot(Weg_asc, f_asc, color='k', linewidth=1.5)

        # ## center-edge deflection (ce)
        w_ml_asc = -self.WA_ML[:max_force_idx + 1]
        w_mr_asc = -self.WA_MR[:max_force_idx + 1]
        # get the average displacement values of the corresponding displacement gauges
        w_mlmr_asc = (w_ml_asc + w_mr_asc) / 2
#        axes.plot(w_mlmr_asc, f_asc, color='red', linewidth=1)
        axes.plot(w_ml_asc, f_asc, color='k', linewidth=linewidth)
        axes.plot(w_mr_asc, f_asc, color='k', linewidth=linewidth)

        # ## edge deflections (e)
        w_v_asc = -self.WA_V[:max_force_idx + 1]
        w_h_asc = -self.WA_H[:max_force_idx + 1]
        w_l_asc = -self.WA_L[:max_force_idx + 1]
        w_r_asc = -self.WA_R[:max_force_idx + 1]
        axes.plot(w_v_asc, f_asc, color='grey', linewidth=linewidth)
        axes.plot(w_h_asc, f_asc, color='grey', linewidth=linewidth)
        axes.plot(w_l_asc, f_asc, color='k', linewidth=linewidth)
        axes.plot(w_r_asc, f_asc, color='k', linewidth=linewidth)

        # get the average displacement values of the corresponding displacement gauges
#        w_vh_asc = (w_v_asc + w_h_asc) / 2
#        w_lr_asc = (w_l_asc + w_r_asc) / 2
#        axes.plot(w_vh_asc, f_asc, color='green', linewidth=1, label='w_vh')
#        axes.plot(w_lr_asc, f_asc, color='blue', linewidth=1, label='w_lr')

        # save 'F-w-arr_m-mlmr-vh-lr' in directory "/simdb/simdata/exp_st"
#        simdata_dir = os.path.join(simdb.simdata_dir, 'exp_st')
#        if os.path.isdir(simdata_dir) == False:
#            os.makedirs(simdata_dir)
#        filename = os.path.join(simdata_dir, 'F-w-arr_m-mlmr-vh-lr_' + self.key + '.csv')
#        Fw_m_mlmr_vh_lr_arr = np.hstack([f_asc[:, None], w_m[:, None] - w_m[ idx_0 ], w_mlmr_asc[:, None], w_vh_asc[:, None], w_lr_asc[:, None]])
#        print 'Fw_m_mlmr_vh_lr_arr'
#        np.savetxt(filename, Fw_m_mlmr_vh_lr_arr, delimiter=';')
#        print 'F-w-curves for center, middle, edges saved to file %s' % (filename)

    #--------------------------------------------------------------------------------
    # view
    #--------------------------------------------------------------------------------

    traits_view = View(VGroup(
                         Group(
                              Item('jump_rtol', format_str="%.4f"),
                              label='curve_ironing'
                              ),
                         Group(
                              Item('thickness', format_str="%.3f"),
                              Item('edge_length', format_str="%.3f"),
                              label='geometry'
                              ),
                         Group(
                              Item('loading_rate'),
                              Item('age'),
                              label='loading rate and age'
                              ),
                         Group(
                              Item('E_c', show_label=True, style='readonly', format_str="%.0f"),
                              Item('ccs@', show_label=False),
                              label='composite cross section'
                              )
                         ),
                        scrollable=True,
                        resizable=True,
                        height=0.8,
                        width=0.6
                        )
예제 #14
0
class CBClampedRandXi(RF):
    '''
    Crack bridged by a fiber with constant
    frictional interface to rigid; free fiber end;
    '''

    implements(IRF)
    title = Str('crack bridge with rigid matrix')
    tau = Float(2.5,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'])

    r = Float(0.013,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform', 'norm'],
              desc='fiber radius')

    E_f = Float(72e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    m = Float(5.,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'])

    sV0 = Float(3.e-3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    V_f = Float(0.0175,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    lm = Float(np.inf,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'])

    w = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    x_label = Str('crack opening [mm]')
    y_label = Str('composite stress [MPa]')

    C_code = Str('')

    def __call__(self, w, tau, E_f, V_f, r, m, sV0):
        '''free and fixed fibers combined
        the failure probability of fixed fibers
        is evaluated by integrating only
        between -lm/2 and lm/2.
        Only intact fibers are considered (no pullout contribution)'''
        T = 2. * tau / r + 1e-10
        k = np.sqrt(T / E_f)
        ef0cb = k * np.sqrt(w)
        s = ((T * (m + 1) * sV0**m) / (2. * E_f * pi * r**2))**(1. / (m + 1))
        Gxi_deb = 1 - np.exp(-(ef0cb / s)**(m + 1))
        if w == 1.00:
            a0 = ef0cb * E_f / T
            print np.sum(a0 > 500.) / float(np.sum(a0 > -0.1))
        return ef0cb * (1 - Gxi_deb) * E_f * V_f * r**2
예제 #15
0
class SimDT(IBVModel):
    '''Simulation: Disk Test
    '''

    implements(ISimModel)

    material_density_roof = Float(-22.4e-3)  # [MN/m^3]

    #----------------------------------------------------
    # elements
    #----------------------------------------------------

    n_elems = Int(50, input=True)
    thickness = Float(1.0, input=True)

    vtk_r = Float(0.9, input=True)

    # fets used for roof
    #
    fets_disk = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _fets_disk_default(self):
        # fe_quad_serendipity_roof is defined in base class
        # connected with material properties of the roof
        #
        mats = MATS2DElastic(E=3.1e5, nu=0.0, stress_state='plane_stress')
        fets = FETS2D4Q8U(mats_eval=mats)
        fets.vtk_r *= self.vtk_r
        return fets

    geo_disk = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_geo_disk(self):
        # list of local origins of each roof defined in global coordinates
        # (for MRDetail two roofs are considered due to symmetry)
        #
        gt = GeoSquare2Circle(circle_center=[0.0, 0.0],
                              circle_radius=1.0,
                              square_edge=4.0)
        return gt

    #----------------------------------------------------
    # fe-grids
    #----------------------------------------------------

    fe_disk_grid = Property(Instance(FEGrid), depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_disk_grid(self):
        fe_grid = FEGrid(coord_min=(-1, -1),
                         coord_max=(1, 1),
                         geo_transform=self.geo_disk,
                         shape=(self.n_elems, self.n_elems),
                         fets_eval=self.fets_disk)
        return fe_grid

    bc_fixed = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_fixed(self):
        fe_disk_grid = self.fe_disk_grid

        extension = 0.1
        alpha_45 = math.pi / 4.0

        bc00 = BCDof(var='u',
                     dof=fe_disk_grid[0, 0, 0, 0].dofs[0, 0, 1],
                     value=-extension * math.cos(alpha_45))

        bc00_link = BCDof(var='u',
                          dof=fe_disk_grid[0, 0, 0, 0].dofs[0, 0, 0],
                          link_dofs=[fe_disk_grid[0, 0, 0, 0].dofs[0, 0, 1]],
                          link_coeffs=[1.0],
                          value=0)

        bc10 = BCDof(var='u',
                     dof=fe_disk_grid[-1, 0, -1, 0].dofs[0, 0, 1],
                     value=-extension * math.cos(alpha_45))

        bc10_link = BCDof(var='u',
                          dof=fe_disk_grid[-1, 0, -1, 0].dofs[0, 0, 0],
                          link_dofs=[fe_disk_grid[-1, 0, -1, 0].dofs[0, 0, 1]],
                          link_coeffs=[-1.0],
                          value=0)

        bc11 = BCDof(var='u',
                     dof=fe_disk_grid[-1, -1, -1, -1].dofs[0, 0, 1],
                     value=extension * math.cos(alpha_45))

        bc11_link = BCDof(
            var='u',
            dof=fe_disk_grid[-1, -1, -1, -1].dofs[0, 0, 0],
            link_dofs=[fe_disk_grid[-1, -1, -1, -1].dofs[0, 0, 1]],
            link_coeffs=[1.0],
            value=0)

        bc01 = BCDof(var='u',
                     dof=fe_disk_grid[0, -1, 0, -1].dofs[0, 0, 1],
                     value=extension * math.cos(alpha_45))

        bc01_link = BCDof(var='u',
                          dof=fe_disk_grid[0, -1, 0, -1].dofs[0, 0, 0],
                          link_dofs=[fe_disk_grid[0, -1, 0, -1].dofs[0, 0, 1]],
                          link_coeffs=[-1.0],
                          value=0)

        n_xy = self.n_elems / 2

        bc_bottom = BCDof(var='u',
                          dof=fe_disk_grid[n_xy, 0, 0, 0].dofs[0, 0, 1],
                          value=-extension)
        bc_right = BCDof(var='u',
                         dof=fe_disk_grid[-1, n_xy, -1, 0].dofs[0, 0, 0],
                         value=extension)
        bc_top = BCDof(var='u',
                       dof=fe_disk_grid[n_xy, -1, 0, -1].dofs[0, 0, 1],
                       value=extension)
        bc_left = BCDof(var='u',
                        dof=fe_disk_grid[0, n_xy, 0, 0].dofs[0, 0, 0],
                        value=-extension)

        return [
            bc_left, bc_right, bc_top, bc_bottom, bc00, bc00_link, bc10,
            bc10_link, bc11, bc11_link, bc01, bc01_link
        ]

    #----------------------------------------------------
    # ps_study
    #----------------------------------------------------
    def peval(self):
        '''
        Evaluate the model and return the array of results specified
        in the method get_sim_outputs.
        '''

        # DISPLACEMENT
        #
        U = self.tloop.eval()

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='$u_z$', unit='[mm]'),
        ]

    #----------------------------------------------------
    # response tracer
    #----------------------------------------------------

    rtrace_list = List

    def _rtrace_list_default(self):
        return [self.max_princ_stress, self.sig_app, self.u]

    max_princ_stress = Instance(RTraceDomainListField)

    def _max_princ_stress_default(self):
        return RTraceDomainListField(
            name='max principle stress',
            idx=0,
            var='max_principle_sig',
            warp=True,
            #                                      position = 'int_pnts',
            record_on='update',
        )

    sig_app = Property(Instance(RTraceDomainListField),
                       depends_on='+ps_levels, +input')

    @cached_property
    def _get_sig_app(self):
        return RTraceDomainListField(
            name='sig_app',
            position='int_pnts',
            var='sig_app',
            record_on='update',
        )

    u = Property(Instance(RTraceDomainListField),
                 depends_on='+ps_levels, +input')

    @cached_property
    def _get_u(self):
        return RTraceDomainListField(
            name='displacement',
            var='u',
            warp=True,
            record_on='update',
        )

    #----------------------------------------------------
    # time loop
    #----------------------------------------------------

    tline = Instance(TLine)

    def _tline_default(self):
        return TLine(min=0.0, step=1.0, max=1.0)

    tloop = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_tloop(self):

        roof = self.fe_disk_grid

        # self.bc_roof_deadweight + \
        bc_list = self.bc_fixed

        ts = TS(sdomain=[roof],
                dof_resultants=True,
                bcond_list=bc_list,
                rtrace_list=self.rtrace_list)

        # Add the time-loop control
        #
        tloop = TLoop(tstepper=ts, tolerance=1e-4, tline=self.tline)

        return tloop
예제 #16
0
class ExpEM(ExType):
    '''Experiment: Elastic Modulus Test
    '''
    #    label = Str('three point bending test')

    implements(IExType)

    file_ext = 'TRA'

    #--------------------------------------------------------------------
    # register a change of the traits with metadata 'input'
    #--------------------------------------------------------------------

    input_change = Event

    @on_trait_change('+input, ccs.input_change, +ironing_param')
    def _set_input_change(self):
        self.input_change = True

    #--------------------------------------------------------------------------------
    # specify inputs:
    #--------------------------------------------------------------------------------

    edge_length = Float(0.06,
                        unit='m',
                        input=True,
                        table_field=True,
                        auto_set=False,
                        enter_set=True)
    height = Float(0.12,
                   unit='m',
                   input=True,
                   table_field=True,
                   auto_set=False,
                   enter_set=True)
    gauge_length = Float(0.10,
                         unit='m',
                         input=True,
                         table_field=True,
                         auto_set=False,
                         enter_set=True)

    # age of the concrete at the time of testing
    age = Int(39,
              unit='d',
              input=True,
              table_field=True,
              auto_set=False,
              enter_set=True)
    loading_rate = Float(0.6,
                         unit='MPa/s',
                         input=True,
                         table_field=True,
                         auto_set=False,
                         enter_set=True)

    #--------------------------------------------------------------------------
    # composite cross section
    #--------------------------------------------------------------------------

    ccs = Instance(CompositeCrossSection)

    def _ccs_default(self):
        '''default settings correspond to 
        setup '7u_MAG-07-03_PZ-0708-1'
        '''
        #        fabric_layout_key = 'MAG-07-03'
        #        fabric_layout_key = '2D-02-06a'
        fabric_layout_key = '2D-05-11'
        #        concrete_mixture_key = 'PZ-0708-1'
        concrete_mixture_key = 'FIL-10-09'
        orientation_fn_key = 'all0'
        #        orientation_fn_key = 'all90'
        #        orientation_fn_key = '90_0'
        n_layers = 12
        s_tex_z = 0.060 / (n_layers + 1)
        ccs = CompositeCrossSection(fabric_layup_list=[
            plain_concrete(s_tex_z * 0.5),
            FabricLayUp(n_layers=n_layers,
                        orientation_fn_key=orientation_fn_key,
                        s_tex_z=s_tex_z,
                        fabric_layout_key=fabric_layout_key),
            plain_concrete(s_tex_z * 0.5)
        ],
                                    concrete_mixture_key=concrete_mixture_key)
        return ccs

    #--------------------------------------------------------------------------
    # Get properties of the composite
    #--------------------------------------------------------------------------

    # E-modulus of the composite at the time of testing
    E_c = Property(Float,
                   unit='MPa',
                   depends_on='input_change',
                   table_field=True)

    def _get_E_c(self):
        return self.ccs.get_E_c_time(self.age)

    # E-modulus of the composite after 28 days
    E_c28 = DelegatesTo('ccs', listenable=False)

    # reinforcement ration of the composite
    rho_c = DelegatesTo('ccs', listenable=False)

    #--------------------------------------------------------------------------------
    # define processing
    #--------------------------------------------------------------------------------

    def _read_data_array(self):
        ''' Read the experiment data. 
        '''
        print 'READ FILE'
        _data_array = np.loadtxt(self.data_file,
                                 delimiter=';',
                                 skiprows=2,
                                 usecols=(4, 5, 10, 17, 20))
        self.data_array = _data_array

    names_and_units = Property

    @cached_property
    def _get_names_and_units(self):
        ''' Set the names and units of the measured data.
        '''
        names = ['delta_u1', 'delta_u2', 'w', 'F', 'time']
        units = ['mm', 'mm', 'mm', 'kN', 's']
        return names, units


#0#"Arbeit";
#1#"Dehn. abs";
#2#"Dehn. abs (2. Kanal)";
#3#"Dehnung";

#4#"Dehnung (1. Kanal)";
#5#"Dehnung (2. Kanal)";

#6#"Dehnung nominell";
#7#"DeltaE";
#8#"E1 korr";
#9#"E2 korr";

#10#"Kolbenweg";

#11#"Kolbenweg abs.";
#12#"Lastrahmen";
#13#"LE-Kanal";
#14#"PrXXXfzeit";
#15#"Querdehnung";
#16#"S korr";
#17#"Standardkraft";
#18#"Vorlaufzeit";
#19#"Weg";
#20#"Zeit";
#21#"Zyklus"

#
#"Nm";
#"mm";
#"mm";
#"mm";
#"mm";
#"mm";
#"mm";
#"%";
#"mm";
#" ";
#"mm";
#"mm";
#" ";
#"mm";
#"s";
#"mm";
#" ";
#"N";
#"s";
#"mm";
#"s";
#" "

#--------------------------------------------------------------------------------
# plot templates
#--------------------------------------------------------------------------------

    plot_templates = {
        'force / displacement': '_plot_force_displacement',
        'stress / strain': '_plot_stress_strain',
        'stress / time': '_plot_stress_time',
    }

    default_plot_template = 'force / displacement'

    def _plot_force_displacement(self, axes):
        xkey = 'deflection [mm]'
        ykey = 'force [kN]'
        xdata = self.w
        ydata = self.F / 1000.  # convert from [N] to [kN]
        axes.set_xlabel('%s' % (xkey, ))
        axes.set_ylabel('%s' % (ykey, ))
        axes.plot(xdata, ydata
                  # color = c, linewidth = w, linestyle = s
                  )

    def _plot_stress_strain(self, axes):
        sig = (self.F / 1000000.) / (self.edge_length**2
                                     )  # convert from [N] to [MN]
        eps1 = (self.delta_u1 / 1000.) / self.gauge_length
        eps2 = (self.delta_u2 / 1000.) / self.gauge_length
        eps_m = (eps1 + eps2) / 2.
        axes.plot(eps_m, sig, color='blue', linewidth=2)

    def _plot_stress_time(self, axes):
        sig = (self.F / 1000000.) / (self.edge_length**2
                                     )  # convert from [N] to [MN]
        axes.plot(self.time, sig, color='blue', linewidth=2)

    def _plot_displ_time(self, axes):
        axes.plot(self.time, self.displ, color='blue', linewidth=2)

    #--------------------------------------------------------------------------------
    # view
    #--------------------------------------------------------------------------------

    traits_view = View(VGroup(
        Group(Item('edge_length', format_str="%.3f"),
              Item('height', format_str="%.3f"),
              Item('gauge_length', format_str="%.3f"),
              label='geometry'),
        Group(Item('loading_rate'), Item('age'), label='loading rate and age'),
        Group(Item('E_c', show_label=True, style='readonly',
                   format_str="%.0f"),
              Item('ccs@', show_label=False),
              label='composite cross section')),
                       scrollable=True,
                       resizable=True,
                       height=0.8,
                       width=0.6)
예제 #17
0
class SimTTBC(IBVModel):
    '''Simulation: Tensile Test Buttsrap Clamping
    '''
    implements(ISimModel)

    #===========================================================================
    # Speciment geometry and discretization parameters
    #===========================================================================
    specimen_ne_x = Int(2,
                        input=True,
                        label='number of elements in x-direction')
    specimen_ne_y = Int(2,
                        input=True,
                        label='number of elements in y-direction')
    specimen_thickness = Float(0.01,
                               input=True,
                               label='thickness of the tensile specimen')
    specimen_length = Float(0.6,
                            input=True,
                            label='length of the tensile specimen')

    specimen_width = Float(0.1,
                           input=True,
                           label='length of the tensile specimen')

    #===========================================================================
    # Buttstrap geometry and discretization parameters
    #===========================================================================
    buttstrap_length = Int(0.2, input=True, label='length of the buttstrap')
    buttstrap_ne_y = Int(
        4, input=True, label='number of elements in buttstrap in y-direction')
    buttstrap_ne_x = Int(
        7, input=True, label='number of elements in buttstrap in x-direction')

    buttstrap_max_thickness = Float(0.04,
                                    input=True,
                                    label='maximum thickness of the buttstrap')
    buttstrap_min_thickness = Float(
        0.04, input=True, label='mimnimum thickness of the buttstrsp')

    #===========================================================================
    # Elastomer geometry
    #===========================================================================
    elastomer_thickness = Float(0.002,
                                input=True,
                                label='thickness of the elastomer')

    elastomer_ne_y = Int(
        1, input=True, label='number of elements in buttstrap in y-direction')
    elastomer_ne_x = Property

    def _get_elastomer_ne_x(self):
        return self.buttstrap_ne_x

    #===========================================================================
    # Friction interface geometry
    #===========================================================================
    friction_thickness = Float(0.005,
                               input=True,
                               label='thickness of the elastomer')

    friction_ne_y = Int(1,
                        input=True,
                        label='number of elements in buttstrap in y-direction')
    friction_ne_x = Property

    def _get_friction_ne_x(self):
        return self.buttstrap_ne_x

    vtk_r = Float(1.0, input=True)

    #===========================================================================
    # Element types
    #===========================================================================

    E_specimen = Int(31000.0,
                     input=True,
                     label='E Modulus of the specimen [MPa]')

    nu_specimen = Int(0.2, input=True, label='E Modulus of the specimen [-]')

    specimen_fets = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _specimen_fets_default(self):
        # fe_quad_serendipity_roof is defined in base class
        # connected with material properties of the roof
        #
        E_eff = self.E_specimen * self.specimen_width
        mats = MATS2DElastic(E=E_eff,
                             nu=self.nu_specimen,
                             stress_state='plane_stress')
        fets = FETS2D4Q8U(mats_eval=mats)
        fets.vtk_r *= self.vtk_r
        return fets

    E_buttstrap = Int(210000.0,
                      input=True,
                      label='E Modulus of the buttstrap [MPa]')

    nu_buttstrap = Int(0.2,
                       input=True,
                       label='Poisson ratio of the buttstrap [-]')

    buttstrap_fets = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _buttstrap_fets_default(self):
        # fe_quad_serendipity_roof is defined in base class
        # connected with material properties of the roof
        #
        E_eff = self.E_buttstrap * self.specimen_width
        mats = MATS2DElastic(E=E_eff,
                             nu=self.nu_buttstrap,
                             stress_state='plane_stress')
        fets = FETS2D4Q8U(mats_eval=mats)
        fets.vtk_r *= self.vtk_r
        return fets

    E_elastomer = Int(100.0,
                      input=True,
                      label='E Modulus of the elastomer [MPa]')

    nu_elastomer = Int(0.3,
                       input=True,
                       label='Poisson ratio of the elastomer [-]')

    elastomer_fets = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _elastomer_fets_default(self):
        # fe_quad_serendipity_roof is defined in base class
        # connected with material properties of the roof
        #
        E_eff = self.E_buttstrap * self.specimen_width
        mats = MATS2DElastic(E=E_eff,
                             nu=self.nu_elastomer,
                             stress_state='plane_stress')
        fets = FETS2D4Q8U(mats_eval=mats)
        fets.vtk_r *= self.vtk_r
        return fets

    g = Float(400000,
              input=True,
              label='Shear stiffness between elastomer and specimen')

    t_max = Float(50,
                  input=True,
                  label='Frictional stress between elastomer and specimen')

    friction_fets = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _friction_fets_default(self):
        width = self.specimen_width
        G = self.g * width
        T_max = self.t_max * width

        ifopen_law = MFnLineArray(ydata=[-1.0e+1, 0., 1.0e+10],
                                  xdata=[-1., 0., 1.])
        mats_ifopen = MATS1DElastic(stress_strain_curve=ifopen_law)

        mats = MATS1D5Bond(mats_phase1=MATS1DElastic(E=0),
                           mats_phase2=MATS1DElastic(E=0),
                           mats_ifslip=MATS1DPlastic(E=G,
                                                     sigma_y=T_max,
                                                     K_bar=0.,
                                                     H_bar=0.),
                           mats_ifopen=mats_ifopen)

        fets = FETS1D52L6ULRH(mats_eval=mats)  #quadratic
        fets.vtk_r *= self.vtk_r
        return fets

    #===========================================================================
    # Geometry transformation
    #===========================================================================
    specimen_cl_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_specimen_cl_geo(self):
        def geo_transform(points):
            points[:, 0] *= self.buttstrap_length
            points[:, 1] *= self.specimen_thickness
            return points

        return geo_transform

    specimen_fl_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_specimen_fl_geo(self):
        def geo_transform(points):
            points[:, 0] *= self.specimen_length
            points[:, 0] += self.buttstrap_length
            points[:, 1] *= self.specimen_thickness
            return points

        return geo_transform

    buttstrap_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_buttstrap_geo(self):
        def geo_transform(points):
            x, y = points.T
            x *= self.buttstrap_length
            h_max = self.buttstrap_max_thickness
            h_min = self.buttstrap_min_thickness
            y *= (h_max - (h_max - h_min) / self.buttstrap_length * x)
            y_offset = (self.specimen_thickness + self.friction_thickness +
                        self.elastomer_thickness)
            points[:, 0], points[:, 1] = x, y + y_offset
            return points

        return geo_transform

    buttstrap_clamp_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_buttstrap_clamp_geo(self):
        def geo_transform(points):
            x, y = points.T
            x *= self.buttstrap_length
            x -= self.buttstrap_length
            y *= self.buttstrap_max_thickness
            y_offset = (self.specimen_thickness + self.friction_thickness +
                        self.elastomer_thickness)
            points[:, 0], points[:, 1] = x, y + y_offset
            return points

        return geo_transform

    elastomer_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_elastomer_geo(self):
        def geo_transform(points):
            x, y = points.T
            x *= self.buttstrap_length
            h = self.elastomer_thickness
            y *= h
            y_offset = self.specimen_thickness + self.friction_thickness
            points[:, 0], points[:, 1] = x, y + y_offset
            return points

        return geo_transform

    friction_geo = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_friction_geo(self):
        def geo_transform(points):
            x, y = points.T
            x *= self.buttstrap_length
            h = self.friction_thickness
            y *= h
            y_offset = self.specimen_thickness
            points[:, 0], points[:, 1] = x, y + y_offset
            return points

        return geo_transform

    #===========================================================================
    # FE-grids
    #===========================================================================

    fe_domain = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_domain(self):
        return FEDomain()

    specimen_fl_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_specimen_fl_fe_level(self):
        return FERefinementGrid(name='specimen free level',
                                fets_eval=self.specimen_fets,
                                domain=self.fe_domain)

    specimen_cl_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_specimen_cl_fe_level(self):
        return FERefinementGrid(name='specimen clamped level',
                                fets_eval=self.specimen_fets,
                                domain=self.fe_domain)

    buttstrap_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_buttstrap_fe_level(self):
        return FERefinementGrid(name='buttstrap level',
                                fets_eval=self.buttstrap_fets,
                                domain=self.fe_domain)

    buttstrap_clamp_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_buttstrap_clamp_fe_level(self):
        return FERefinementGrid(name='buttstrap clamp level',
                                fets_eval=self.buttstrap_fets,
                                domain=self.fe_domain)

    elastomer_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_elastomer_fe_level(self):
        return FERefinementGrid(name='elastomer level',
                                fets_eval=self.elastomer_fets,
                                domain=self.fe_domain)

    friction_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_friction_fe_level(self):
        return FERefinementGrid(name='friction level',
                                fets_eval=self.friction_fets,
                                domain=self.fe_domain)

    specimen_fl_fe_grid = Property(Instance(FEGrid),
                                   depends_on='+ps_levels, +input')

    @cached_property
    def _get_specimen_fl_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.specimen_fl_fe_level,
                         geo_transform=self.specimen_fl_geo,
                         shape=(self.specimen_ne_x, self.specimen_ne_y),
                         fets_eval=self.specimen_fets)
        return fe_grid

    specimen_cl_fe_grid = Property(Instance(FEGrid),
                                   depends_on='+ps_levels, +input')

    @cached_property
    def _get_specimen_cl_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.specimen_cl_fe_level,
                         geo_transform=self.specimen_cl_geo,
                         shape=(self.buttstrap_ne_x, self.specimen_ne_y),
                         fets_eval=self.specimen_fets)
        return fe_grid

    buttstrap_fe_grid = Property(Instance(FEGrid),
                                 depends_on='+ps_levels, +input')

    @cached_property
    def _get_buttstrap_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.buttstrap_fe_level,
                         geo_transform=self.buttstrap_geo,
                         shape=(self.buttstrap_ne_x, self.buttstrap_ne_y),
                         fets_eval=self.buttstrap_fets)
        return fe_grid

    buttstrap_clamp_fe_grid = Property(Instance(FEGrid),
                                       depends_on='+ps_levels, +input')

    @cached_property
    def _get_buttstrap_clamp_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.buttstrap_clamp_fe_level,
                         geo_transform=self.buttstrap_clamp_geo,
                         shape=(1, self.buttstrap_ne_y),
                         fets_eval=self.buttstrap_fets)
        return fe_grid

    elastomer_fe_grid = Property(Instance(FEGrid),
                                 depends_on='+ps_levels, +input')

    @cached_property
    def _get_elastomer_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.elastomer_fe_level,
                         geo_transform=self.elastomer_geo,
                         shape=(self.elastomer_ne_x, self.elastomer_ne_y),
                         fets_eval=self.elastomer_fets)
        return fe_grid

    friction_fe_grid = Property(Instance(FEGrid),
                                depends_on='+ps_levels, +input')

    @cached_property
    def _get_friction_fe_grid(self):
        fe_grid = FEGrid(coord_min=(0, 0),
                         coord_max=(1, 1),
                         level=self.friction_fe_level,
                         geo_transform=self.friction_geo,
                         shape=(self.friction_ne_x, self.friction_ne_y),
                         fets_eval=self.friction_fets)
        return fe_grid

    #===========================================================================
    # Boundary conditions
    #===========================================================================
    bc_list = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_list(self):

        sp_fl_grid = self.specimen_fl_fe_grid
        sp_cl_grid = self.specimen_cl_fe_grid
        bs_grid = self.buttstrap_fe_grid
        bs_clamp_grid = self.buttstrap_clamp_fe_grid
        el_grid = self.elastomer_fe_grid
        fl_grid = self.friction_fe_grid

        link_sp_fl_cl = BCDofGroup(
            var='u',
            value=0.,
            dims=[0, 1],
            get_dof_method=sp_cl_grid.get_right_dofs,
            get_link_dof_method=sp_fl_grid.get_left_dofs,
            link_coeffs=[1.])

        link_fl_sp = BCDofGroup(var='u',
                                value=0.,
                                dims=[0, 1],
                                get_dof_method=fl_grid.get_bottom_dofs,
                                get_link_dof_method=sp_cl_grid.get_top_dofs,
                                link_coeffs=[1.])

        link_el_fl = BCDofGroup(var='u',
                                value=0.,
                                dims=[0, 1],
                                get_dof_method=el_grid.get_bottom_dofs,
                                get_link_dof_method=fl_grid.get_top_dofs,
                                link_coeffs=[1.])

        link_bs_el = BCDofGroup(var='u',
                                value=0.,
                                dims=[0, 1],
                                get_dof_method=bs_grid.get_bottom_dofs,
                                get_link_dof_method=el_grid.get_top_dofs,
                                link_coeffs=[1.])

        link_bs_clamp = BCDofGroup(var='u',
                                   value=0.,
                                   dims=[0, 1],
                                   get_dof_method=bs_clamp_grid.get_right_dofs,
                                   get_link_dof_method=bs_grid.get_left_dofs,
                                   link_coeffs=[1.])

        symx_bc = BCSlice(var='u',
                          slice=sp_fl_grid[-1, :, -1, :],
                          dims=[0],
                          value=0)

        symy_fl_bc = BCSlice(var='u',
                             slice=sp_fl_grid[:, 0, :, 0],
                             dims=[1],
                             value=0)

        symy_cl_bc = BCSlice(var='u',
                             slice=sp_cl_grid[:, 0, :, 0],
                             dims=[1],
                             value=0)

        cntl_bc = BCSlice(var='u',
                          slice=bs_clamp_grid[0, :, 0, :],
                          dims=[0],
                          value=-0.001)

        return [
            symx_bc, symy_fl_bc, symy_cl_bc, cntl_bc, link_sp_fl_cl,
            link_bs_clamp, link_fl_sp, link_el_fl, link_bs_el
        ]

    #----------------------------------------------------
    # ps_study
    #----------------------------------------------------
    def peval(self):
        '''
        Evaluate the model and return the array of results specified
        in the method get_sim_outputs.
        '''

        # DISPLACEMENT
        #
        U = self.tloop.eval()

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='$u_z$', unit='[mm]'),
        ]

    #----------------------------------------------------
    # response tracer
    #----------------------------------------------------

    rtrace_list = List

    def _rtrace_list_default(self):
        return [self.max_princ_stress, self.sig_app, self.u]

    max_princ_stress = Instance(RTraceDomainListField)

    def _max_princ_stress_default(self):
        return RTraceDomainListField(
            name='max principle stress',
            idx=0,
            var='max_principle_sig',
            warp=True,
            #                                      position = 'int_pnts',
            record_on='update',
        )

    sig_app = Property(Instance(RTraceDomainListField),
                       depends_on='+ps_levels, +input')

    @cached_property
    def _get_sig_app(self):
        return RTraceDomainListField(
            name='sig_app',
            position='int_pnts',
            var='sig_app',
            record_on='update',
        )

    u = Property(Instance(RTraceDomainListField),
                 depends_on='+ps_levels, +input')

    @cached_property
    def _get_u(self):
        return RTraceDomainListField(
            name='displacement',
            var='u',
            warp=True,
            record_on='update',
        )

    #----------------------------------------------------
    # time loop
    #----------------------------------------------------

    tline = Instance(TLine)

    def _tline_default(self):
        return TLine(min=0.0, step=1.0, max=1.0)

    tloop = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_tloop(self):

        ts = TS(sdomain=self.fe_domain,
                dof_resultants=True,
                bcond_list=self.bc_list,
                rtrace_list=self.rtrace_list)

        # Add the time-loop control
        #
        tloop = TLoop(tstepper=ts, tolerance=1e-4, tline=self.tline)

        return tloop
예제 #18
0
class POShortFiber(RF):
    '''
    Pullout of fiber from a stiff matrix;
    stress criterion for debonding, free fiber end
    '''

    implements(IRF)

    title = Str('pullout - short fiber with constant friction')
    image = Image('pics/cb_short_fiber.jpg')

    xi = Float(0.0179,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['weibull_min', 'uniform'])

    E_f = Float(200e+3,
                auto_set=False,
                enter_set=True,
                desc='filament stiffness [N/mm2]',
                distr=['uniform', 'norm'],
                scale=210e3,
                shape=0)

    D_f = Float(0.3,
                auto_set=False,
                enter_set=True,
                desc='filament diameter [mm]',
                distr=['uniform', 'norm'],
                scale=0.5,
                shape=0)

    le = Float(8.5,
               auto_set=False,
               enter_set=True,
               desc='embedded lentgh [mm]',
               distr=['uniform'],
               scale=8.5,
               shape=0)

    L_f = Float(17.0,
                auto_set=False,
                enter_set=True,
                desc='fiber length [mm]',
                distr=['uniform', 'norm'],
                scale=30,
                shape=0)

    tau = Float(1.76,
                auto_set=False,
                enter_set=True,
                desc='bond shear stress [N/mm2]',
                distr=['norm', 'uniform'],
                scale=1.76,
                shape=0.5)

    f = Float(0.03,
              auto_set=False,
              enter_set=True,
              desc='snubbing coefficient',
              distr=['uniform', 'norm'],
              scale=0.05,
              shape=0)

    phi = Float(0.0,
                auto_set=False,
                enter_set=True,
                desc='inclination angle',
                distr=['sin2x', 'sin_distr'],
                scale=1.0,
                shape=0)

    l = Float(0.0,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              desc='free length')

    theta = Float(0.01,
                  auto_set=False,
                  enter_set=True,
                  distr=['uniform', 'norm'],
                  desc='slack')

    u = Float(ctrl_range=(0, 0.01, 100), auto_set=False, enter_set=True)

    x_label = Str('displacement [mm]', enter_set=True, auto_set=False)
    y_label = Str('force [N]', enter_set=True, auto_set=False)

    C_code = ''

    def __call__(self, u, tau, L_f, D_f, E_f, le, phi, f, l, theta, xi):

        l = l * (1 + theta)
        u = u - theta * l
        T = tau * pi * D_f
        E = E_f
        A = D_f**2 / 4. * pi

        # debonding stage
        q_deb = -l * T + sqrt((l * T)**2 + 2 * E * A * T * u * H(u))

        # displacement at which debonding is finished
        u0 = le * T * (le + 2 * l) / 2 / E_f / A

        q_pull = le * T * ((u0 - u) / (le - u0) + 1)
        q = q_deb * H(le * T - q_deb) + q_pull * H(q_deb - le * T)

        # include inclination influence
        q = q * H(q) * e**(f * phi)

        # include breaking strain
        q = q * H(A * E_f * xi - q)
        return q

    def get_q_x(self, u, x, tau, L_f, D_f, E_f, z, phi, f, l, theta, xi):
        q = self.__call__(u, tau, L_f, D_f, E_f, z, phi, f, l, theta, xi)
        l = l * (1 + theta)
        T = tau * pi * D_f
        qfree = q
        qbond = q - T * (x - l)

        return qfree * H(l - x) + qbond * H(x - l)

    traits_view = View(Item('E_f', label='fiber E-mod'),
                       Item('D_f', label='fiber diameter'),
                       Item('f', label='snubbing coef.'),
                       Item('phi', label='inclination angle'),
                       Item('le', label='embedded length'),
                       Item('tau', label='frictional coef.'),
                       resizable=True,
                       scrollable=True,
                       height=0.8,
                       width=0.8,
                       buttons=[OKButton, CancelButton])
예제 #19
0
파일: mr_one.py 프로젝트: rosoba/simvisage
class MRone(MushRoofModel):

    implements(ISimModel)
    mushroof_part = 'one'
    #===============================================================================
    # fe_grid
    #===============================================================================

    n_elems_xy_quarter = Int(10, input=True)  # , ps_levels = [4, 16, 5] )
    n_elems_z = Int(1, input=True)  # , ps_levels = [1, 2, 1] )
    n_elems_col_z = Int(10, input=True, ps_levels=[5, 20, 3])
    n_elems_col_xy = Int(2, input=True, ps_levels=[2, 4, 1])

    shift_elems = True

    vtk_r = Float(1.00)

    # default roof
    fe_roof = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _fe_roof_default(self):
        fets = self.fe_quad_serendipity_roof
        fets.vtk_r *= self.vtk_r
        return fets

    # default plate
    fe_plate = Instance((FETSEval), depends_on='+ps_levels, +input')

    def _fe_plate_default(self):
        fets = self.fe_quad_serendipity_plate
        fets.ngp_r = 3
        fets.ngp_s = 3
        fets.ngp_t = 3
        fets.vtk_r *= self.vtk_r
        return fets

    # shell
    #
    hp_shell = Property(Instance(HPShell), depends_on='+ps_levels, +input')

    @cached_property
    def _get_hp_shell(self):
        return HPShell(length_xy_quarter=self.length_xy_quarter,
                       length_z=self.length_z,
                       n_elems_xy_quarter=self.n_elems_xy_quarter,
                       n_elems_z=self.n_elems_z,
                       scalefactor_delta_h=self.scalefactor_delta_h,
                       const_reinf_layer_elem=self.const_reinf_layer_elem,
                       width_top_col=self.width_top_col,
                       mushroof_part=self.mushroof_part,
                       shift_array=self.shift_array,
                       X0=self.X0)

    # plate
    #
    plate = Property(Instance(GEOColumn), depends_on='+ps_levels, +input')

    @cached_property
    def _get_plate(self):
        return GEOColumn(
            width_top=self.width_top_col,
            width_bottom=self.width_top_col,
            X0=[3.5, 3.5, -self.t_plate],  # - 0.25],
            h_col=self.t_plate)

    # column
    #
#    X0_column = Array( [ 4., 4., -3.] )
    column = Property(Instance(GEOColumn), depends_on='+ps_levels, +input')

    @cached_property
    def _get_column(self):
        return GEOColumn(
            width_top_col=self.width_top_col,
            width_bottom_col=self.width_bottom_col,
            h_col=self.h_col - self.t_plate,
            # r_pipe = self.r_pipe,
            X0=[3.5, 3.5, -(self.h_col)])  # - 0.5] )

    # default column
    fe_column = Instance((FETSEval),
                         transient=True,
                         depends_on='+ps_levels, +input')

    def _fe_column_default(self):
        fets = self.fe_quad_serendipity_column
        fets.vtk_r *= self.vtk_r
        return fets

    fe_grid_roof = Property(Instance(FEGrid), depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_grid_roof(self):
        return FEGrid(coord_min=(0.0, 0.0, 0.0),
                      coord_max=(1.0, 1.0, 1.0),
                      geo_transform=self.hp_shell,
                      shift_array=self.shift_array,
                      shape=(self.n_elems_xy, self.n_elems_xy, self.n_elems_z),
                      fets_eval=self.fe_roof)

    fe_grid_column = Property(Instance(FEGrid),
                              depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_grid_column(self):
        return FEGrid(coord_min=(0.0, 0.0, 0.0),
                      coord_max=(1.0, 1.0, 1.0),
                      geo_transform=self.column,
                      shape=(self.n_elems_col_xy, self.n_elems_col_xy,
                             self.n_elems_col_z),
                      fets_eval=self.fe_column)

    fe_grid_plate = Property(Instance(FEGrid), depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_grid_plate(self):
        return FEGrid(coord_min=(0.0, 0.0, 0.0),
                      coord_max=(1.0, 1.0, 1.0),
                      geo_transform=self.plate,
                      shape=(self.n_elems_col_xy, self.n_elems_col_xy, 2),
                      fets_eval=self.fe_plate)

    #===============================================================================
    # ps_study
    #===============================================================================
    def peval(self):
        '''
        Evaluate the model and return the array of results specified
        in the method get_sim_outputs.
        '''
        U = self.tloop.eval()

        U_edge = U[self.edge_corner_1_dof][0, 0, 2]

        F_int = self.tloop.tstepper.F_int

        F_int_slice_x = F_int[self.edge_roof_right]
        F_int_slice_y = F_int[self.edge_roof_top]

        # bring dofs into right order for plot
        #
        F_hinge_in_order_x = self.sort_by_dofs(self.edge_roof_top,
                                               F_int_slice_x)
        F_hinge_in_order_y = self.sort_by_dofs(self.edge_roof_top,
                                               F_int_slice_y)
        F_hinge_x = append(F_hinge_in_order_x[:, :-1, 0],
                           F_hinge_in_order_x[-1, -1, 0])
        F_hinge_y = append(F_hinge_in_order_y[:, :-1, 1],
                           F_hinge_in_order_y[-1, -1, 1])
        F_hinge_y_sum = sum(F_hinge_y.flatten())
        F_hinge_x_sum = sum(F_hinge_x.flatten())
        #
        #        self.visual_force_bar( F_hinge_x.flatten()
        #                               , y_label = "internal force x [MN]"
        #                               , Title = 'F_Hinge_x_shrinkage' )
        #        self.visual_force_bar( F_hinge_y.flatten()
        #                               , y_label = "internal force y [MN]"
        #                               , Title = 'F_Hinge_y_shrinkage' )
        print "u_edge", U_edge
        print "n_elems_xy_col", self.n_elems_col_xy
        print "n_elems_z_col", self.n_elems_col_z
        print "n_elems_xy_quarter", self.n_elems_xy_quarter
        print "n_elems_z", self.n_elems_z

        return array(
            [
                U_edge,
                #                        u_x_corner2,
                #                       F_hinge_y_sum] )
                #                        u_z_corner2,
                #                        max_princ_stress ]
            ],
            dtype='float_')

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='U', unit='m'),
            #                 SimOut( name = 'u_x_corner2', unit = 'm' ),
            #                 SimOut( name = 'N Gelenk', unit = 'MN' ), ]
            #                 SimOut( name = 'u_z_corner2', unit = 'm' ),
            #                 SimOut( name = 'maximum principle stress', unit = 'MPa' )
        ]

    #===============================================================================
    # response tracer
    #===============================================================================

    rtrace_list = List

    def _rtrace_list_default(self):
        return [self.max_princ_stress, self.sig_app, self.u, self.f_dof]

    shift_array = Array(value=[
        [0.45 / 2**0.5, 0.45 / 2**0.5, 1],
    ],
                        input=True)

    #===============================================================================
    # boundary conditions
    #===============================================================================

    bc_plate_roof_link_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_plate_roof_link_list(self):
        '''
        links all plate corner nodes of each elements to the adjacent elements of the roof
        '''
        roof = self.fe_grid_roof
        plate = self.fe_grid_plate
        bc_col_link_list = []

        slice_1 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=roof[self.n_elems_xy_quarter - 1,
                               self.n_elems_xy_quarter, 0, 0, 0, 0],
                    link_slice=plate[0, 0, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]
        slice_2 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter - 1, 0, 0, 0, 0],
                    link_slice=plate[-1, 0, -1, -1, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_3 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=roof[self.n_elems_xy_quarter + 1,
                               self.n_elems_xy_quarter, 0, 0, 0, 0],
                    link_slice=plate[-1, -1, -1, -1, -1, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_4 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter + 1, 0, 0, 0, 0],
                    link_slice=plate[0, -1, -1, 0, -1, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_5 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter, 0, 0, 0, 0],
                    link_slice=plate[self.n_elems_col_xy / 2.0,
                                     self.n_elems_col_xy / 2.0, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        bc_plate_roof_link_list = slice_1 + slice_2 + slice_3 + slice_4 + slice_5

        return bc_plate_roof_link_list

    bc_roof_top_roof_low_link_list = Property(List,
                                              depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_roof_top_roof_low_link_list(self):
        '''
        links all plate corner nodes of each elements to the adjacent elements of the roof
        '''
        roof = self.fe_grid_roof
        plate = self.fe_grid_plate
        bc_roof_top_roof_low_link_list = []

        slice_1 = [
            BCSlice(var='u',
                    dims=[2],
                    link_slice=roof[self.n_elems_xy_quarter - 1,
                                    self.n_elems_xy_quarter, 0, 0, 0, 0],
                    slice=roof[self.n_elems_xy_quarter - 1,
                               self.n_elems_xy_quarter, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]
        slice_2 = [
            BCSlice(var='u',
                    dims=[2],
                    link_slice=roof[self.n_elems_xy_quarter,
                                    self.n_elems_xy_quarter - 1, 0, 0, 0, 0],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter - 1, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_3 = [
            BCSlice(var='u',
                    dims=[2],
                    link_slice=roof[self.n_elems_xy_quarter + 1,
                                    self.n_elems_xy_quarter, 0, 0, 0, 0],
                    slice=roof[self.n_elems_xy_quarter + 1,
                               self.n_elems_xy_quarter, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_4 = [
            BCSlice(var='u',
                    dims=[2],
                    link_slice=roof[self.n_elems_xy_quarter,
                                    self.n_elems_xy_quarter + 1, 0, 0, 0, 0],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter + 1, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_5 = [
            BCSlice(var='u',
                    dims=[2],
                    link_slice=roof[self.n_elems_xy_quarter,
                                    self.n_elems_xy_quarter, 0, 0, 0, 0],
                    slice=roof[self.n_elems_xy_quarter,
                               self.n_elems_xy_quarter, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        bc_roof_top_roof_low_link_list = slice_1 + slice_2 + slice_3 + slice_4 + slice_5

        return bc_roof_top_roof_low_link_list

    bc_plate_column_link_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_plate_column_link_list(self):
        '''
        links all column nodes to plate nodes
        '''
        column = self.fe_grid_column
        plate = self.fe_grid_plate

        slice_1 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=plate[:, :, 0, -1, -1, 0],
                    link_slice=column[:, :, -1, -1, -1, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_2 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=plate[:, :, 0, 0, 0, 0],
                    link_slice=column[:, :, -1, 0, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_3 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=plate[:, :, 0, 0, -1, 0],
                    link_slice=column[:, :, -1, 0, -1, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        slice_4 = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=plate[:, :, 0, -1, 0, 0],
                    link_slice=column[:, :, -1, -1, 0, -1],
                    link_coeffs=[1.0],
                    value=0.)
        ]

        return slice_1 + slice_2 + slice_3 + slice_4
#        return [BCSlice( var = 'u'  , dims = [0, 1, 2],
#                         slice = plate[:,:,0,:,:, 0 ],
#                         link_slice = column[ :,:,-1 ,:,:,-1], link_coeffs = [1.0], value = 0. )]

    link_edge_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_link_edge_list(self):
        '''
        links all edge nodes to one node, for this node boundary conditions are applied,
        the complete force within the edge hinge can therefore be evaluated at one node
        '''
        roof = self.fe_grid_roof
        dof_constraint_0 = [
            BCSlice(var='u',
                    dims=[1],
                    slice=roof[:, -1, -1, :, -1, -1],
                    value=0.0)
        ]
        dof_constraint_1 = [
            BCSlice(var='u',
                    dims=[0],
                    slice=roof[-1, :, -1, -1, :, -1],
                    value=0.0)
        ]
        link_edge_list = dof_constraint_0 + dof_constraint_1
        return link_edge_list

    bc_col_clamped_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_col_clamped_list(self):
        column = self.fe_grid_column
        constraint = [
            BCSlice(var='u',
                    dims=[0, 1, 2],
                    slice=column[:, :, 0, :, :, 0],
                    value=0.0)
        ]
        return constraint

    bc_col_hinge_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_col_hinge_list(self):
        constraint = []
        column = self.fe_grid_column
        for i in range(0, self.n_elems_col):
            dof_const = [
                BCSlice(var='u',
                        dims=[0, 1, 2],
                        slice=column[i, 0, 0, 0, 0, 0],
                        link_slice=column[-1 - i, -1, 0, -1, -1, 0],
                        link_coeffs=[-1.0],
                        value=0.0)
            ]
            constraint = constraint + dof_const
        for i in range(0, self.n_elems_col):
            dof_const = [
                BCSlice(var='u',
                        dims=[0, 1, 2],
                        slice=column[0, -1 - i, 0, 0, -1, 0],
                        link_slice=column[-1, i, 0, -1, 0, 0],
                        link_coeffs=[-1.0],
                        value=0.0)
            ]
            constraint = constraint + dof_const

        return constraint

    #===============================================================================
    # loading cases for mr_one only symmetric
    #===============================================================================

    lc_g_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_lc_g_list(self):
        # slices
        roof = self.fe_grid_roof
        column = self.fe_grid_column
        upper_surf = roof[:, :, -1, :, :, -1]
        bottom_edge_roof = roof[:, 0, -1, :, 0, -1]
        left_edge_roof = roof[0, :, -1, 0, :, -1]

        # loads in global z- direction
        material_density_roof = -22.4e-3  # [MN/m^3]
        material_density_column = -26e-3  # [MN/m^3]
        additional_surface_load = -0.20e-3  # [MN/m^2]
        additional_t_constr = -0.02 * 22.4e-3
        edge_load = -0.35e-3  # [MN/m]
        return [
            BCSlice(var='f',
                    value=material_density_roof,
                    dims=[2],
                    integ_domain='global',
                    slice=roof[:, :, :, :, :, :]),
            BCSlice(var='f',
                    value=material_density_column,
                    dims=[2],
                    integ_domain='global',
                    slice=column[:, :, :, :, :, :]),
        ]


#                 BCSlice( var = 'f', value = additional_surface_load + additional_t_constr,
#                          dims = [2], integ_domain = 'global',
#                          slice = upper_surf ),
#                 BCSlice( var = 'f', value = edge_load, dims = [2],
#                          integ_domain = 'global',
#                          slice = bottom_edge_roof ),
#                 BCSlice( var = 'f', value = edge_load, dims = [2],
#                          integ_domain = 'global',
#                          slice = left_edge_roof )]

    lc_s_list = Property(List, depends_on='+ps_levels, +input')

    @cached_property
    def _get_lc_s_list(self):
        # slices
        roof = self.fe_grid_roof
        upper_surf = roof[:, :, -1, :, :, -1]
        # loads in global z- direction
        snow_load = -0.85e-3
        return [
            BCSlice(var='f',
                    value=snow_load,
                    dims=[2],
                    integ_domain='global',
                    slice=upper_surf)
        ]

    lc_shrink_list = Property(List, depends_on='+ps_levels, +input')

    def _get_lc_shrink_list(self):
        self.initial_strain_roof = True
        self.initial_strain_col = True
        self.t_up = -100
        self.t_lo = -100

    #===============================================================================
    # time loop
    #===============================================================================

    tloop = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_tloop(self):
        roof = self.fe_grid_roof
        column = self.fe_grid_column
        plate = self.fe_grid_plate

        ts = TS(
            sdomain=[roof, plate, column],
            dof_resultants=True,
            bcond_list=

            # boundary conditions
            #
            self.bc_roof_top_roof_low_link_list +
            self.bc_plate_column_link_list + self.bc_plate_roof_link_list +
            self.link_edge_list + self.bc_col_clamped_list +

            # loading
            #
            self.lc_g_list,
            rtrace_list=self.rtrace_list)

        # Add the time-loop control
        tloop = TLoop(tstepper=ts, tolerance=1e-4, tline=self.tline)
        self.edge_corner_1_dof = roof[0, 0, 0, 0, 0, 0].dofs
        self.edge_corner_2_dof = roof[-1, 0, -1, -1, 0, -1].dofs
        self.dof = roof[-1, 0, -1, -1, 0, -1].dofs[0][0][0]
        self.edge_roof_top = roof[:, -1, -1, :, -1, -1].dofs
        self.edge_roof_right = roof[-1, :, -1, -1, :, -1].dofs

        return tloop
예제 #20
0
class fiber_tt_5p(RF):
    ur'''
Response function of a single fiber 
===================================

Response of a fiber loaded in tension can be described by a linear function
with the domain bounded from left and right by the Heaviside terms.

..    math::
    q\left(\varepsilon; E,A,\theta,\lambda,\xi\right) = E A \frac{{\varepsilon
    - \theta \left( {1 + \lambda } \right)}}{{\left( {1 + \theta } \right)
    \left( {1 + \lambda } \right)}}
    H\left[ {e - \theta \left( {1 + \lambda } \right)} \right]
    H\left[ {\xi  - \frac{{e - \theta \left( {1 + \lambda } \right)}}
    {{\left( {1 + \theta } \right)\left( {1 + \lambda } \right)}}} \right]

where the variables :math:`A=` cross-sectional area, :math:`E=` Young's modulus,
:math:`\theta=` filament activation strain, :math:`\lambda=` ratio of extra
(stretched) filament length to the nominal length and :math:`\xi=` breaking strain
are considered random and normally distributed. The function :math:`H(\eta)`
represents the Heaviside function with values 0 for :math:`\eta < 0`
and 1 for :math:`\eta > 0`.

'''
    implements(IRF)

    title = Str('brittle filament')

    def __call__(self, eps, lambd, xi, E_mod, theta, A):
        '''
        Implements the response function with arrays as variables.
        first extract the variable discretizations from the orthogonal grid.
        '''
        # NOTE: as each variable is an array oriented in different direction
        # the algebraic expressions (-+*/) perform broadcasting,. i.e. performing
        # the operation for all combinations of values. Thus, the resulgin eps
        # is contains the value of local strain for any combination of
        # global strain, xi, theta and lambda
        #

        eps_ = (eps - theta * (1 + lambd)) / ((1 + theta) * (1 + lambd))

        # cut off all the negative strains due to delayed activation
        #
        eps_ *= Heaviside(eps_)

        # broadcast eps also in the xi - dimension
        # (by multiplying with array containing ones with the same shape as xi )
        #
        eps_grid = eps_ * Heaviside(xi - eps_)

        # cut off all the realizations with strain greater than the critical one.
        #
        # eps_grid[ eps_grid >= xi ] = 0

        # transform it to the force
        #
        q_grid = E_mod * A * eps_grid

        return q_grid

    cython_code = '''
            eps_ = ( eps - theta * ( 1 + lambd ) ) / ( ( 1 + theta ) * ( 1 + lambd ) )
            # Computation of the q( ... ) function
            if eps_ < 0 or eps_ > xi:
                q = 0.0
            else:
                q = E_mod * A * eps_
        '''

    weave_code = '''
예제 #21
0
class RFBase(RF):

    implements(IRF)

    title = Str('RFSumParams')

    a = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    b = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    c = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    d = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    ee = Float(1,
               auto_set=False,
               enter_set=True,
               distr=['uniform'],
               loc=1.0,
               scale=0.1,
               shape=0.1)

    f = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    g = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    h = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    i = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)

    k = Float(1,
              auto_set=False,
              enter_set=True,
              distr=['uniform'],
              loc=1.0,
              scale=0.1,
              shape=0.1)
예제 #22
0
class ExpSH(ExType):
    '''Experiment: Shell Test
    '''
#    label = Str('slab test')
    implements(IExType)

    #--------------------------------------------------------------------
    # register a change of the traits with metadata 'input'
    #--------------------------------------------------------------------

    input_change = Event
    @on_trait_change('+input, ccs.input_change, +ironing_param')
    def _set_input_change(self):
        self.input_change = True

    #--------------------------------------------------------------------------------
    # specify inputs:
    #--------------------------------------------------------------------------------

    edge_length = Float(1.25, unit = 'm', input = True, table_field = True,
                           auto_set = False, enter_set = True)
    thickness = Float(0.03, unit = 'm', input = True, table_field = True,
                           auto_set = False, enter_set = True)

    # age of the concrete at the time of testing
    age = Int(28, unit = 'd', input = True, table_field = True,
                             auto_set = False, enter_set = True)
    loading_rate = Float(0.50, unit = 'mm/min', input = True, table_field = True,
                            auto_set = False, enter_set = True)

    #--------------------------------------------------------------------------
    # composite cross section
    #--------------------------------------------------------------------------

    ccs = Instance(CompositeCrossSection)
    def _ccs_default(self):
        '''default settings correspond to 
        setup '7u_MAG-07-03_PZ-0708-1'
        '''
        fabric_layout_key = 'MAG-07-03'
#        fabric_layout_key = '2D-02-06a'
        concrete_mixture_key = 'PZ-0708-1'
#        concrete_mixture_key = 'FIL-10-09'
#        orientation_fn_key = 'all0'                                           
        orientation_fn_key = '90_0'
        n_layers = 10
        s_tex_z = 0.030 / (n_layers + 1)
        ccs = CompositeCrossSection (
                    fabric_layup_list = [
                            plain_concrete(s_tex_z * 0.5),
                            FabricLayUp (
                                   n_layers = n_layers,
                                   orientation_fn_key = orientation_fn_key,
                                   s_tex_z = s_tex_z,
                                   fabric_layout_key = fabric_layout_key
                                   ),
                            plain_concrete(s_tex_z * 0.5)
                                        ],
                    concrete_mixture_key = concrete_mixture_key
                    )
        return ccs

    #--------------------------------------------------------------------------
    # Get properties of the composite 
    #--------------------------------------------------------------------------

    # E-modulus of the composite at the time of testing 
    E_c = Property(Float, unit = 'MPa', depends_on = 'input_change', table_field = True)
    def _get_E_c(self):
        return self.ccs.get_E_c_time(self.age)

    # E-modulus of the composite after 28 days
    E_c28 = DelegatesTo('ccs', listenable = False)

    # reinforcement ration of the composite 
    rho_c = DelegatesTo('ccs', listenable = False)

    #--------------------------------------------------------------------------------
    # define processing
    #--------------------------------------------------------------------------------

    # put this into the ironing procedure processor
    #
    jump_rtol = Float(1,
                      auto_set = False, enter_set = True,
                      ironing_param = True)


    data_array_ironed = Property(Array(float),
                                  depends_on = 'data_array, +ironing_param, +axis_selection')
    @cached_property
    def _get_data_array_ironed(self):
        '''remove the jumps in the displacement curves 
        due to resetting the displacement gauges. 
        '''
        print '*** curve ironing activated ***'

        # each column from the data array corresponds to a measured parameter 
        # e.g. displacement at a given point as function of time u = f(t))
        #
        data_array_ironed = copy(self.data_array)

        for idx in range(self.data_array.shape[1]):

            # use ironing method only for columns of the displacement gauges.
            #
            if self.names_and_units[0][ idx ] != 'Kraft' and \
                self.names_and_units[0][ idx ] != 'Bezugskanal' and \
                self.names_and_units[0][ idx ] != 'D_1o'and \
                self.names_and_units[0][ idx ] != 'D_2o'and \
                self.names_and_units[0][ idx ] != 'D_3o'and \
                self.names_and_units[0][ idx ] != 'D_4o'and \
                self.names_and_units[0][ idx ] != 'D_1u'and \
                self.names_and_units[0][ idx ] != 'D_2u'and \
                self.names_and_units[0][ idx ] != 'D_3u'and \
                self.names_and_units[0][ idx ] != 'D_4u'and \
                self.names_and_units[0][ idx ] != 'W30_vo'and \
                self.names_and_units[0][ idx ] != 'W30_hi':

                # 1d-array corresponding to column in data_array
                data_arr = copy(data_array_ironed[:, idx])

                # get the difference between each point and its successor
                jump_arr = data_arr[1:] - data_arr[0:-1]

                # get the range of the measured data 
                data_arr_range = max(data_arr) - min(data_arr)

                # determine the relevant criteria for a jump
                # based on the data range and the specified tolerances:
                jump_crit = self.jump_rtol * data_arr_range

                # get the indexes in 'data_column' after which a 
                # jump exceeds the defined tolerance criteria
                jump_idx = where(fabs(jump_arr) > jump_crit)[0]

                print 'number of jumps removed in data_arr_ironed for', self.names_and_units[0][ idx ], ': ', jump_idx.shape[0]
                # glue the curve at each jump together
                for jidx in jump_idx:
                    # get the offsets at each jump of the curve
                    shift = data_arr[jidx + 1] - data_arr[jidx]
                    # shift all succeeding values by the calculated offset
                    data_arr[jidx + 1:] -= shift

                data_array_ironed[:, idx] = data_arr[:]

        return data_array_ironed


    @on_trait_change('+ironing_param')
    def process_source_data(self):
        '''read in the measured data from file and assign
        attributes after array processing.        
        
        NOTE: if center displacement gauge ('WA_M') is missing the measured 
        displacement of the cylinder ('Weg') is used instead.
        A minor mistake is made depending on how much time passes
        before the cylinder has contact with the slab.
        '''
        print '*** process source data ***'

        self._read_data_array()
        # curve ironing:
        #
        self.processed_data_array = self.data_array_ironed

        # set attributes:
        #
        self._set_array_attribs()

    #--------------------------------------------------------------------------------
    # plot templates
    #--------------------------------------------------------------------------------

    plot_templates = {'force / time' : '_plot_force_time',
                      'force / deflections center' : '_plot_force_deflection_center',
                      'force / smoothed deflections center' : '_plot_smoothed_force_deflection_center',
                      'force / deflections' : '_plot_force_deflections',
                      'force / eps_t' : '_plot_force_eps_t',
                      'force / eps_c' : '_plot_force_eps_c',
                      'force / w_elastomer' : '_plot_force_w_elastomer',
                      'time / deflections' : '_plot_time_deflections'
                     }
    default_plot_template = 'force / time'

    def _plot_force_w_elastomer(self, axes):

        xkey = 'displacement [mm]'
        ykey = 'force [kN]'
        W_vl = self.W_vl
        W_vr = self.W_vr
        W_hl = self.W_hl
        W_hr = self.W_hr
        force = self.Kraft

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))
        axes.plot(W_vl, force)
        axes.plot(W_vr, force)
        axes.plot(W_hl, force)
        axes.plot(W_hr, force)


    def _plot_force_time(self, axes):

        xkey = 'time [s]'
        ykey = 'force [kN]'
        xdata = self.Bezugskanal
        ydata = self.Kraft

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))
        axes.plot(xdata, ydata
                       # color = c, linewidth = w, linestyle = s 
                       )

    def _plot_force_deflection_center(self, axes):

        xkey = 'deflection [mm]'
        ykey = 'force [kN]'
        xdata = -self.WD4
        ydata = self.Kraft

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))
        axes.plot(xdata, ydata
                       # color = c, linewidth = w, linestyle = s 
                       )

    n_fit_window_fraction = Float(0.1)

    def _plot_smoothed_force_deflection_center(self, axes):

        xkey = 'deflection [mm]'
        ykey = 'force [kN]'

        # get the index of the maximum stress
        max_force_idx = argmax(self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = self.Kraft[:max_force_idx + 1]
        w_asc = -self.WD4[:max_force_idx + 1]

        f_max = f_asc[-1]
        w_max = w_asc[-1]

        n_points = int(self.n_fit_window_fraction * len(w_asc))
        f_smooth = smooth(f_asc, n_points, 'flat')
        w_smooth = smooth(w_asc, n_points, 'flat')

        axes.plot(w_smooth, f_smooth, color = 'blue', linewidth = 2)

        secant_stiffness_w10 = (f_smooth[10] - f_smooth[0]) / (w_smooth[10] - w_smooth[0])
        w0_lin = array([0.0, w_smooth[10] ], dtype = 'float_')
        f0_lin = array([0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_')

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))


    def _plot_force_deflections(self, axes):

        xkey = 'displacement [mm]'
        ykey = 'force [kN]'

        # get the index of the maximum stress
        max_force_idx = argmax(self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = self.Kraft[:max_force_idx + 1]

        WD1 = -self.WD1[:max_force_idx + 1]
        WD2 = -self.WD2[:max_force_idx + 1]
        WD3 = -self.WD3[:max_force_idx + 1]
        WD4 = -self.WD4[:max_force_idx + 1]
        WD5 = -self.WD5[:max_force_idx + 1]
        WD6 = -self.WD6[:max_force_idx + 1]
        WD7 = -self.WD7[:max_force_idx + 1]

        axes.plot(WD1, f_asc, color = 'blue', linewidth = 1 )
        axes.plot(WD2, f_asc, color = 'green', linewidth = 1 )
        axes.plot(WD3, f_asc, color = 'red', linewidth = 1 )
        axes.plot(WD4, f_asc, color = 'black', linewidth = 3 )
        axes.plot(WD5, f_asc, color = 'red', linewidth = 1 )
        axes.plot(WD6, f_asc, color = 'green', linewidth = 1 )
        axes.plot(WD7, f_asc, color = 'blue', linewidth = 1 )

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))


    def _plot_time_deflections(self, axes):

        xkey = 'time [s]'
        ykey = 'deflections [mm]'

        time = self.Bezugskanal

        WD1 = -self.WD1
        WD2 = -self.WD2
        WD3 = -self.WD3
        WD4 = -self.WD4
        WD5 = -self.WD5
        WD6 = -self.WD6
        WD7 = -self.WD7

        axes.plot(time, WD1, color = 'blue', linewidth = 1 )
        axes.plot(time, WD2, color = 'green', linewidth = 1 )
        axes.plot(time, WD3, color = 'red', linewidth = 1 )
        axes.plot(time, WD4, color = 'black', linewidth = 3 )
        axes.plot(time, WD5, color = 'red', linewidth = 1 )
        axes.plot(time, WD6, color = 'green', linewidth = 1 )
        axes.plot(time, WD7, color = 'blue', linewidth = 1 )

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))


    def _plot_force_eps_c(self, axes):

        xkey = 'force [kN]'
        ykey = 'strain [mm/m]'

        # get the index of the maximum stress
        max_force_idx = argmax(self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = self.Kraft[:max_force_idx + 1]
        
        D_1u = -self.D_1u[:max_force_idx + 1]
        D_2u = -self.D_2u[:max_force_idx + 1]
        D_3u = -self.D_3u[:max_force_idx + 1]
        D_4u = -self.D_4u[:max_force_idx + 1]
        
        D_1o = -self.D_1o[:max_force_idx + 1]
        D_2o = -self.D_2o[:max_force_idx + 1]
        D_3o = -self.D_3o[:max_force_idx + 1]
        D_4o = -self.D_4o[:max_force_idx + 1]

        axes.plot(f_asc, D_1u, color = 'blue', linewidth = 1 )
        axes.plot(f_asc, D_2u, color = 'blue', linewidth = 1 )
        axes.plot(f_asc, D_3u, color = 'blue', linewidth = 1 )
        axes.plot(f_asc, D_4u, color = 'blue', linewidth = 1 )

        axes.plot(f_asc, D_1o, color = 'red', linewidth = 1 )
        axes.plot(f_asc, D_2o, color = 'red', linewidth = 1 )
        axes.plot(f_asc, D_3o, color = 'red', linewidth = 1 )
        axes.plot(f_asc, D_4o, color = 'red', linewidth = 1 )

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))


    def _plot_force_eps_t(self, axes):

        xkey = 'strain [mm/m]'
        ykey = 'force [kN]'

        # get the index of the maximum stress
        max_force_idx = argmax(self.Kraft)
        # get only the ascending branch of the response curve
        f_asc = self.Kraft[:max_force_idx + 1]

        eps_vo = -self.W30_vo[:max_force_idx + 1] / 300. 
        eps_hi = -self.W30_hi[:max_force_idx + 1] / 300. 

        axes.plot(eps_vo, f_asc, color = 'blue', linewidth = 1 )
        axes.plot(eps_hi, f_asc, color = 'green', linewidth = 1 )

        axes.set_xlabel('%s' % (xkey,))
        axes.set_ylabel('%s' % (ykey,))


    #--------------------------------------------------------------------------------
    # view
    #--------------------------------------------------------------------------------

    traits_view = View(VGroup(
                         Group(
                              Item('jump_rtol', format_str = "%.4f"),
                              label = 'curve_ironing'
                              ),
                         Group(
                              Item('thickness', format_str = "%.3f"),
                              Item('edge_length', format_str = "%.3f"),
                              label = 'geometry'
                              ),
                         Group(
                              Item('loading_rate'),
                              Item('age'),
                              label = 'loading rate and age'
                              ),
                         Group(
                              Item('E_c', show_label = True, style = 'readonly', format_str = "%.0f"),
                              Item('ccs@', show_label = False),
                              label = 'composite cross section'
                              )
                         ),
                        scrollable = True,
                        resizable = True,
                        height = 0.8,
                        width = 0.6
                        )
예제 #23
0
class CBEMClampedFiber(RF):
    '''
    Crack bridged by a short fiber with constant
    frictional interface to the elastic matrix; clamped fiber end
    '''

    implements(IRF)

    title = Str('crack bridge - clamped fiber with constant friction')

    xi = Float(0.0179,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['weibull_min', 'uniform'])

    tau = Float(2.5,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'])

    l = Float(0.0,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='free length')

    A_r = Float(0.89,
                auto_set=False,
                input=True,
                enter_set=True,
                distr=['uniform', 'weibull_min'],
                desc='CS area of a the reinforcement')

    E_r = Float(72.0e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    E_m = Float(30.0e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    A_m = Float(50.0,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    theta = Float(0.01,
                  auto_set=False,
                  enter_set=True,
                  input=True,
                  distr=['uniform', 'norm'],
                  desc='slack')

    phi = Float(1.,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'],
                desc='bond quality')

    Ll = Float(1.,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'],
               desc='embedded length - left')

    Lr = Float(.5,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'],
               desc='embedded length - right')

    Nf = Float(1.,
               auto_set=False,
               enter_set=True,
               input=True,
               desc='number of parallel fibers',
               distr=['uniform'])

    w = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    Kr = Property(depends_on='A_r, E_r')

    @cached_property
    def _get_Kr(self):
        return self.A_r * self.E_r

    Km = Property(depends_on='A_r, E_m')

    @cached_property
    def _get_Km(self):
        return self.A_m * self.E_m

    Kc = Property(depends_on='A_r, E_r, E_m')

    @cached_property
    def _get_Kc(self):
        return self.Kr + self.Km

    x_label = Str('crack opening [mm]')
    y_label = Str('force [N]')

    C_code = Str('')

    def crackbridge(self, w, l, T, Kr, Km, Lmin, Lmax):
        c = (2 * l * (Km + Kr) + Kr * (Lmin + Lmax))
        P0 = (T *
              (Km + Kr)) / (2. *
                            Km**2) * (sqrt(c**2 + 4 * w * Kr * Km**2 / T) - c)
        return P0

    def pullout(self, u, l, T, Kr, Km, L):
        c = l * (Km + Kr) + L * Kr
        P1 = (T *
              (Km + Kr)) / Km**2 * (sqrt(c**2 + 2 * u * Kr * Km**2 / T) - c)
        return P1

    def linel(self, u, l, T, Kr, Km, L):
        P2 = (T * L**2 + 2 * u * Kr) / 2. / (L + l)

        return P2

    def __call__(self, w, tau, l, A_r, E_f, E_m, A_m, theta, xi, phi, Ll, Lr,
                 Nf):

        # cross sectional area of a single fiber

        Lmin = minimum(Ll, Lr)
        Lmax = maximum(Ll, Lr)

        Lmin = maximum(Lmin - l / 2., 0)
        Lmax = maximum(Lmax - l / 2., 0)

        l = minimum(l / 2., Lr) + minimum(l / 2., Ll)

        l = l * (1 + theta)
        w = w - theta * l
        w = H(w) * w
        D = sqrt(A_r * Nf / pi) * 2
        T = tau * phi * D * pi

        Km = A_m * E_m
        Kr = A_r * E_f

        # double sided debonding
        l0 = l / 2.
        q0 = self.crackbridge(w, l0, T, Kr, Km, Lmin, Lmax)

        # displacement at which the debonding to the closer clamp is finished
        # the closer distance is min(L1,L2)

        w0 = T * Lmin * ((2 * l0 + Lmin) * (Kr + Km) + Kr * Lmax) / (Km * Kr)
        # force at w0
        Q0 = Lmin * T * (Km + Kr) / (Km)
        # print Q0
        # debonding from one side; the other side is clamped
        # equal to a one sided pullout with embedded length Lmax - Lmin and free length 2*Lmin + l

        l1 = 2 * Lmin + l
        L1 = Lmax - Lmin
        q1 = self.pullout(w - w0, l1, T, Kr, Km, L1) + Q0

        # debonding completed at both sides, response becomes linear elastic

        # displacement at which the debonding is finished at both sides
        w1 = (L1 * T * (Kr + Km) * (L1 + l1)) / Kr / Km - T * L1**2 / 2. / Kr
        # print 'alt w0', w0, 'alt w1', w1 , 'alt w0+w1', w0 + w1
        q2 = self.linel(w - w0, l1, T, Kr, Km, L1) + Q0
        # print self.linel(0, l1, T, Kr, Km, L1)

        # cut out definition ranges and add all parts
        q0 = H(w) * q0 * H(w0 - w)
        q1 = H(w - w0) * q1 * H(w1 + w0 - w)
        q2 = H(w - w1 - w0) * q2

        q = q0 + q1 + q2

        # include breaking strain
        q = q * H(Kr * xi - q)

        return q
예제 #24
0
class Filament(RF):
    '''Linear elastic, brittle filament.
    '''

    implements(IRF)

    title = Str('brittle filament')

    xi = Float(
        0.017857,
        auto_set=False,
        enter_set=True,
        distr=['weibull_min', 'uniform'],
        scale=0.0178,
        shape=4.0,
    )

    theta = Float(0.01,
                  auto_set=False,
                  enter_set=True,
                  distr=['uniform', 'norm'],
                  loc=0.01,
                  scale=0.001)

    lambd = Float(0.2,
                  auto_set=False,
                  enter_set=True,
                  distr=['uniform'],
                  loc=0.0,
                  scale=0.1)

    A = Float(5.30929158457e-10,
              auto_set=False,
              enter_set=True,
              distr=['weibull_min', 'uniform', 'norm'],
              scale=5.3e-10,
              shape=8)

    E_mod = Float(70.0e9,
                  auto_set=False,
                  enter_set=True,
                  distr=['weibull_min', 'uniform', 'norm'],
                  scale=70e9,
                  shape=8)

    eps = Float(ctrl_range=(0, 0.1, 100), auto_set=False, enter_set=True)

    C_code = '''
            double eps_ = ( eps - theta * ( 1 + lambd ) ) /
                             ( ( 1 + theta ) * ( 1 + lambd ) );
            // Computation of the q( ... ) function
            if ( eps_ < 0 || eps_ > xi ){
                q = 0.0;
            }else{
                  q = E_mod * A * eps_;
            }
        '''

    def __call__(self, eps, xi, theta, lambd, A, E_mod):
        '''
        Implements the response function with arrays as variables.
        first extract the variable discretizations from the orthogonal grid.
        '''
        # NOTE: as each variable is an array oriented in different direction
        # the algebraic expressions (-+*/) perform broadcasting,. i.e. performing
        # the operation for all combinations of values. Thus, the resulgin eps
        # is contains the value of local strain for any combination of
        # global strain, xi, theta and lambda
        #

        eps_ = (eps - theta * (1 + lambd)) / ((1 + theta) * (1 + lambd))

        # cut off all the negative strains due to delayed activation
        #
        eps_ *= Heaviside(eps_)

        # broadcast eps also in the xi - dimension
        # (by multiplying with array containing ones with the same shape as xi )
        #
        eps_grid = eps_ * Heaviside(xi - eps_)

        # cut off all the realizations with strain greater than the critical one.
        #
        # eps_grid[ eps_grid >= xi ] = 0

        # transform it to the force
        #
        q_grid = E_mod * A * eps_grid

        return q_grid
예제 #25
0
class CBClamped(RF):
    '''
    Crack bridged by a fiber with constant
    frictional interface to rigid; free fiber end;
    '''

    implements(IRF)

    title = Str('crack bridge with rigid matrix')

    tau = Float(2.5,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'])

    r = Float(0.013,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform', 'norm'],
              desc='fiber radius')

    E_f = Float(72e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    m = Float(5.,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'])

    sV0 = Float(3.e-3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    V_f = Float(0.0175,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    lm = Float(np.inf,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'])

    w = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    x_label = Str('crack opening [mm]')
    y_label = Str('composite stress [MPa]')

    C_code = Str('')

    def e_broken(self, Pf, depsf, r, m, sV0, mask):
        '''weibull_fibers_cdf_mc'''
        s_free = ((depsf * (m + 1.) * sV0**m) / (2. * pi * r**2.))**(1. /
                                                                     (m + 1.))
        xi_free = s_free * (-np.log(1. - Pf))**(1. / (m + 1))
        s_fixed = ((depsf * sV0**m) / (2. * pi * r**2.))**(1. / (m + 1.))
        xi_fixed = s_fixed * (-np.log(1. - Pf))**(1. / (m + 1))
        return xi_free, xi_fixed

    def __call__(self, w, tau, E_f, V_f, r, m, sV0, lm, Pf):
        '''free and fixed fibers combined'''
        T = 2. * tau / r
        k = np.sqrt(T / E_f)
        ef0cb = k * np.sqrt(w)
        ef0lin = w / lm + T * lm / 4. / E_f
        depsf = T / E_f
        a0 = ef0cb / depsf
        mask = a0 < lm / 2.0
        e_int = ef0cb * mask + ef0lin * (mask == False)
        xi_free, xi_fixed = self.e_broken(Pf, depsf, r, m, sV0, mask)
        axi = xi_free / depsf
        mask_xi = axi < lm / 2.
        e_broken = xi_free / (m + 1.) * (mask_xi) + xi_fixed / 2. * (mask_xi
                                                                     == False)
        xi = xi_free * (mask_xi) + xi_fixed * (mask_xi == False)
        e = e_int * (e_int < xi) + e_broken * (e_int > xi)
        return e * E_f * V_f * r**2

    def __call__2(self, w, tau, E_f, V_f, r, m, sV0, Pf):
        '''free debonding only = __call__ with lm=infty'''
        #strain and debonded length of intact fibers
        T = 2. * tau / r
        ef0_inf = np.sqrt(T * w / E_f)
        #scale parameter with respect to a reference volume
        s0 = ((T * (m + 1) * sV0**m) / (2. * E_f * pi * r**2))**(1. / (m + 1))
        # strain at fiber breakage
        ef0_break = s0 * (-np.log(1. - Pf))**(1. / (m + 1))
        # debonded length at fiber breakage
        a_break = ef0_break * E_f / T
        #mean pullout length of broken fibers
        mu_Lpo = a_break / (m + 1)
        # strain carried by broken fibers
        ef0_residual = T / E_f * mu_Lpo

        if self.include_pullout == True:
            ef0_tot = ef0_residual * H(ef0_inf - ef0_break) + ef0_inf * H(
                ef0_break - ef0_inf)
        else:
            ef0_tot = ef0_inf * H(ef0_break - ef0_inf)
        return ef0_tot * E_f * V_f * r**2
예제 #26
0
class MRquarter(MushRoofModel):

    implements(ISimModel)
    mushroof_part = 'quarter'

    n_elems_xy_quarter = Int(6, ps_levels=[3, 15, 5])
    n_elems_z = Int(2, ps_levels=[1, 4, 2])

    #----------------------------------------------------
    # elements
    #----------------------------------------------------
    vtk_r = Float(0.9)

    # default roof
    fe_roof = Instance(
        FETSEval,
        ps_levels=[
            'fe2d5_quad_serendipity', 'fe_quad_serendipity', 'fe_linear',
            'fe_quad_lagrange'
        ],
        depends_on='+initial_strain_roof, +initial_strain_col, +vtk_r')

    def _fe_roof_default(self):
        fets = self.fe2d5_quad_serendipity
        #        fets = self.fe_quad_serendipity
        fets.vtk_r *= self.vtk_r
        return fets

    #----------------------------------------------------
    # grid and geometric transformation
    #----------------------------------------------------
    fe_grid_roof = Property(Instance(FEGrid), depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_grid_roof(self):
        return FEGrid(coord_min=(0.0, 0.0, 0.0),
                      coord_max=(1.0, 1.0, 1.0),
                      geo_transform=self.hp_shell,
                      shape=(self.n_elems_xy, self.n_elems_xy, self.n_elems_z),
                      fets_eval=self.fe2d5_quad_serendipity)
#                       fets_eval = self.fe_roof)
#                       fets_eval = self.fe_quad_serendipity)

    mats_roof = Property(Instance(MATS2D5MicroplaneDamage),
                         depends_on='+input')
    #    mats_roof = Property( Instance( MATS3DElastic), depends_on = '+input' )
    @cached_property
    def _get_mats_roof(self):
        # return MATS3DElastic(E=self.E_roof, nu=self.nu)
        return MATS2D5MicroplaneDamage(E=29100.0,
                                       nu=0.2,
                                       n_mp=30,
                                       symmetrization='sum-type',
                                       model_version='compliance',
                                       phi_fn=self.phi_fn)

    fe2d5_quad_serendipity = Property(Instance(FETSEval, transient=True),
                                      depends_on='+input')

    def _get_fe2d5_quad_serendipity(self):
        return FETS2D58H20U(mats_eval=self.mats_roof)

    fe_quad_serendipity = Property(Instance(FETSEval, transient=True),
                                   depends_on='+input')

    def _get_fe_quad_serendipity(self):
        return FETS3D8H20U(mats_eval=self.mats_roof)

    shrink_factor = Float(1.0)
    # shell
    #
    hp_shell = Property(Instance(HPShell), depends_on='+ps_levels, +input')

    @cached_property
    def _get_hp_shell(self):
        return HPShell(length_xy_quarter=self.length_xy_quarter /
                       self.shrink_factor,
                       length_z=self.length_z / self.shrink_factor,
                       n_elems_xy_quarter=self.n_elems_xy_quarter,
                       n_elems_z=self.n_elems_z,
                       scalefactor_delta_h=self.scalefactor_delta_h,
                       mushroof_part='quarter',
                       shift_elems=False,
                       X0=self.X0)

    #----------------------------------------------------
    # ps_study
    #----------------------------------------------------
    def peval(self):
        '''
        Evaluate the model and return the array of results specified
        in the method get_sim_outputs.
        '''
        U = self.tloop.eval()
        u_center_top_z = U[self.center_top_dof][0, 0, 2]
        print 'u_center_top_z', u_center_top_z
        return np.array([u_center_top_z], dtype='float_')


#        max_princ_stress = max(self.max_princ_stress._get_field_data().flatten())
#        return np.array([ u_center_top_z, max_princ_stress ],
#                        dtype = 'float_')

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='u_z_free_corner', unit='m'),
            SimOut(name='maximum principal stress', unit='MPa'),
        ]

    #----------------------------------------------------
    # response tracer
    #----------------------------------------------------

    rtrace_list = List

    def _rtrace_list_default(self):
        return [self.eps_app, self.sig_app, self.max_omega_i, self.phi_pdc]

    max_lambda = Float(1.0, input=True)
    '''Maximum lambda factor to impose on the structure.
    The final loading loading level is calculated
    as the reference boundary conditions multiplied by the lambda_factor
    and uls_factor. Thus, lambda factor defines the load level as a multiple
    of the load level predicted by the linear analysis.
    '''

    f_w_diagram = Property(Instance(RTraceGraph),
                           depends_on='+ps_levels, +input')

    @cached_property
    def _get_f_w_diagram(self):
        domain = self.fe_grid_roof
        w_z = domain[-1, -1, -1, -1, -1, -1].dofs[0, 0, 2]
        return RTraceGraph(
            name='load - corner deflection',
            var_x='U_k',
            idx_x=w_z,
            transform_x='-x',
            var_y='time',
            idx_y=0,
            # transform_y='y * %g' % self.lambda_factor,
            record_on='update')

    n_steps = Int(15.0, auto_set=False, enter_set=False, input=True)
    time_fn_load = Instance(MFnLineArray, input=True)

    def _time_fn_load_default(self):
        eta = 0.27 * 1.2
        return MFnLineArray(xdata=[0.0, 1.0, 3.0, 5.0, 8.0, 15.0],
                            ydata=[0.0, 1.0, 1.0 / eta, 1.78 / eta, 8.0, 9.05])

    boundary_x1 = Property(depends_on='+input')

    @cached_property
    def _get_boundary_x1(self):
        return self.fe_grid_roof.domain[-1, :, -1, -1, :, -1]

    #----------------------------------------------------
    # time loop
    #----------------------------------------------------

    tloop = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_tloop(self):
        domain = self.fe_grid_roof

        #----------------------------------------------------
        # loading and boundaries
        #----------------------------------------------------

        #--- LC1: dead load
        # g = 22.4 kN/m^3
        # orientation: global z-direction;
        material_density_roof = -22.43e-3  # [MN/m^3]

        #--- LC2 additional dead load
        # gA = 0,20 kN/m^2
        # orientation: global z-direction (following the curved structure);
        additional_dead_load = -0.20e-3  # [MN/m^2]

        #--- LC2 additional boundary load
        # gA = 0,35 kN/m^2
        # orientation: global z-direction (following the curved structure);
        boundary_dead_load = -0.35e-3  # [MN/m]

        #--- LC3 snow
        # s = 0,79 kN/m^2
        # orientation: global z-direction (projection);
        surface_load_s = -0.85e-3  # [MN/m^2]

        #--- LC4 wind (pressure)
        # w = 0,13 kN/m^2
        # orientation: local t-direction (surface normal);
        surface_load_w = -0.13e-3  # [MN/m^2]

        # NOTE: additional line-loads at the edge of the roof need to be considered!

        upper_surface = domain[:, :, -1, :, :, -1]
        whole_domain = domain[:, :, :, :, :, :]
        boundary_x1 = domain[-1, :, -1, -1, :, -1]
        boundary_y1 = domain[:, -1, -1, :, -1, -1]

        time_fn_load = self.time_fn_load

        time_fn_permanent_load = MFnLineArray(xdata=[0.0, 1.0],
                                              ydata=[0.0, 1.0])
        time_fn_snow_load = MFnLineArray(xdata=[0.0, 1.0], ydata=[0.0, 0.0])

        force_bc = [
            # own weight
            BCSlice(name='self weight',
                    var='f',
                    value=material_density_roof,
                    dims=[2],
                    integ_domain='global',
                    time_function=time_fn_load.get_value,
                    slice=whole_domain),

            # LC2: additional dead-load
            BCSlice(name='additional load',
                    var='f',
                    value=additional_dead_load,
                    dims=[2],
                    integ_domain='global',
                    time_function=time_fn_load.get_value,
                    slice=upper_surface),

            # LC2: additional boundary-load
            BCSlice(name='additional boundary load 1',
                    var='f',
                    value=boundary_dead_load,
                    dims=[2],
                    integ_domain='global',
                    time_function=time_fn_load.get_value,
                    slice=boundary_x1),

            # LC2: additional boundary-load
            BCSlice(name='additional boundary load 2',
                    var='f',
                    value=boundary_dead_load,
                    dims=[2],
                    integ_domain='global',
                    time_function=time_fn_load.get_value,
                    slice=boundary_y1),
            # LC3: snow load
            BCSlice(name='snow load',
                    var='f',
                    value=surface_load_s,
                    dims=[2],
                    integ_domain='global',
                    time_function=time_fn_snow_load.get_value,
                    slice=upper_surface),

            #                     # LC3: wind
            #                     BCSlice( var = 'f', value = surface_load_w, dims = [2],
            #                              integ_domain = 'global',
            #                              slice = upper_surface )
        ]

        bc_symplane_yz = BCSlice(var='u',
                                 value=0.,
                                 dims=[0],
                                 slice=domain[0, :, :, 0, :, :])
        bc_symplane_xz = BCSlice(var='u',
                                 value=0.,
                                 dims=[1],
                                 slice=domain[:, 0, :, :, 0, :])
        bc_support_000 = BCSlice(var='u',
                                 value=0.,
                                 dims=[2],
                                 slice=domain[0, 0, 0, :, :, 0])

        #        bc_column = [
        #                     BCSlice( var = 'u'  , dims = [0, 1, 2],
        #                              slice = domain[self.n_elems_xy_quarter - 1,
        #                                               self.n_elems_xy_quarter - 1,
        #                                               0,
        #                                               0, -1, 0 ],
        #                              value = 0. ),
        #                    BCSlice( var = 'u'  , dims = [0, 1, 2],
        #                            slice = domain[self.n_elems_xy_quarter - 1,
        #                                           self.n_elems_xy_quarter - 1 ,
        #                                           0,
        #                                           - 1, 0, 0],
        #                            value = 0. )]

        # bc_corner_load   = BCSlice( var = 'f', value = -nodal_load, dims = [2], slice = domain[-1,-1,-1,-1,-1,-1] )
        # bc_topface_load  = BCSlice( var = 'f', value = -nodal_load, dims = [2], slice = domain[:,:,-1,:,:,-1] )

        #        support_z_dofs = domain[0, 0, 0, :, : , 0].dofs[:, :, 2]
        #        support_f_w = RTraceGraph(name='force - corner deflection',
        #                           var_x='time', idx_x=0,
        #                           transform_x='x * %g' % lambda_failure,
        #                           var_y='F_int', idx_y_arr=np.unique(support_z_dofs.flatten()),
        #                           transform_y='-y',
        #                           record_on='update')

        rtrace_list = [self.f_w_diagram] + self.rtrace_list

        ts = TS(sdomain=[domain],
                dof_resultants=True,
                bcond_list=[bc_symplane_yz, bc_symplane_xz, bc_support_000] +
                force_bc,
                rtrace_list=rtrace_list)

        step = 1.0  # self.n_steps
        # Add the time-loop control
        tloop = TLoop(tstepper=ts,
                      RESETMAX=0,
                      KMAX=70,
                      tolerance=0.5e-3,
                      tline=TLine(min=0.0, step=step,
                                  max=1.0))  # self.max_lambda))
        return tloop
예제 #27
0
class CBRandXi(RF):
    '''
    Crack bridged by a fiber with constant
    frictional interface to rigid; free fiber end;
    '''

    implements(IRF)

    title = Str('crack bridge with rigid matrix')

    tau = Float(2.5,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'])

    r = Float(0.013,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform', 'norm'],
              desc='fiber radius')

    E_f = Float(72e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    m = Float(5.,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'])

    sV0 = Float(3.e-3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    V_f = Float(0.0175,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    w = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    include_pullout = Bool(True)

    x_label = Str('crack opening [mm]')
    y_label = Str('composite stress [MPa]')

    C_code = Str('')

    def __call__(self, w, tau, E_f, V_f, r, m, sV0):
        #strain and debonded length of intact fibers
        T = 2. * tau / r
        ef0_inf = np.sqrt(T * w / E_f)
        #scale parameter with respect to a reference volume
        s0 = ((T * (m + 1) * sV0**m) / (2. * E_f * pi * r**2))**(1. / (m + 1))
        k = np.sqrt(T / E_f)
        ef0 = k * np.sqrt(w)
        G = 1 - np.exp(-(ef0 / s0)**(m + 1))
        mu_int = ef0 * E_f * V_f * (1 - G)
        I = s0 * gamma(1 + 1. / (m + 1)) * gammainc(1 + 1. / (m + 1),
                                                    (ef0 / s0)**(m + 1))
        mu_broken = E_f * V_f * I / (m + 1)
        res = mu_int + mu_broken
        return res * r**2
예제 #28
0
class ExpBT3PT(ExType):
    '''Experiment: Bending Test Three Point
    '''
    #    label = Str('three point bending test')

    implements(IExType)

    file_ext = 'raw'

    #--------------------------------------------------------------------
    # register a change of the traits with metadata 'input'
    #--------------------------------------------------------------------

    input_change = Event

    @on_trait_change('+input, ccs.input_change, +ironing_param')
    def _set_input_change(self):
        self.input_change = True

    #--------------------------------------------------------------------------------
    # specify inputs:
    #--------------------------------------------------------------------------------

    length = Float(0.46,
                   unit='m',
                   input=True,
                   table_field=True,
                   auto_set=False,
                   enter_set=True)
    width = Float(0.1,
                  unit='m',
                  input=True,
                  table_field=True,
                  auto_set=False,
                  enter_set=True)
    thickness = Float(0.02,
                      unit='m',
                      input=True,
                      table_field=True,
                      auto_set=False,
                      enter_set=True)

    # age of the concrete at the time of testing
    age = Int(33,
              unit='d',
              input=True,
              table_field=True,
              auto_set=False,
              enter_set=True)
    loading_rate = Float(4.0,
                         unit='mm/min',
                         input=True,
                         table_field=True,
                         auto_set=False,
                         enter_set=True)

    #--------------------------------------------------------------------------
    # composite cross section
    #--------------------------------------------------------------------------

    ccs = Instance(CompositeCrossSection)

    def _ccs_default(self):
        '''default settings
        '''
        #        fabric_layout_key = 'MAG-07-03'
        #        fabric_layout_key = '2D-02-06a'
        fabric_layout_key = '2D-05-11'
        #        fabric_layout_key = '2D-09-12'
        #        concrete_mixture_key = 'PZ-0708-1'
        #        concrete_mixture_key = 'FIL-10-09'
        concrete_mixture_key = 'barrelshell'
        orientation_fn_key = 'all0'
        #        orientation_fn_key = 'all90'
        #        orientation_fn_key = '90_0'
        n_layers = 6
        s_tex_z = 0.020 / (n_layers + 1)
        ccs = CompositeCrossSection(fabric_layup_list=[
            plain_concrete(s_tex_z * 0.5),
            FabricLayUp(n_layers=n_layers,
                        orientation_fn_key=orientation_fn_key,
                        s_tex_z=s_tex_z,
                        fabric_layout_key=fabric_layout_key),
            plain_concrete(s_tex_z * 0.5)
        ],
                                    concrete_mixture_key=concrete_mixture_key)
        return ccs

    #--------------------------------------------------------------------------
    # Get properties of the composite
    #--------------------------------------------------------------------------

    # E-modulus of the composite at the time of testing
    E_c = Property(Float,
                   unit='MPa',
                   depends_on='input_change',
                   table_field=True)

    def _get_E_c(self):
        return self.ccs.get_E_c_time(self.age)

    # E-modulus of the composite after 28 days
    E_c28 = DelegatesTo('ccs', listenable=False)

    # reinforcement ration of the composite
    rho_c = DelegatesTo('ccs', listenable=False)

    #--------------------------------------------------------------------------------
    # define processing
    #--------------------------------------------------------------------------------

    # flag distinguishes weather data from a displacement gauge is available
    # stored in a separate ASC-file with a corresponding file name
    #
    flag_ASC_file = Bool(False)

    def _read_data_array(self):
        ''' Read the experiment data.
        '''
        if exists(self.data_file):

            print 'READ FILE'
            file_split = self.data_file.split('.')

            # first check if a '.csv' file exists. If yes use the
            # data stored in the '.csv'-file and ignore
            # the data in the '.raw' file!
            #
            file_name = file_split[0] + '.csv'
            if not os.path.exists(file_name):
                file_name = file_split[0] + '.raw'
                if not os.path.exists(file_name):
                    raise IOError, 'file %s does not exist' % file_name

            print 'file_name', file_name
            _data_array = loadtxt_bending(file_name)
            self.data_array = _data_array

            # check if a '.ASC'-file exists. If yes append this information
            # to the data array.
            #
            file_name = file_split[0] + '.ASC'
            if not os.path.exists(file_name):
                print 'NOTE: no data from displacement gauge is available (no .ASC file)'
                self.flag_ASC_file = False
            else:
                print 'NOTE: additional data from displacement gauge for center deflection is available (.ASC-file loaded)!'
                self.flag_ASC_file = True
                # add data array read in from .ASC-file; the values are assigned by '_set_array_attribs' based on the
                # read in values in 'names_and_units' read in from the corresponding .DAT-file
                #
                self.data_array_ASC = loadtxt(file_name, delimiter=';')
        else:
            print 'WARNING: data_file with path %s does not exist == False' % (
                self.data_file)

    names_and_units = Property(depends_on='data_file')

    @cached_property
    def _get_names_and_units(self):
        '''names and units corresponding to the returned '_data_array' by 'loadtxt_bending'
        '''
        names = ['w_raw', 'eps_c_raw', 'F_raw']
        units = ['mm', '1*E-3', 'N']
        print 'names, units from .raw-file', names, units
        return names, units

    names_and_units_ASC = Property(depends_on='data_file')

    @cached_property
    def _get_names_and_units_ASC(self):
        ''' Extract the names and units of the measured data.
        The order of the names in the .DAT-file corresponds
        to the order of the .ASC-file.
        '''
        file_split = self.data_file.split('.')
        file_name = file_split[0] + '.DAT'
        data_file = open(file_name, 'r')
        lines = data_file.read().split()
        names = []
        units = []
        for i in range(len(lines)):
            if lines[i] == '#BEGINCHANNELHEADER':
                name = lines[i + 1].split(',')[1]
                unit = lines[i + 3].split(',')[1]
                names.append(name)
                units.append(unit)

        print 'names, units extracted from .DAT-file', names, units
        return names, units

    factor_list_ASC = Property(depends_on='data_file')

    def _get_factor_list_ASC(self):
        return self.names_and_units_ASC[0]

    def _set_array_attribs(self):
        '''Set the measured data as named attributes defining slices into
        the processed data array.
        '''
        for i, factor in enumerate(self.factor_list):
            self.add_trait(
                factor,
                Array(value=self.processed_data_array[:, i], transient=True))

        if self.flag_ASC_file:
            for i, factor in enumerate(self.factor_list_ASC):
                self.add_trait(
                    factor,
                    Array(value=self.data_array_ASC[:, i], transient=True))

    elastomer_law = Property(depends_on='input_change')

    @cached_property
    def _get_elastomer_law(self):

        elastomer_path = os.path.join(simdb.exdata_dir, 'bending_tests',
                                      'three_point',
                                      '2011-06-10_BT-3PT-12c-6cm-0-TU_ZiE',
                                      'elastomer_f-w.raw')
        _data_array_elastomer = loadtxt_bending(elastomer_path)

        # force [kN]:
        # NOTE: after conversion 'F_elastomer' is a positive value
        #
        F_elastomer = -0.001 * _data_array_elastomer[:, 2].flatten()

        # displacement [mm]:
        # NOTE: after conversion 'w_elastomer' is a positive value
        #
        w_elastomer = -1.0 * _data_array_elastomer[:, 0].flatten()

        mfn_displacement_elastomer = MFnLineArray(xdata=F_elastomer,
                                                  ydata=w_elastomer)
        return frompyfunc(mfn_displacement_elastomer.get_value, 1, 1)

    w_wo_elast = Property(depends_on='input_change')

    @cached_property
    def _get_w_wo_elast(self):
        # use the machine displacement for the center displacement:
        # subtract the deformation of the elastomer cushion between the cylinder
        # and change sign in positive values for vertical displacement [mm]
        #
        return self.w_raw - self.elastomer_law(self.F_raw)

    M_ASC = Property(Array('float_'), depends_on='input_change')

    @cached_property
    def _get_M_ASC(self):
        return self.F_ASC * self.length / 4.0

    M_raw = Property(Array('float_'), depends_on='input_change')

    @cached_property
    def _get_M_raw(self):
        return self.F_raw * self.length / 4.0

#    # get only the ascending branch of the response curve
#    #
#    max_force_idx = Property(Int)
#    def _get_max_force_idx(self):
#        '''get the index of the maximum force'''
#        return argmax(-self.Kraft)
#
#    f_asc = Property(Array)
#    def _get_f_asc(self):
#        '''get only the ascending branch of the response curve'''
#        return -self.Kraft[:self.max_force_idx + 1]

    K_bending_elast = Property(Array('float_'), depends_on='input_change')

    @cached_property
    def _get_K_bending_elast(self):
        '''calculate the analytical bending stiffness of the beam (3 point bending)
        '''
        t = self.thickness
        w = self.width
        L = self.length

        # coposite E-modulus
        #
        E_c = self.E_c

        # moment of inertia
        #
        I_yy = t**3 * w / 12.

        delta_11 = (L**3) / 48 / E_c / I_yy

        # [MN/m]=[kN/mm] bending stiffness with respect to a force applied at center of the beam
        #
        K_bending_elast = 1 / delta_11
        #         print 'K_bending_elast', K_bending_elast

        return K_bending_elast

    F_cr = Property(Array('float_'), depends_on='input_change')

    @cached_property
    def _get_F_cr(self):
        '''calculate the analytical cracking load of the beam
        '''
        t = self.thickness
        w = self.width
        L = self.length

        # approx. flectural tensile strength
        #
        f_cfl = 6.  # MPa

        # resistant moment
        #
        W_yy = t**2 * w / 6.

        # analytical cracking load of the beam
        # corresponds to l = 0.46m and f_cfl = approx. 8.4 MPa#
        #
        F_cr = W_yy * f_cfl * 1000. / L  # [kN]

        return F_cr

    def process_source_data(self):
        '''read in the measured data from file and assign
        attributes after array processing.
        '''
        super(ExpBT3PT, self).process_source_data()

        #---------------------------------------------
        # process data from .raw file (machine data)
        #---------------------------------------------

        # convert machine force [N] to [kN] and return only positive values
        #
        self.F_raw *= -0.001

        # convert machine displacement [mm] to positive values
        # and remove offset
        #
        self.w_raw *= -1.0
        self.w_raw -= self.w_raw[0]

        # convert [permille] to [-] and return only positive values
        #
        self.eps_c_raw *= -0.001

        # access the derived arrays to initiate their processing
        #
        self.w_wo_elast
        self.M_raw

        #---------------------------------------------
        # process data from .ASC file (displacement gauge)
        #---------------------------------------------

        # only if separate ASC.-file with force-displacement data from displacement gauge is available
        #
        if self.flag_ASC_file == True:

            self.F_ASC = -1.0 * self.Kraft

            # remove offset and change sign to return positive displacement values
            #
            if hasattr(self, "WA50"):
                self.WA50 *= -1
                self.WA50 -= self.WA50[0]
                WA50_avg = np.average(self.WA50)

            if hasattr(self, "W10_u"):
                self.W10_u *= -1
                self.W10_u -= self.W10_u[0]
                W10_u_avg = np.average(self.W10_u)

            # check which displacement gauge has been used depending on weather two names are listed in .DAT file or only one
            # and assign values to 'w_ASC'
            #
            if hasattr(self, "W10_u") and hasattr(self, "WA50"):
                if W10_u_avg > WA50_avg:
                    self.w_ASC = self.W10_u
                    print 'self.W10_u assigned to self.w_ASC'
                else:
                    self.w_ASC = self.WA50
                    print 'self.WA50 assigned to self.w_ASC'
            elif hasattr(self, "W10_u"):
                self.w_ASC = self.W10_u
                print 'self.W10_u assigned to self.w_ASC'
            elif hasattr(self, "WA50"):
                self.w_ASC = self.WA50
                print 'self.WA50 assigned to self.w_ASC'

            # convert strain from [permille] to [-],
            # switch to positive values for compressive strains
            # and remove offset
            #
            self.eps_c_ASC = -0.001 * self.DMS_l
            self.eps_c_ASC -= self.eps_c_ASC[0]

            # access the derived arrays to initiate their processing
            #
            self.M_ASC

    #--------------------------------------------------------------------------------
    # plot templates
    #--------------------------------------------------------------------------------

    plot_templates = {
        'force / machine displacement (incl. w_elast)':
        '_plot_force_machine_displacement',
        'force / machine displacement (without w_elast)':
        '_plot_force_machine_displacement_wo_elast',
        'force / machine displacement (without w_elast, interpolated)':
        '_plot_force_machine_displacement_wo_elast_interpolated',
        'force / machine displacement (analytical offset)':
        '_plot_force_machine_displacement_wo_elast_analytical_offset',
        'force / gauge displacement': '_plot_force_gauge_displacement',
        'force / gauge displacement (analytical offset)':
        '_plot_force_gauge_displacement_with_analytical_offset',
        'force / gauge displacement (interpolated)':
        '_plot_force_gauge_displacement_interpolated',

        #                       'smoothed force / gauge displacement'            : '_plot_smoothed_force_gauge_displacement',
        #                       'smoothed force / machine displacement'          : '_plot_smoothed_force_machine_displacement_wo_elast',
        #
        'moment / eps_c (ASC)': '_plot_moment_eps_c_ASC',
        'moment / eps_c (raw)': '_plot_moment_eps_c_raw',
        #
        #                       'smoothed moment / eps_c (ASC)'                  : '_plot_smoothed_moment_eps_c_ASC',
        #                       'smoothed moment / eps_c (raw)'                  : '_plot_smoothed_moment_eps_c_raw',
        #
        #                       'analytical bending stiffness'                   :  '_plot_analytical_bending_stiffness'
    }

    default_plot_template = 'force / deflection (displacement gauge)'

    def _plot_analytical_bending_stiffness(self,
                                           axes,
                                           color='red',
                                           linewidth=1.,
                                           linestyle='--'):
        '''plot the analytical bending stiffness of the beam (3 point bending)
        '''
        t = self.thickness
        w = self.width
        L = self.length

        # composite E-modulus
        #
        E_c = self.E_c

        # moment of inertia
        #
        I_yy = t**3 * w / 12.

        delta_11 = L**3 / 48 / E_c / I_yy
        K_linear = 1 / delta_11  # [MN/m] bending stiffness with respect to a force applied at center of the beam
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., K_linear])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_force_machine_displacement_wo_elast(self,
                                                  axes,
                                                  color='blue',
                                                  linewidth=1.,
                                                  linestyle='-'):

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_raw)

        # get only the ascending branch of the response curve
        #
        f_asc = self.F_raw[:max_force_idx + 1]
        w_asc = self.w_wo_elast[:max_force_idx + 1]
        axes.plot(w_asc,
                  f_asc,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')
#        xkey = 'deflection [mm]'
#        ykey = 'force [kN]'
#        axes.set_xlabel('%s' % (xkey,))
#        axes.set_ylabel('%s' % (ykey,))

    def _plot_force_machine_displacement_wo_elast_interpolated(
            self, axes, color='green', linewidth=1., linestyle='-'):

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_raw)

        # get only the ascending branch of the response curve
        #
        f_asc = self.F_raw[:max_force_idx + 1]
        w_asc = np.copy(self.w_wo_elast[:max_force_idx + 1])

        # interpolate the starting point of the center deflection curve based on the slope of the curve
        # (remove offset in measured displacement where there is still no force measured)
        #
        idx_10 = np.where(f_asc > f_asc[-1] * 0.10)[0][0]
        idx_8 = np.where(f_asc > f_asc[-1] * 0.08)[0][0]
        f8 = f_asc[idx_8]
        f10 = f_asc[idx_10]
        w8 = w_asc[idx_8]
        w10 = w_asc[idx_10]
        m = (f10 - f8) / (w10 - w8)
        delta_w = f8 / m
        w0 = w8 - delta_w * 0.9
        #         print 'w0', w0
        f_asc_interpolated = np.hstack([0., f_asc[idx_8:]])
        w_asc_interpolated = np.hstack([w0, w_asc[idx_8:]])
        #         print 'type( w_asc_interpolated )', type(w_asc_interpolated)
        w_asc_interpolated -= float(w0)
        axes.plot(w_asc_interpolated,
                  f_asc_interpolated,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)

        #        fw_arr = np.hstack([f_asc_interpolated[:, None], w_asc_interpolated[:, None]])
        #        print 'fw_arr.shape', fw_arr.shape
        #        np.savetxt('BT-3PT-12c-6cm-TU_f-w_interpolated.csv', fw_arr, delimiter=';')

        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_force_machine_displacement_wo_elast_analytical_offset(
            self, axes, color='green', linewidth=1., linestyle='-'):

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_raw)

        # get only the ascending branch of the response curve
        #
        f_asc = self.F_raw[:max_force_idx + 1]
        w_asc = np.copy(self.w_wo_elast[:max_force_idx + 1])

        M_asc = f_asc * self.length / 4.
        eps_c_asc = self.eps_c_raw[:max_force_idx + 1]

        t = self.thickness
        w = self.width

        # coposite E-modulus
        #
        E_c = self.E_c

        # resistant moment
        #
        W_yy = t**2 * w / 6.

        K_I_analytic = W_yy * E_c  # [MN/m] bending stiffness with respect to center moment
        K_I_analytic *= 1000.  # [kN/m] bending stiffness with respect to center moment

        # interpolate the starting point of the center deflection curve based on the slope of the curve
        # (remove offset in measured displacement where there is still no force measured)
        #
        idx_lin = np.where(M_asc <= K_I_analytic * eps_c_asc)[0][0]
        idx_lin = int(idx_lin * 0.7)
        #         idx_lin = 50

        #        idx_lin = np.where(M_asc - M_asc[0] / eps_c_asc <= 0.90 * K_I_analytic)[0][0]
        print 'idx_lin', idx_lin
        print 'F_asc[idx_lin]', f_asc[idx_lin]
        print 'M_asc[idx_lin]', M_asc[idx_lin]
        print 'w_asc[idx_lin]', w_asc[idx_lin]

        w_lin_epsc = w_asc[idx_lin]

        w_lin_analytic = f_asc[idx_lin] / self.K_bending_elast

        f_asc_offset_analytic = f_asc[idx_lin:]
        w_asc_offset_analytic = w_asc[idx_lin:]
        w_asc_offset_analytic -= np.array([w_lin_epsc])
        w_asc_offset_analytic += np.array([w_lin_analytic])

        axes.plot(w_asc_offset_analytic,
                  f_asc_offset_analytic,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_force_machine_displacement(self,
                                         axes,
                                         color='black',
                                         linewidth=1.,
                                         linestyle='-'):
        xdata = self.w_raw
        ydata = self.F_raw
        axes.plot(xdata,
                  ydata,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        #        xkey = 'deflection [mm]'
        #        ykey = 'force [kN]'
        #        axes.set_xlabel('%s' % (xkey,))
        #        axes.set_ylabel('%s' % (ykey,))
        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_force_gauge_displacement_with_analytical_offset(
            self, axes, color='black', linewidth=1., linestyle='-'):

        # skip the first values (= first seconds of testing)
        # and start with the analytical bending stiffness instead to avoid artificial offset of F-w-diagram
        #
        #         w_max = np.max(self.w_ASC)
        #         cut_idx = np.where(self.w_ASC > 0.001 * w_max)[0]

        cut_idx = np.where(self.w_ASC > 0.01)[0]

        print 'F_cr ', self.F_cr
        #         cut_idx = np.where(self.F_ASC > 0.6 * self.F_cr)[0]

        print 'cut_idx', cut_idx[0]
        print 'w_ASC[cut_idx[0]]', self.w_ASC[cut_idx[0]]
        xdata = np.copy(self.w_ASC[cut_idx])
        ydata = np.copy(self.F_ASC[cut_idx])

        # specify offset if force does not start at the origin with value 0.
        F_0 = ydata[0]
        print 'F_0 ', F_0
        offset_w = F_0 / self.K_bending_elast
        xdata -= xdata[0]
        xdata += offset_w

        f_asc_interpolated = np.hstack([0, ydata])
        w_asc_interpolated = np.hstack([0, xdata])

        #        fw_arr = np.hstack([f_asc_interpolated[:, None], w_asc_interpolated[:, None]])
        #        print 'fw_arr.shape', fw_arr.shape
        #        np.savetxt('BT-3PT-6c-2cm-TU_f-w_interpolated.csv', fw_arr, delimiter=';')

        xdata = self.w_raw
        ydata = self.F_raw
        axes.plot(xdata,
                  ydata,
                  color='blue',
                  linewidth=linewidth,
                  linestyle=linestyle)

        axes.plot(w_asc_interpolated,
                  f_asc_interpolated,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        #        xkey = 'deflection [mm]'
        #        ykey = 'force [kN]'
        #        axes.set_xlabel('%s' % (xkey,))
        #        axes.set_ylabel('%s' % (ykey,))
        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_force_gauge_displacement(self,
                                       axes,
                                       offset_w=0.,
                                       color='black',
                                       linewidth=1.,
                                       linestyle='-'):
        xdata = self.w_ASC
        ydata = self.F_ASC

        # specify offset if force does not start at the origin
        xdata += offset_w

        axes.plot(xdata,
                  ydata,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        #        xkey = 'deflection [mm]'
        #        ykey = 'force [kN]'
        #        axes.set_xlabel('%s' % (xkey,))
        #        axes.set_ylabel('%s' % (ykey,))

        #        fw_arr = np.hstack([xdata[:, None], ydata[:, None]])
        #        print 'fw_arr.shape', fw_arr.shape
        #        np.savetxt('BT-3PT-6c-2cm-TU-80cm-V3_f-w_asc.csv', fw_arr, delimiter=';')

        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_smoothed_force_gauge_displacement(self, axes):

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_ASC)

        # get only the ascending branch of the response curve
        #
        F_asc = self.F_ASC[:max_force_idx + 1]
        w_asc = self.w_ASC[:max_force_idx + 1]

        n_points = int(self.n_fit_window_fraction * len(w_asc))
        F_smooth = smooth(F_asc, n_points, 'flat')
        w_smooth = smooth(w_asc, n_points, 'flat')

        axes.plot(w_smooth, F_smooth, color='blue', linewidth=2)

    def _plot_force_gauge_displacement_interpolated(self,
                                                    axes,
                                                    color='green',
                                                    linewidth=1.,
                                                    linestyle='-'):
        '''get only the ascending branch of the meassured load-displacement curve)'''

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_ASC)

        # get only the ascending branch of the response curve
        #
        f_asc = self.F_ASC[:max_force_idx + 1]
        w_asc = self.w_ASC[:max_force_idx + 1]

        # interpolate the starting point of the center deflection curve based on the slope of the curve
        # (remove offset in measured displacement where there is still no force measured)
        #
        idx_10 = np.where(f_asc > f_asc[-1] * 0.10)[0][0]
        idx_8 = np.where(f_asc > f_asc[-1] * 0.08)[0][0]
        f8 = f_asc[idx_8]
        f10 = f_asc[idx_10]
        w8 = w_asc[idx_8]
        w10 = w_asc[idx_10]
        m = (f10 - f8) / (w10 - w8)
        delta_w = f8 / m
        w0 = w8 - delta_w * 0.9
        print 'w0', w0

        f_asc_interpolated = np.hstack([0., f_asc[idx_8:]])
        w_asc_interpolated = np.hstack([w0, w_asc[idx_8:]])
        print 'type( w_asc_interpolated )', type(w_asc_interpolated)
        w_asc_interpolated -= float(w0)

        #        w_offset = f_asc[idx_10] / self.K_bending_elast
        #        f_asc_interpolated = np.hstack([0., f_asc[ idx_10: ]])
        #        w_asc_interpolated = np.hstack([0, w_asc[ idx_10: ] - w_asc[idx_10] + w_offset])

        axes.plot(w_asc_interpolated,
                  f_asc_interpolated,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)

        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')

    def _plot_smoothed_force_machine_displacement_wo_elast(self, axes):

        # get the index of the maximum stress
        #
        max_force_idx = argmax(self.F_raw)

        # get only the ascending branch of the response curve
        #
        F_asc = self.F_raw[:max_force_idx + 1]
        w_asc = self.w_wo_elast[:max_force_idx + 1]

        n_points = int(self.n_fit_window_fraction * len(w_asc))
        F_smooth = smooth(F_asc, n_points, 'flat')
        w_smooth = smooth(w_asc, n_points, 'flat')

        axes.plot(w_smooth, F_smooth, color='blue', linewidth=2)

        # plot analytical bending stiffness
        #
        w_linear = 2 * np.array([0., 1.])
        F_linear = 2 * np.array([0., self.K_bending_elast])
        axes.plot(w_linear, F_linear, linestyle='--')


#        secant_stiffness_w10 = ( f_smooth[10] - f_smooth[0] ) / ( w_smooth[10] - w_smooth[0] )
#        w0_lin = array( [0.0, w_smooth[10] ], dtype = 'float_' )
#        f0_lin = array( [0.0, w_smooth[10] * secant_stiffness_w10 ], dtype = 'float_' )

# axes.plot( w0_lin, f0_lin, color = 'black' )

    def _plot_moment_eps_c_ASC(self, axes):
        xkey = 'compressive strain [1*E-3]'
        ykey = 'moment [kNm]'
        xdata = self.eps_c_ASC
        ydata = self.M_ASC
        axes.set_xlabel('%s' % (xkey, ))
        axes.set_ylabel('%s' % (ykey, ))
        axes.plot(xdata, ydata)
        # plot stiffness in uncracked state
        t = self.thickness
        w = self.width
        # composite E-modulus
        #
        E_c = self.E_c

        # resistant moment
        #
        W_yy = t**2 * w / 6.

        max_M = np.max(self.M_raw)

        K_linear = W_yy * E_c  # [MN/m] bending stiffness with respect to center moment
        K_linear *= 1000.  # [kN/m] bending stiffness with respect to center moment
        w_linear = np.array([0., max_M / K_linear])
        M_linear = np.array([0., max_M])
        axes.plot(w_linear, M_linear, linestyle='--')

    def _plot_moment_eps_c_raw(self,
                               axes,
                               color='black',
                               linewidth=1.5,
                               linestyle='-'):
        xkey = 'compressive strain [1*E-3]'
        ykey = 'moment [kNm]'
        xdata = self.eps_c_raw
        ydata = self.M_raw
        axes.set_xlabel('%s' % (xkey, ))
        axes.set_ylabel('%s' % (ykey, ))
        axes.plot(xdata,
                  ydata,
                  color=color,
                  linewidth=linewidth,
                  linestyle=linestyle)
        # plot stiffness in uncracked state
        t = self.thickness
        w = self.width
        # composite E-modulus
        #
        E_c = self.E_c

        # resistant moment
        #
        W_yy = t**2 * w / 6.

        max_M = np.max(self.M_raw)

        K_linear = W_yy * E_c  # [MN/m] bending stiffness with respect to center moment
        K_linear *= 1000.  # [kN/m] bending stiffness with respect to center moment
        w_linear = np.array([0., max_M / K_linear])
        M_linear = np.array([0., max_M])
        axes.plot(w_linear, M_linear, linestyle='--')

    n_fit_window_fraction = Float(0.1)

    smoothed_M_eps_c_ASC = Property(depends_on='input_change')

    @cached_property
    def _get_smoothed_M_eps_c_ASC(self):
        # get the index of the maximum stress
        max_idx = argmax(self.M_ASC)
        # get only the ascending branch of the response curve
        m_asc = self.M_ASC[:max_idx + 1]
        eps_c_asc = self.eps_c_ASC[:max_idx + 1]
        n_points = int(self.n_fit_window_fraction * len(eps_c_asc))
        m_smoothed = smooth(m_asc, n_points, 'flat')
        eps_c_smoothed = smooth(eps_c_asc, n_points, 'flat')
        return m_smoothed, eps_c_smoothed

    smoothed_eps_c_ASC = Property

    def _get_smoothed_eps_c_ASC(self):
        return self.smoothed_M_eps_c_ASC[1]

    smoothed_M_ASC = Property

    def _get_smoothed_M_ASC(self):
        return self.smoothed_M_eps_c_ASC[0]

    def _plot_smoothed_moment_eps_c_ASC(self, axes):
        axes.plot(self.smoothed_eps_c_ASC,
                  self.smoothed_M_ASC,
                  color='blue',
                  linewidth=2)

    smoothed_M_eps_c_raw = Property(depends_on='input_change')

    @cached_property
    def _get_smoothed_M_eps_c_raw(self):
        # get the index of the maximum stress
        max_idx = argmax(self.M_raw)
        # get only the ascending branch of the response curve
        m_asc = self.M_raw[:max_idx + 1]
        eps_c_asc = self.eps_c_raw[:max_idx + 1]
        n_points = int(self.n_fit_window_fraction * len(eps_c_asc))
        m_smoothed = smooth(m_asc, n_points, 'flat')
        eps_c_smoothed = smooth(eps_c_asc, n_points, 'flat')
        return m_smoothed, eps_c_smoothed

    smoothed_eps_c_raw = Property

    def _get_smoothed_eps_c_raw(self):
        return self.smoothed_M_eps_c_raw[1]

    smoothed_M_raw = Property

    def _get_smoothed_M_raw(self):
        return self.smoothed_M_eps_c_raw[0]

    def _plot_smoothed_moment_eps_c_raw(self, axes):
        axes.plot(self.smoothed_eps_c_raw,
                  self.smoothed_M_raw,
                  color='blue',
                  linewidth=2)

    #--------------------------------------------------------------------------------
    # view
    #--------------------------------------------------------------------------------

    traits_view = View(VGroup(
        Group(Item('length', format_str="%.3f"),
              Item('width', format_str="%.3f"),
              Item('thickness', format_str="%.3f"),
              label='geometry'),
        Group(Item('loading_rate'), Item('age'), label='loading rate and age'),
        Group(Item('E_c', show_label=True, style='readonly',
                   format_str="%.0f"),
              Item('ccs@', show_label=False),
              label='composite cross section')),
                       scrollable=True,
                       resizable=True,
                       height=0.8,
                       width=0.6)
예제 #29
0
class SimBT4PT(IBVModel):
    '''Simulation: four point bending test.
    '''

    input_change = Event

    @on_trait_change('+input,ccs_unit_cell.input_change')
    def _set_input_change(self):
        self.input_change = True

    implements(ISimModel)

    #-----------------
    # discretization:
    #-----------------

    # specify weather the elastomer is to be modeled or if the load is
    # introduced as line load
    #
    elstmr_flag = Bool(True)

    # discretization in x-direction (longitudinal):
    #
    outer_zone_shape_x = Int(6, input=True, ps_levels=(4, 12, 3))

    # discretization in x-direction (longitudinal):
    #
    load_zone_shape_x = Int(2, input=True, ps_levels=(1, 4, 1))

    # middle part discretization in x-direction (longitudinal):
    #
    mid_zone_shape_x = Int(3, input=True, ps_levels=(1, 4, 1))

    # discretization in y-direction (width):
    #
    shape_y = Int(2, input=True, ps_levels=(1, 4, 2))

    # discretization in z-direction:
    #
    shape_z = Int(2, input=True, ps_levels=(1, 3, 3))

    #-----------------
    # geometry:
    #-----------------
    #
    # edge length of the bending specimen (beam) (entire length without symmetry)
    #
    length = Float(1.50, input=True)

    elstmr_length = Float(0.05, input=True)
    mid_zone_length = Float(0.50, input=True)
    elstmr_thickness = Float(0.005, input=True)
    width = Float(0.20, input=True)
    thickness = Float(0.06, input=True)

    #-----------------
    # derived geometric parameters
    #-----------------
    #
    # half the length of the elastomer (load introduction
    # with included symmetry)
    #
    sym_specmn_length = Property

    def _get_sym_specmn_length(self):
        return self.length / 2.

    sym_mid_zone_specmn_length = Property

    def _get_sym_mid_zone_specmn_length(self):
        return self.mid_zone_length / 2.

    # half the length of the elastomer (load introduction
    # with included symmetry
    #
    sym_elstmr_length = Property

    def _get_sym_elstmr_length(self):
        return self.elstmr_length / 2.

    # half the specimen width
    #
    sym_width = Property

    def _get_sym_width(self):
        return self.width / 2.

    #----------------------------------------------------------------------------------
    # mats_eval
    #----------------------------------------------------------------------------------

    # age of the plate at the time of testing
    # NOTE: that the same phi-function is used independent of age. This assumes a
    # an afine/proportional damage evolution for different ages.
    #
    age = Int(28, input=True)

    # time stepping params
    #
    tstep = Float(0.05, auto_set=False, enter_set=True, input=True)
    tmax = Float(1.0, auto_set=False, enter_set=True, input=True)
    tolerance = Float(0.001, auto_set=False, enter_set=True, input=True)

    # specify type of 'linalg.norm'
    # default value 'None' sets norm to 2-norm,
    # i.e "norm = sqrt(sum(x_i**2))
    #
    # set 'ord=np.inf' to switch norm to
    # "norm = max(abs(x_i))"
    #
    ord = Enum(np.inf, None)

    n_mp = Int(30, input=True)

    # @todo: for mats_eval the information of the unit cell should be used
    # in order to use the same number of microplanes and model version etc...
    #
    specmn_mats = Property(Instance(MATS2D5MicroplaneDamage),
                           depends_on='input_change')

    @cached_property
    def _get_specmn_mats(self):
        return MATS2D5MicroplaneDamage(
            E=self.E_c,
            #                                 E=self.E_m,
            nu=self.nu,
            # corresponding to settings in "MatsCalib"
            n_mp=self.n_mp,
            symmetrization='sum-type',
            model_version='compliance',
            phi_fn=self.phi_fn)

    if elstmr_flag:
        elstmr_mats = Property(Instance(MATS3DElastic),
                               depends_on='input_change')

        @cached_property
        def _get_elstmr_mats(self):
            # specify a small elastomer stiffness (approximation)
            E_elast = self.E_c / 10.
            print 'effective elastomer E_modulus', E_elast
            return MATS3DElastic(E=E_elast, nu=0.4)

    #-----------------
    # fets:
    #-----------------

    # specify element shrink factor in plot of fe-model
    #
    vtk_r = Float(0.95)

    # use quadratic serendipity elements
    #
    specmn_fets = Property(Instance(FETSEval), depends_on='input_change')

    @cached_property
    def _get_specmn_fets(self):
        fets = FETS2D58H20U(mats_eval=self.specmn_mats)
        fets.vtk_r *= self.vtk_r
        return fets

    # use quadratic serendipity elements
    #
    elstmr_fets = Property(Instance(FETSEval), depends_on='input_change')

    @cached_property
    def _get_elstmr_fets(self):
        fets = FETS2D58H20U(mats_eval=self.elstmr_mats)
        fets.vtk_r *= self.vtk_r
        return fets

    fe_domain = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_fe_domain(self):
        return FEDomain()

    #===========================================================================
    # fe level
    #===========================================================================

    outer_zone_specmn_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_outer_zone_specmn_fe_level(self):
        return FERefinementGrid(name='outer zone specimen patch',
                                fets_eval=self.specmn_fets,
                                domain=self.fe_domain)

    load_zone_specmn_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_load_zone_specmn_fe_level(self):
        return FERefinementGrid(name='load zone specimen patch',
                                fets_eval=self.specmn_fets,
                                domain=self.fe_domain)

    mid_zone_specmn_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_mid_zone_specmn_fe_level(self):
        return FERefinementGrid(name='mid zone specimen patch',
                                fets_eval=self.specmn_fets,
                                domain=self.fe_domain)

    elstmr_fe_level = Property(depends_on='+ps_levels, +input')

    def _get_elstmr_fe_level(self):
        return FERefinementGrid(name='elastomer patch',
                                fets_eval=self.elstmr_fets,
                                domain=self.fe_domain)

    #===========================================================================
    # Grid definition
    #===========================================================================

    mid_zone_specmn_fe_grid = Property(Instance(FEGrid),
                                       depends_on='+ps_levels, +input')

    @cached_property
    def _get_mid_zone_specmn_fe_grid(self):
        # only a quarter of the beam is simulated due to symmetry:
        fe_grid = FEGrid(coord_min=(0., 0., 0.),
                         coord_max=(self.sym_mid_zone_specmn_length -
                                    self.sym_elstmr_length, self.sym_width,
                                    self.thickness),
                         shape=(self.mid_zone_shape_x, self.shape_y,
                                self.shape_z),
                         level=self.mid_zone_specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

    load_zone_specmn_fe_grid = Property(Instance(FEGrid),
                                        depends_on='+ps_levels, +input')

    @cached_property
    def _get_load_zone_specmn_fe_grid(self):
        # only a quarter of the beam is simulated due to symmetry:
        fe_grid = FEGrid(coord_min=(self.sym_mid_zone_specmn_length -
                                    self.sym_elstmr_length, 0., 0.),
                         coord_max=(self.sym_mid_zone_specmn_length +
                                    self.sym_elstmr_length, self.sym_width,
                                    self.thickness),
                         shape=(self.load_zone_shape_x, self.shape_y,
                                self.shape_z),
                         level=self.load_zone_specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

#    if elstmr_flag:

    elstmr_fe_grid = Property(Instance(FEGrid),
                              depends_on='+ps_levels, +input')

    @cached_property
    def _get_elstmr_fe_grid(self):
        fe_grid = FEGrid(coord_min=(self.sym_mid_zone_specmn_length -
                                    self.sym_elstmr_length, 0.,
                                    self.thickness),
                         coord_max=(self.sym_mid_zone_specmn_length +
                                    self.sym_elstmr_length, self.sym_width,
                                    self.thickness + self.elstmr_thickness),
                         level=self.elstmr_fe_level,
                         shape=(self.load_zone_shape_x, self.shape_y, 1),
                         fets_eval=self.elstmr_fets)
        return fe_grid

    outer_zone_specmn_fe_grid = Property(Instance(FEGrid),
                                         depends_on='+ps_levels, +input')

    @cached_property
    def _get_outer_zone_specmn_fe_grid(self):
        # only a quarter of the plate is simulated due to symmetry:
        fe_grid = FEGrid(coord_min=(self.sym_mid_zone_specmn_length +
                                    self.sym_elstmr_length, 0., 0.),
                         coord_max=(self.sym_specmn_length, self.sym_width,
                                    self.thickness),
                         shape=(self.outer_zone_shape_x, self.shape_y,
                                self.shape_z),
                         level=self.outer_zone_specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

    #===========================================================================
    # Boundary conditions
    #===========================================================================
    w_max = Float(-0.030, input=True)  # [m]

    w_max = Float(-0.030, input=True)  # [m]

    bc_list = Property(depends_on='+ps_levels, +input')

    @cached_property
    def _get_bc_list(self):
        mid_zone_specimen = self.mid_zone_specmn_fe_grid
        load_zone_specimen = self.load_zone_specmn_fe_grid
        outer_zone_specimen = self.outer_zone_specmn_fe_grid

        if self.elstmr_flag:
            elastomer = self.elstmr_fe_grid

        #--------------------------------------------------------------
        # boundary conditions for the symmetry
        #--------------------------------------------------------------
        # symmetry in the xz-plane
        # (Note: the x-axis corresponds to the axis of symmetry along the longitudinal axis of the beam)
        #
        bc_outer_zone_symplane_xz = BCSlice(var='u',
                                            value=0.,
                                            dims=[1],
                                            slice=outer_zone_specimen[:,
                                                                      0, :, :,
                                                                      0, :])
        bc_load_zone_symplane_xz = BCSlice(var='u',
                                           value=0.,
                                           dims=[1],
                                           slice=load_zone_specimen[:, 0, :, :,
                                                                    0, :])
        bc_mid_zone_symplane_xz = BCSlice(var='u',
                                          value=0.,
                                          dims=[1],
                                          slice=mid_zone_specimen[:, 0, :, :,
                                                                  0, :])

        if self.elstmr_flag:
            bc_el_symplane_xz = BCSlice(var='u',
                                        value=0.,
                                        dims=[1],
                                        slice=elastomer[:, 0, :, :, 0, :])
        # symmetry in the yz-plane
        #
        bc_mid_zone_symplane_yz = BCSlice(var='u',
                                          value=0.,
                                          dims=[0],
                                          slice=mid_zone_specimen[0, :, :,
                                                                  0, :, :])

        #--------------------------------------------------------------
        # boundary conditions for the support
        #--------------------------------------------------------------
        bc_support_0y0 = BCSlice(var='u',
                                 value=0.,
                                 dims=[2],
                                 slice=outer_zone_specimen[-1, :, 0, -1, :, 0])

        #--------------------------------------------------------------
        # connect all grids
        #--------------------------------------------------------------
        link_loadzn_outerzn = BCDofGroup(
            var='u',
            value=0.,
            dims=[0, 1, 2],
            get_dof_method=load_zone_specimen.get_right_dofs,
            get_link_dof_method=outer_zone_specimen.get_left_dofs,
            link_coeffs=[1.])
        link_midzn_loadzn = BCDofGroup(
            var='u',
            value=0.,
            dims=[0, 1, 2],
            get_dof_method=mid_zone_specimen.get_right_dofs,
            get_link_dof_method=load_zone_specimen.get_left_dofs,
            link_coeffs=[1.])

        if self.elstmr_flag:
            link_elstmr_loadzn_z = BCDofGroup(
                var='u',
                value=0.,
                dims=[2],
                get_dof_method=elastomer.get_back_dofs,
                get_link_dof_method=load_zone_specimen.get_front_dofs,
                link_coeffs=[1.])

            # hold elastomer in a single point in order to avoid kinematic movement yielding singular K_mtx
            #
            bc_elstmr_fix = BCSlice(var='u',
                                    value=0.,
                                    dims=[0],
                                    slice=elastomer[0, 0, 0, 0, 0, 0])

        #--------------------------------------------------------------
        # loading
        #--------------------------------------------------------------
        # w_max = center displacement:
        w_max = self.w_max

        if self.elstmr_flag:
            # apply displacement at all top nodes of the elastomer (surface load)
            #
            bc_w = BCSlice(var='u',
                           value=w_max,
                           dims=[2],
                           slice=elastomer[:, :, -1, :, :, -1])
        else:
            bc_w = BCSlice(
                var='u',
                value=w_max,
                dims=[2],
                # slice is only exactly in the center of the loading zone for 'load_zone_shape_x' = 2
                # center line of the load zone
                slice=load_zone_specimen[0, :, -1, -1, :, -1])


#        f_max = 0.010 / 4. / self.sym_width
#        bc_line_f = BCSlice(var = 'f', value = f_max, dims = [2],
#                            # slice is only valid for 'load_zone_shape_x' = 2
#                            # center line of the load zone
#                            slice = load_zone_specimen[0, :, -1, -1, :, -1])

        bc_list = [
            bc_outer_zone_symplane_xz,
            bc_load_zone_symplane_xz,
            bc_mid_zone_symplane_xz,
            bc_mid_zone_symplane_yz,
            #
            link_midzn_loadzn,
            link_loadzn_outerzn,
            bc_support_0y0,
            #
            bc_w,
        ]

        if self.elstmr_flag:
            bc_list += [bc_el_symplane_xz, link_elstmr_loadzn_z, bc_elstmr_fix]

        return bc_list

    #----------------------
    # tloop
    #----------------------

    tloop = Property(depends_on='input_change')

    @cached_property
    def _get_tloop(self):

        #--------------------------------------------------------------
        # ts
        #--------------------------------------------------------------

        mid_zone_spec = self.mid_zone_specmn_fe_grid
        load_zone_spec = self.load_zone_specmn_fe_grid
        outer_zone_spec = self.outer_zone_specmn_fe_grid

        if self.elstmr_flag:
            # ELSTRMR TOP SURFACE
            # dofs at elastomer top surface (used to integrate the force)
            #
            elastomer = self.elstmr_fe_grid
            elstmr_top_dofs_z = elastomer[:, :, -1, :, :,
                                          -1].dofs[:, :, 2].flatten()
            load_dofs_z = np.unique(elstmr_top_dofs_z)
            print 'load_dofs_z', load_dofs_z
        else:
            # LINE LOAD TOP OF LOAD ZONE
            # dofs at center line of the specmn load zone (used to integrate the force)
            # note slice index in x-direction is only valid for load_zone_shape_x = 2 !
            #
            load_zone_spec_topline_dofs_z = load_zone_spec[
                0, :, -1, -1, :, -1].dofs[:, :, 2].flatten()
            load_dofs_z = np.unique(load_zone_spec_topline_dofs_z)
            print 'load_dofs_z', load_dofs_z

        # SUPPRT LINE
        # dofs at support line of the specmn (used to integrate the force)
        #
        outer_zone_spec_supprtline_dofs_z = outer_zone_spec[
            -1, :, 0, -1, :, 0].dofs[:, :, 2].flatten()
        supprt_dofs_z = np.unique(outer_zone_spec_supprtline_dofs_z)
        print 'supprt_dofs_z', supprt_dofs_z

        # CENTER DOF (used for tracing of the displacement)
        #
        center_bottom_dof = mid_zone_spec[0, 0, 0, 0, 0, 0].dofs[0, 0, 2]
        print 'center_bottom_dof', center_bottom_dof

        # THIRDPOINT DOF (used for tracing of the displacement)
        # dofs at center middle of the laod zone at the bottom side
        #
        # NOTE: slice index in x-direction is only valid for load_zone_shape_x = 2 !
        thirdpoint_bottom_dof = load_zone_spec[0, 0, 0, -1, 0, 0].dofs[0, 0, 2]
        print 'thirdpoint_bottom_dof', thirdpoint_bottom_dof

        # force-displacement-diagram (CENTER)
        #
        self.f_w_diagram_center = RTraceGraph(
            name='displacement_elasttop (center) - force',
            var_x='U_k',
            idx_x=center_bottom_dof,
            var_y='F_int',
            idx_y_arr=load_dofs_z,
            record_on='update',
            transform_x='-x * 1000',  # %g * x' % ( fabs( w_max ),),
            # due to symmetry the total force sums up from four parts of the beam (2 symmetry axis):
            #
            transform_y='-4000. * y')

        # force-displacement-diagram_supprt (SUPPRT)
        #
        self.f_w_diagram_supprt = RTraceGraph(
            name='displacement_supprtline (center) - force',
            var_x='U_k',
            idx_x=center_bottom_dof,
            var_y='F_int',
            idx_y_arr=supprt_dofs_z,
            record_on='update',
            transform_x='-x * 1000',  # %g * x' % ( fabs( w_max ),),
            # due to symmetry the total force sums up from four parts of the beam (2 symmetry axis):
            #
            transform_y='4000. * y')

        # force-displacement-diagram (THIRDPOINT)
        #
        self.f_w_diagram_thirdpoint = RTraceGraph(
            name='displacement_elasttop (thirdpoint) - force',
            var_x='U_k',
            idx_x=thirdpoint_bottom_dof,
            var_y='F_int',
            idx_y_arr=load_dofs_z,
            record_on='update',
            transform_x='-x * 1000',  # %g * x' % ( fabs( w_max ),),
            # due to symmetry the total force sums up from four parts of the beam (2 symmetry axis):
            #
            transform_y='-4000. * y')

        ts = TS(
            sdomain=self.fe_domain,
            bcond_list=self.bc_list,
            rtrace_list=[
                self.f_w_diagram_center,
                self.f_w_diagram_thirdpoint,
                self.f_w_diagram_supprt,
                RTraceDomainListField(name='Displacement',
                                      var='u',
                                      idx=0,
                                      warp=True),
                #                             RTraceDomainListField(name = 'Stress' ,
                #                                            var = 'sig_app', idx = 0, warp = True,
                #                                            record_on = 'update'),
                #                             RTraceDomainListField(name = 'Strain' ,
                #                                        var = 'eps_app', idx = 0, warp = True,
                #                                        record_on = 'update'),
                #                             RTraceDomainListField(name = 'Damage' ,
                #                                        var = 'omega_mtx', idx = 0, warp = True,
                #                                        record_on = 'update'),
                RTraceDomainListField(name='max_omega_i',
                                      warp=True,
                                      var='max_omega_i',
                                      idx=0,
                                      record_on='update'),
                #                             RTraceDomainListField(name = 'IStress' ,
                #                                            position = 'int_pnts',
                #                                            var = 'sig_app', idx = 0,
                #                                            record_on = 'update'),
                #                             RTraceDomainListField(name = 'IStrain' ,
                #                                            position = 'int_pnts',
                #                                            var = 'eps_app', idx = 0,
                #                                            record_on = 'update'),
            ])

        # Add the time-loop control
        tloop = TLoop(tstepper=ts,
                      KMAX=50,
                      tolerance=self.tolerance,
                      RESETMAX=0,
                      tline=TLine(min=0.0, step=self.tstep, max=self.tmax),
                      ord=self.ord)

        return tloop

    def peval(self):
        '''
        Evaluate the model and return the array of results specified
        in the method get_sim_outputs.
        '''
        U = self.tloop.eval()

        self.f_w_diagram_center.refresh()
        F_max = max(self.f_w_diagram_center.trace.ydata)

        u_center_top_z = U[self.center_top_dofs][0, 0, 2]
        return array([u_center_top_z, F_max], dtype='float_')

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='u_center_top_z', unit='m'),
            SimOut(name='F_max', unit='kN')
        ]
예제 #30
0
class CBEMClampedFiberStress(RF):
    '''
    Crack bridged by a fiber with constant
    frictional interface to the elastic matrix; clamped fiber end;
    Gives tension.
    '''

    implements(IRF)

    title = Str('crack bridge - clamped fiber with constant friction')

    xi = Float(0.0179,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['weibull_min', 'uniform'])

    tau = Float(2.5,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'])

    l = Float(10.0,
              auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='free length')

    r = Float(0.013,
              auto_set=False,
              input=True,
              enter_set=True,
              desc='fiber radius in mm')

    E_f = Float(72e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    E_m = Float(30e3,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    V_f = Float(0.0175,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform'])

    theta = Float(0.01,
                  auto_set=False,
                  enter_set=True,
                  input=True,
                  distr=['uniform', 'norm'],
                  desc='slack')

    phi = Float(1.,
                auto_set=False,
                enter_set=True,
                input=True,
                distr=['uniform', 'norm'],
                desc='bond quality')

    Ll = Float(1.,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'],
               desc='embedded length - left',
               ctrl_range=(0.0, 1.0, 10))

    Lr = Float(.5,
               auto_set=False,
               enter_set=True,
               input=True,
               distr=['uniform'],
               desc='embedded length - right',
               ctrl_range=(0.0, 1.0, 10))

    w = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    x = Float(auto_set=False,
              enter_set=True,
              input=True,
              distr=['uniform'],
              desc='crack width',
              ctrl_range=(0.0, 1.0, 10))

    x_label = Str('crack opening [mm]')
    y_label = Str('force [N]')

    C_code = Str('')

    def crackbridge(self, w, l, T, Kf, Km, Vf):
        # Phase A : Both sides debonding .
        Kc = Kf + Km
        c = Kc * T * l / 2.
        q0 = (np.sqrt(c**2 + w * Kf * Km * Kc * T) - c) / Km
        return q0 / Vf

    def pullout(self, w, l, T, Kf, Km, Vf, Lmin, Lmax):
        # Phase B : Debonding of shorter side is finished
        Kc = Kf + Km
        c = Kc * T * (Lmin + l)
        f = T**2 * Lmin**2 * Kc**2
        q1 = (np.sqrt(c**2. + f + 2 * w * Kc * T * Kf * Km) - c) / Km
        return q1 / Vf

    def linel(self, w, l, T, Kf, Km, Vf, Lmax, Lmin):
        # Phase C: Both sides debonded - linear elastic behavior.
        Kc = Kf + Km
        q2 = (2. * w * Kf * Km + T * Kc *
              (Lmin**2 + Lmax**2)) / (2. * Km * (Lmax + l + Lmin))
        return q2 / Vf

    def __call__(self, w, tau, l, E_f, E_m, theta, xi, phi, Ll, Lr, V_f, r):
        # assigning short and long embedded length
        Lmin = np.minimum(Ll, Lr)
        Lmax = np.maximum(Ll, Lr)

        Lmin = np.maximum(Lmin - l / 2., 1e-15)
        Lmax = np.maximum(Lmax - l / 2., 1e-15)

        # maximum condition for free length
        l = np.minimum(l / 2., Lr) + np.minimum(l / 2., Ll)

        # defining variables
        w = w - theta * l
        l = l * (1 + theta)
        w = H(w) * w
        T = 2. * tau * V_f / r
        Km = (1. - V_f) * E_m
        Kf = V_f * E_f
        Kc = Km + Kf

        # double sided debonding
        # q0 = self.crackbridge(w, l, T, Kr, Km, Lmin, Lmax)
        q0 = self.crackbridge(w, l, T, Kf, Km, V_f)

        # displacement at which the debonding to the closer clamp is finished
        w0 = (Lmin + l) * Lmin * Kc * T / Kf / Km

        # debonding of one side; the other side is clamped
        q1 = self.pullout(w, l, T, Kf, Km, V_f, Lmin, Lmax)

        # displacement at which the debonding is finished at both sides
        e1 = Lmax * Kc * T / Km / Kf
        w1 = e1 * (l + Lmax / 2.) + (e1 + e1 * Lmin / Lmax) * Lmin / 2.

        # debonding completed at both sides, response becomes linear elastic
        q2 = self.linel(w, l, T, Kf, Km, V_f, Lmax, Lmin)

        # cut out definition ranges
        q0 = H(w) * (q0 + 1e-15) * H(w0 - w)
        q1 = H(w - w0) * q1 * H(w1 - w)
        q2 = H(w - w1) * q2

        # add all parts
        q = q0 + q1 + q2
        # include breaking strain
        q = q * H(E_f * xi - q)
        return q