Esempio n. 1
0
class Reinforcement(HasTraits):
    '''common class for all reinforcement types'''
    label = Str('reinforcement')
    r = EitherType(klasses=[FloatType, RV])
    V_f = Float
    E_f = Float
    xi = EitherType(klasses=[FloatType, RV, WeibullFibers])
    tau = EitherType(klasses=[FloatType, RV])
    n_int = Int

    @on_trait_change('n_int')
    def check(self):
        if self.n_int < 50:
            print 'Warning: integration with', self.n_int, 'points might not be accurate enough'
            print 'a minimum of 50 integration points is recommended'
Esempio n. 2
0
class InfiniteEmbeddedLength(BaseBC):
    def __init__(self, **kw):
        super(InfiniteEmbeddedLength, self).__init__(**kw)
        self.L = infty

    type = EitherType(names=['double sided', 'one sided'],
                      klasses=[InfFreeDbl, InfFreeOne])
Esempio n. 3
0
class MATSExplore(IBVModel):

    '''
    Simulate the loading histories of a material point in 2D space.
    '''

    dim = EitherType(names=['1D', '1D5', '2D', '3D'],
                     klasses=[MATS1DExplore,
                              MATS1D5Explore,
                              MATS2DExplore,
                              MATS3DExplore
                              ])

    max_load = Float(5.0, enter_set=True, auto_set=False)

    time_function = Callable(lambda t: t)

    n_steps = Float(30, enter_set=True, auto_set=False)

    tolerance = Float(1e-5, enter_set=True, auto_set=False)

    n_iterations = Float(10, enter_set=True, auto_set=False)

    n_restarts = Float(5, enter_set=True, auto_set=False)

    def _dim_default(self):
        return MATS2DExplore(explorer=self)

    def _dim_changed(self):
        self.dim.explorer = self
        self.dim._mats_eval_changed()

    def _tloop_default(self):

        self.ts = TStepper(
            tse=self.dim.mats_eval,
            sdomain=FEUnitElem(mats_eval=self.dim.mats_eval)
        )

        # Put the time-stepper into the time-loop
        #
        n_steps = self.n_steps

        tloop = TLoop(tstepper=self.ts,
                      KMAX=100, RESETMAX=self.n_restarts,
                      tolerance=1e-7,
                      tline=TLine(min=0.0, step=1.0 / n_steps, max=1.0))

        return tloop

    traits_view = View(
        Item('dim@', show_label=False),
        resizable=True,
        width=1.0,
        height=1.0,
        scrollable=True,
    )
Esempio n. 4
0
class MATS2DExplore(MATSXDExplore):
    '''
    Simulate the loading histories of a material point in 2D space.
    '''

    mats_eval = EitherType(
        klasses=[MATS2DElastic, MATS2DMicroplaneDamage, MATS2DScalarDamage])

    def _mats_eval_default(self):
        return MATS2DElastic()
Esempio n. 5
0
class MATS1D5Explore(MATSXDExplore):
    '''
    Simulate the loading histories of a material point in 1D space.
    
    Specify the loading scenarios.
    '''
    mats_eval = EitherType(klasses=[MATS1D5Bond])

    def _mats_eval_default(self):
        return MATS1D5Bond()
Esempio n. 6
0
class MATS3DExplore(MATSXDExplore):
    '''
    Simulate the loading histories of a material point in 3D space.
    '''

    mats_eval = EitherType(klasses=[
        MATS3DElastic, MATS3DDesmorat, MATS3DMplCSDEEQ, MATS3DMicroplaneDamage,
        MATS3DScalarDamage
    ])

    def _mats_eval_default(self):
        return MATS3DScalarDamage()

    def _mats_eval_changed(self):
        pass
Esempio n. 7
0
class ShortFibers(Reinforcement):
    '''implements short fiber reinforcement'''
    phi = EitherType(
        klasses=[FloatType,
                 RV])  #inclination of short fibers to the crack plane normal
    Lf = Float  #length of short fibers
    bond_law = Enum('plastic', 'elasto-plastic')
    tau_fr = Float  # frictional bond at debonded interface
    k_tau = Float  #stiffness of the elastic adhesive bond
    beta = Float  #slip hardening coefficient
    snub = Float  # snubbing coefficient

    le = Property(depends_on='Lf')

    @cached_property
    def _get_le(self):
        return RV('uniform', loc=0.0, scale=self.Lf / 2.)
Esempio n. 8
0
class MATS2DPlastic(MATS2DEval):
    '''
    Elastic Model.
    '''

    implements(IMATSEval)

    #-------------------------------------------------------------------------
    # Parameters of the numerical algorithm (integration)
    #-------------------------------------------------------------------------

    stress_state = Enum(
        "plane strain",
        "plane stress",
    )
    algorithm = Enum("closest point", "cutting plane")

    #-------------------------------------------------------------------------
    # Material parameters
    #-------------------------------------------------------------------------
    yf = EitherType(klasses=[J2, DruckerPrager, Gurson, CamClay],
                    label="Yield Face",
                    desc="Yield Face Definition")
    #    yf = Instance( IYieldFace2D,
    #                 label = "Yield Face",
    #                 desc = "Yield Face Definition")
    E = Float(210.0e+3, label="E", desc="Young's Modulus")
    nu = Float(0.2, label='nu', desc="Poison's ratio")
    K_bar = Float(0., label='K', desc="isotropic softening parameter")
    H_bar = Float(0., label='H', desc="kinematic softening parameter")
    tolerance = Float(1.0e-4, label='TOL', desc="tolerance of return mapping")

    max_iter = Int(20, label='Iterations', desc="maximal number of iterations")

    D_el = Property(Array(float), depends_on='E, nu')

    @cached_property
    def _get_D_el(self):
        if self.stress_state == "plane_stress":
            return self._get_D_plane_stress()
        else:
            return self._get_D_plane_strain()

    H_mtx = Property(Array(float), depends_on='K_bar, H_bar')

    @cached_property
    def _get_H_mtx(self):
        H_mtx = diag([self.K_bar, self.H_bar, self.H_bar, self.H_bar])
        return H_mtx

    # This event can be used by the clients to trigger an action upon
    # the completed reconfiguration of the material model
    #

    #-------------------------------------------------------------------------
    # View specification
    #-------------------------------------------------------------------------

    view_traits = View(VSplit(
        Group(Item('yf'), Item('E'), Item('nu'), Item('K_bar'), Item('H_bar'),
              Item('tolerance'), Item('max_iter')),
        Group(
            Item('stress_state', style='custom'),
            Item('algorithm', style='custom'),
            Spring(resizable=True),
            label='Configuration parameters',
            show_border=True,
        ),
    ),
                       resizable=True)

    #-------------------------------------------------------------------------
    # Private initialization methods
    #-------------------------------------------------------------------------

    #-------------------------------------------------------------------------
    # Setup for computation within a supplied spatial context
    #-------------------------------------------------------------------------
    def get_state_array_size(self):
        '''
        Return number of number to be stored in state array
        @param sctx:spatial context
        '''
        return 7

    def setup(self, sctx):
        '''
        Intialize state variables.
        '''
        sctx.mats_state_array = zeros(7, float_)

    def new_cntl_var(self):
        return zeros(3, float_)

    def new_resp_var(self):
        return zeros(3, float_)

    #-------------------------------------------------------------------------
    # Evaluation - get the corrector and predictor
    #-------------------------------------------------------------------------

    def get_corr_pred(self, sctx, eps_app_eng, d_eps, tn, tn1):
        '''
        Corrector predictor computation.
        @param eps_app_eng input variable - engineering strain
        '''
        delta_gamma = 0.
        if sctx.update_state_on:
            # print "in us"
            eps_n = eps_app_eng - d_eps
            sigma, f_trial, epsilon_p, q_1, q_2 = self._get_state_variables(
                sctx, eps_n)

            sctx.mats_state_array[:3] = epsilon_p
            sctx.mats_state_array[3] = q_1
            sctx.mats_state_array[4:] = q_2

        diff1s = zeros([3])
        sigma, f_trial, epsilon_p, q_1, q_2 = self._get_state_variables(
            sctx, eps_app_eng)
        # Note: the state variables are not needed here, just gamma
        diff2ss = self.yf.get_diff2ss(eps_app_eng, self.E, self.nu, sctx)
        Xi_mtx = inv(inv(self.D_el) + delta_gamma * diff2ss * f_trial)
        N_mtx_denom = sqrt(dot(dot(diff1s, Xi_mtx), diff1s))
        if N_mtx_denom == 0.:
            N_mtx = zeros(3)
        else:
            N_mtx = dot(Xi_mtx, self.diff1s) / N_mtx_denom
        D_mtx = Xi_mtx - vdot(N_mtx, N_mtx)

        # print "sigma ",sigma
        # print "D_mtx ",D_mtx
        return sigma, D_mtx

    #-------------------------------------------------------------------------
    # Subsidiary methods realizing configurable features
    #-------------------------------------------------------------------------
    def _get_state_variables(self, sctx, eps_app_eng):
        epsilon_p = eps_p_old = sctx.mats_state_array[:3]
        q_1 = sctx.mats_state_array[3]
        q_2 = sctx.mats_state_array[4:]

        sigma = dot(self.D_el, (eps_app_eng - epsilon_p))
        xi_trial = sigma - q_2
        f_trial = self.yf.get_f_trial(xi_trial, q_1)
        # print "f_trial", f_trial
        R_k = zeros(3)
        int_count = 1
        while f_trial > self.tolerance or norm(R_k) > self.tolerance:
            if int_count > self.max_iter:
                print "Maximal number of iteration reached"
                break
            diff1s = self.yf.get_diff1s(eps_app_eng, self.E, self.nu, sctx)
            diff1q = self.yf.get_diff1q(eps_app_eng, self.E, self.nu, sctx)

            if self.stress_state == "plane stress":
                raise NotImplementedError
            else:
                if self.algorithm == "cutting plane":
                    delta_gamma_2 = (f_trial /
                                     (dot(dot(diff1s, self.D_el), diff1s) +
                                      dot(dot(diff1q, self.H_mtx), diff1q)))

                    delta_gamma += delta_gamma_2
                    epsilon_p += delta_gamma_2 * diff1s

                    q_1 += delta_gamma_2 * self.K_bar * diff1q[0]
                    q_2 += delta_gamma_2 * self.H_bar * diff1q[1:]

                elif self.algorithm == "closest point":
                    diff2ss = self.yf.get_diff2ss(eps_app_eng, self.E, self.nu,
                                                  sctx)
                    diff2sq = self.yf.get_diff2sq(eps_app_eng, self.E, self.nu,
                                                  sctx)
                    A_mtx_inv = inv(self.D_el) + delta_gamma * diff2ss
                    # self.delta_gamma *  diff2sq))
                    A_mtx = inv(A_mtx_inv)
                    delta_gamma_2 = ((f_trial - dot(dot(diff1s, A_mtx), R_k)) /
                                     (dot(dot(diff1s, A_mtx), diff1s)))

                    delta_eps_p = dot(dot(inv(self.D_el), A_mtx),
                                      R_k + delta_gamma_2 * diff1s)

                    epsilon_p += delta_eps_p
                    delta_gamma += delta_gamma_2

                    R_k = -epsilon_p + eps_p_old + delta_gamma * diff1s

                else:
                    raise NotImplementedError

            sigma = dot(self.D_el, (eps_app_eng - epsilon_p))
            xi_trial = sigma - q_2

            f_trial = self.yf.get_f_trial(xi_trial, q_1)
            # print "f_trial_after", self.f_trial
            int_count += 1
        return sigma, f_trial, epsilon_p, q_1, q_2

    def _get_D_plane_stress(self):
        E = self.E
        nu = self.nu
        D_stress = zeros([3, 3])
        D_stress[0][0] = E / (1.0 - nu * nu)
        D_stress[0][1] = E / (1.0 - nu * nu) * nu
        D_stress[1][0] = E / (1.0 - nu * nu) * nu
        D_stress[1][1] = E / (1.0 - nu * nu)
        D_stress[2][2] = E / (1.0 - nu * nu) * (1.0 / 2.0 - nu / 2.0)
        return D_stress

    def _get_D_plane_strain(self):
        E = self.E
        nu = self.nu
        D_strain = zeros([3, 3])
        D_strain[0][0] = E * (1.0 - nu) / (1.0 + nu) / (1.0 - 2.0 * nu)
        D_strain[0][1] = E / (1.0 + nu) / (1.0 - 2.0 * nu) * nu
        D_strain[1][0] = E / (1.0 + nu) / (1.0 - 2.0 * nu) * nu
        D_strain[1][1] = E * (1.0 - nu) / (1.0 + nu) / (1.0 - 2.0 * nu)
        D_strain[2][2] = E * (1.0 - nu) / (1.0 + nu) / (2.0 - 2.0 * nu)
        return D_strain

    #-------------------------------------------------------------------------
    # Response trace evaluators
    #-------------------------------------------------------------------------

    def get_sig_norm(self, sctx, eps_app_eng):
        sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0)
        return array([scalar_sqrt(sig_eng[0]**2 + sig_eng[1]**2)])

    def get_eps_p(self, sctx, eps_app_eng):
        # print "eps tracer ", sctx.mats_state_array[:3]
        return sctx.mats_state_array[:3]

    # Declare and fill-in the rte_dict - it is used by the clients to
    # assemble all the available time-steppers.
    #
    rte_dict = Trait(Dict)

    def _rte_dict_default(self):
        return {
            'sig_app': self.get_sig_app,
            'eps_app': self.get_eps_app,
            'sig_norm': self.get_sig_norm,
            'eps_p': self.get_eps_p
        }
Esempio n. 9
0
class Cuypers(HasTraits):
    '''
    Stochastic cracking model due to H. Cuypers (W. Curtin)
    matrix tensile strength is assumed to follow the Weibull distribution
    '''

    material = Instance(Material)

    def _material_default(self):
        return Material()

    m = Float(
        5.3,
        auto_set=False,
        enter_set=True,  # [-]
        desc='Weibull shape parameter for the matrix tensional strength [-]',
        modified=True)

    orientation = Range(
        low=0.0,
        high=Pi / 2,
        value=0.0,
        auto_set=False,
        enter_set=True,  # [-]
        desc='fiber orientation [rad]',
        modified=True)

    sigma_mu = Float(
        12.0,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='mean matrix tensional strength [MPa]',
        modified=True)

    sigma_fu = Float(
        720.0,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='fiber tensional strength [MPa]',
        modified=True)

    reinf_ratio = EitherType(names=['grid fiber layout', 'explicit value'],
                             klasses=[GridReinforcement, SimplyRatio],
                             modified=True)

    Pf = Range(
        low=0.0,
        high=1.0 - 1e-15,
        value=0.9,
        auto_set=False,
        enter_set=True,  # [-]
        desc='probability of crack spacing to be of final range',
        modified=True)

    sigma_ref = Range(
        low=1e-10,
        high=80.0,
        value=12.0,
        auto_set=False,
        enter_set=True,  # [MPa]
        desc='reference matrix stress',
        modified=True)

    sigma_ref_2 = Property(Float, depends_on='m, sigma_mu')

    def _get_sigma_ref_2(self):
        return e**(0.0991 / self.m) * self.scale_sigma_m

    rho = Property(Float, depends_on='reinf_ratio.rho,orientation')

    def _get_rho(self):
        if self.reinf_ratio.rho * cos(self.orientation) == 0:
            return 1e-15
        else:
            return self.reinf_ratio.rho * cos(self.orientation)

    V_f = Property(Float, depends_on='reinf_ratio.rho, orientation')

    @cached_property
    def _get_V_f(self):
        return self.rho

    V_m = Property(Float, depends_on='reinf_ratio.rho, orientation')

    @cached_property
    def _get_V_m(self):
        return 1 - self.rho

    alpha = Property(Float, depends_on='E_m,E_f,reinf_ratio.rho, orientation')

    @cached_property
    def _get_alpha(self):
        return (self.material.E_m * self.V_m) / (self.material.E_f * self.V_f)

    E_c = Property(Float, depends_on='E_m,E_f,reinf_ratio.rho, orientation')

    @cached_property
    def _get_E_c(self):
        return self.material.E_f * self.V_f + self.material.E_m * self.V_m

    delta_final = Property(Float, depends_on='E_m,E_f,rho,r,sigma_ref,tau,m')

    @cached_property
    def _get_delta_final(self):
        return self.sigma_ref * (self.V_m * self.material.r) / (
            self.V_f * 2 * self.material.tau)

    cs_final = Property(Float)

    def _get_cs_final(self):
        return 1.337 * self.delta_final

    def _get_delta(self, sigma_c):
        return sigma_c * (self.V_m * self.material.r * self.material.E_m) / (
            self.V_f * 2 * self.material.tau * self.E_c)

    # matrix strength scale parameter for the Weibull distribution with sigma_mu as
    # mean and m as shape parameter
    scale_sigma_m = Property(Float, depends_on='sigma_mu, m')

    @cached_property
    def _get_scale_sigma_m(self):
        return self.sigma_mu / gamma(1. + 1. / self.m)

    # composite scale parameter for the Weibull distribution with sigma_mu as
    # mean and m as shape parameter
    scale_sigma_c = Property(
        Float,
        depends_on='sigma_mu, m, E_m, E_f, reinf_ratio.rho, orientation')

    @cached_property
    def _get_scale_sigma_c(self):
        return self.scale_sigma_m / self.material.E_m * self.E_c

    def _get_cs(self, sigma_c):
        Pf = weibull_min.cdf(sigma_c, self.m, scale=self.scale_sigma_c)
        if Pf == 0:
            Pf = 1e-15
        return self.cs_final * 1.0 / Pf

    def eps_c(self, sigma_c):
        cs = self._get_cs(sigma_c)
        delta = self._get_delta(sigma_c)
        if cs > 2 * delta:
            return sigma_c / self.E_c * (1 + self.alpha * delta / cs)
        else:
            return sigma_c * (1. / (self.material.E_f * self.V_f) -
                              (self.alpha * cs) / (4. * delta * self.E_c))

    def _get_epsilon_c(self, sigma_c):
        get_epsilon_c = np.vectorize(self.eps_c)
        return get_epsilon_c(sigma_c)

    sigma_cu = Property(depends_on='rho, orientation, sigma_fu')

    @cached_property
    def _get_sigma_cu(self):
        '''Ultimate composite strength.
        The strength is given by the fiber strength related to the composite
        cross section by the reinforcement ratio rho and projected
        by the cosine of the fiber inclination into the loading direction.
        '''
        # 0.05 quantile strength of the matrix as a criterion for matrix failure
        # when this value is higher than the composite strength governed by the
        # reinforcement stress
        quantile = weibull_min.ppf(0.05, self.m, scale=self.scale_sigma_m)
        # composite failure due to matrix failure
        if self.sigma_fu * self.V_f * cos(
                self.orientation) < quantile / self.V_m:
            return quantile / self.V_m
        else:
            # composite failure due to fiber failure
            return self.sigma_fu * self.V_f * cos(self.orientation)

    csf = Property(
        depends_on='m, sigma_mu, sigma_ref, Pf, sigma_fu, orientation, E_f, E_m'
    )

    @cached_property
    def _get_csf(self):
        # composite stress at Pf probability for CS to be of final range
        # scale parameter for composite stress
        scale_sigma_c = self.scale_sigma_m / self.E_m * self.E_c

        sigma = weibull_min.ppf(self.Pf, self.m, scale=scale_sigma_c)

        # point of reaching final crack spacing
        epsilon_csf = np.hstack(
            (0, self._get_epsilon_c(sigma), self._get_epsilon_c(sigma)))
        sigma_csf = np.hstack((sigma, sigma, 0))
        return epsilon_csf, sigma_csf

    sig_eps_fn = Property(depends_on='+modified, reinf_ratio.+modified')

    @cached_property
    def _get_sig_eps_fn(self):
        '''Get the stress and strain arrays'''
        n_points = 100
        sigma_c_arr = np.linspace(0, self.sigma_cu, n_points)
        if self.sigma_cu == self.sigma_fu * self.V_f * cos(self.orientation):
            epsilon_c_arr = self._get_epsilon_c(sigma_c_arr)
        else:
            epsilon_c_arr = sigma_c_arr / self.E_c

        # stress with respect to reinforcement
        sigma_f_arr = sigma_c_arr / self.rho

        # stress of reinforcement with no matrix interaction
        sigma_fiber = epsilon_c_arr[[0, -1]] * self.material.E_f * self.rho

        return epsilon_c_arr, sigma_c_arr, sigma_f_arr, sigma_fiber
class PolarDiscr(HasTraits):
    '''
    Manager of the microplane arrays.

    This class is responsible for the generation and initialization
    and state management of an array of microplanes. Additionally, it
    can perform the setup of damage function parameters using the
    value of the microplane integrator object.
    '''

    mfn_class = Class(None)
    #-------------------------------------------------------------------------
    # Common parameters for for isotropic and anisotropic damage function specifications
    #-------------------------------------------------------------------------
    n_mp = Range(0, 50, 6, label='Number of microplanes', auto_set=False)

    E = Float(34e+3,
              label="E",
              desc="Young's Modulus",
              auto_set=False,
              enter_set=True)
    nu = Float(0.2,
               label='nu',
               desc="Poison's ratio",
               auto_set=False,
               enter_set=True)

    c_T = Float(
        0.0,
        label='c_T',
        desc='fraction of tangential stress accounted on each microplane',
        auto_set=False,
        enter_set=True)

    #-------------------------------------------------------------------------
    # list of angles
    #-------------------------------------------------------------------------
    alpha_list = Property(Array, depends_on='n_mp')

    @cached_property
    def _get_alpha_list(self):
        return array(
            [Pi / self.n_mp * (i - 0.5) for i in range(1, self.n_mp + 1)])

    #-------------------------------------------------------------------------
    # Damage function specification
    #-------------------------------------------------------------------------

    phi_fn = EitherType(klasses=[
        PhiFnGeneral, PhiFnGeneralExtended, PhiFnGeneralExtendedExp,
        PhiFnStrainSoftening, PhiFnStrainHardening, PhiFnStrainHardeningLinear,
        PhiFnStrainHardeningBezier
    ])

    def _phi_fn_default(self):
        print 'setting phi_fn default'
        return PhiFnStrainSoftening(polar_discr=self)

    def _phi_fn_changed(self):
        print 'setting phi_fn changed'
        self.phi_fn.polar_discr = self

    varied_params = List(Str, [])

    #-------------------------------------------------------------------------
    # Management of spatially varying parameters depending on the value of mats_eval
    #-------------------------------------------------------------------------
    varpars = Dict

    def _varpars_default(self):
        return self._get_varpars()

    @on_trait_change('phi_fn,varied_params')
    def _update_varpars(self):
        self.varpars = self._get_varpars()

    def _get_varpars(self):
        '''
        reset the varpar list according to the current phi_fn object.
        '''
        params = self.phi_fn.identify_parameters()
        varset = {}
        for key in params:
            par_val = getattr(self.phi_fn, key)
            varset[key] = VariedParam(phi_fn=self.phi_fn,
                                      mats_eval=self,
                                      varname=key)
            if key in self.varied_params:
                varset[key].switched_on = True
        return varset

    varpar_list = Property(List(VariedParam), depends_on='varpars')

    @cached_property
    def _get_varpar_list(self):
        return [self.varpars[key] for key in self.phi_fn.identify_parameters()]

    # variable selectable in the table of varied params (just for viewing)
    current_varpar = Instance(VariedParam)

    def _current_varpar_default(self):
        if len(self.varpar_list) > 0:
            return self.varpar_list[0]
        return None

    @on_trait_change('phi_fn')
    def set_current_varpar(self):
        if len(self.varpar_list) > 0:
            self.current_varpar = self.varpar_list[0]

    #-------------------------------------------------------------------------
    # Get the damage state for all microplanes
    #-------------------------------------------------------------------------
    def get_phi_arr(self, sctx, e_max_arr):
        '''
        Return the damage coefficients
        '''
        # gather the coefficients for parameters depending on the orientation
        carr_list = [
            self.varpars[key].polar_fn_vectorized(self.alpha_list)
            for key in self.phi_fn.identify_parameters()
        ]
        # vectorize the damage function evaluation
        n_arr = 1 + len(carr_list)
        phi_fn_vectorized = frompyfunc(self.phi_fn.get_value, n_arr, 1)
        # damage parameter for each microplane
        return phi_fn_vectorized(e_max_arr, *carr_list)

    def get_polar_fn_fracture_energy_arr(self, sctx, e_max_arr):
        '''
        Return the fracture energy contributions
        '''
        carr_list = [
            self.varpars[key].polar_fn_vectorized(self.alpha_list)
            for key in self.phi_fn.identify_parameters()
        ]
        # vectorize the damage function evaluation
        n_arr = 1 + len(carr_list)
        integ_phi_fn_vectorized = frompyfunc(self.phi_fn.get_integ, n_arr, 1)
        return self.E * integ_phi_fn_vectorized(e_max_arr, *carr_list)

    polar_fn_group = Group(
        Group(Item('n_mp@', width=200),
              Item('E'),
              Item('nu'),
              Item('c_T'),
              Spring(),
              label='Elasticity parameters'),
        Group(Item('phi_fn@', show_label=False), label='Damage parameters'),
        Group(VSplit(
            Item('varpar_list',
                 label='List of material variables',
                 show_label=False,
                 editor=varpar_editor),
            Item('current_varpar',
                 label='Selected variable',
                 show_label=False,
                 style='custom',
                 resizable=True),
            dock='tab',
        ),
              label='Angle-dependent variations'),
        Include('config_param_vgroup'),
        layout='tabbed',
        springy=True,
        dock='tab',
        id='ibvpy.mats.matsXD_cmdm.MATSXDPolarDiscr',
    )

    traits_view = View(Include('polar_fn_group'),
                       resizable=True,
                       scrollable=True,
                       width=0.6,
                       height=0.9)
Esempio n. 11
0
class Reinforcement(HasTraits):

    label = Str('reinforcement')
    r = EitherType(klasses=[FloatType, RV])
    V_f = Float
    E_f = Float
    xi = EitherType(klasses=[FloatType, RV, WeibullFibers])
    tau = EitherType(klasses=[FloatType, RV])
    n_int = Int

    results = Property(depends_on='r, V_f, E_f, xi, tau, n_int')

    @cached_property
    def _get_results(self):
        stat_weights = 1.0
        if isinstance(self.tau, RV):
            tau = self.tau.ppf(
                np.linspace(.5 / self.n_int, 1. - .5 / self.n_int, self.n_int))
            stat_weights *= 1. / self.n_int
            nu_r_tau = np.ones_like(tau)
        else:
            tau = self.tau
            nu_r_tau = 1.0
        if isinstance(self.r, RV):
            r = self.r.ppf(
                np.linspace(.5 / self.n_int, 1. - .5 / self.n_int, self.n_int))
            stat_weights *= 1. / self.n_int
            r2 = r**2
            nu_r = r2 / np.mean(r2)
        else:
            r = self.r
            r2 = r**2
            nu_r = nu_r_tau * 1.0
        if isinstance(tau, np.ndarray) and isinstance(r, np.ndarray):
            r = r.reshape(1, self.n_int)
            tau = tau.reshape(self.n_int, 1)
            nu_r_r = (r2 / np.mean(r2)).reshape(1, self.n_int)
            nu_r_tau = np.ones(self.n_int).reshape(self.n_int, 1)
            nu_r = nu_r_r * nu_r_tau
            r_arr = (nu_r * np.mean(r2))**0.5
            return (2. * tau / r / self.E_f
                    ).flatten(), stat_weights, nu_r.flatten(), r_arr.flatten()
        else:
            r_arr = (nu_r * np.mean(r2))**0.5
            return 2. * tau / r / self.E_f, stat_weights, nu_r, r_arr

    depsf_arr = Property(depends_on='r, V_f, E_f, xi, tau, n_int')

    @cached_property
    def _get_depsf_arr(self):
        return self.results[0]

    stat_weights = Property(depends_on='r, V_f, E_f, xi, tau, n_int')

    @cached_property
    def _get_stat_weights(self):
        return self.results[1]

    nu_r = Property(depends_on='r, V_f, E_f, xi, tau, n_int')

    @cached_property
    def _get_nu_r(self):
        return self.results[2]

    r_arr = Property(depends_on='r, V_f, E_f, xi, tau, n_int')

    @cached_property
    def _get_r_arr(self):
        return self.results[3]
Esempio n. 12
0
class MATS1D5Bond(MATS1D5Eval):
    '''Bond model for two phases interacting over an interface with zero thickness.

    Both phases can be associated with arbitrary 1D mats model.
    Interface behavior can be defined for both sliding and opening using 1D mats models.
    '''
    implements(IMATSEval)

    #-------------------------------------------------------------------------
    # Submodels constituting the interface behavior
    #-------------------------------------------------------------------------

    mats_phase1 = EitherType(klasses=mats_klasses,
                             desc='Material model of phase 1')
    mats_ifslip = EitherType(klasses=mats_klasses,
                             desc='Material model for interface slippage')
    mats_ifopen = EitherType(klasses=mats_klasses,
                             desc='Material model for interface opening')
    mats_phase2 = EitherType(klasses=mats_klasses,
                             desc='Material model for phase 2')

    def _mats_phase1_default(self):
        return MATS1DElastic()

    def _mats_ifslip_default(self):
        return MATS1DElastic()

    def _mats_ifopen_default(self):
        return MATS1DElastic()

    def _mats_phase2_default(self):
        return MATS1DElastic()

    traits_view = View(Item('mats_phase1@'),
                       Item('mats_ifslip@'),
                       Item('mats_ifopen@'),
                       Item('mats_phase2@'),
                       resizable=True,
                       scrollable=True,
                       width=0.8,
                       height=0.9,
                       buttons=['OK', 'Cancel'])

    #-------------------------------------------------------------------------
    # Subsidiary maps to enable generic loop over the material models
    #-------------------------------------------------------------------------

    # order of the material model names used for association in generic loops
    _mats_names = List(
        ['mats_phase1', 'mats_slip', 'mats_open', 'mats_phase2'])

    # hidden list of all four involved mats
    _mats_list = Property(
        depends_on='mats_phase1, mats_slip, mats_open, mats_phase2')

    @cached_property
    def _get__mats_list(self):
        return [
            self.mats_phase1, self.mats_ifslip, self.mats_ifopen,
            self.mats_phase2
        ]

    # state array map with the sizes of the array
    _state_sizes = Property(
        depends_on='mats_phase1, mats_slip, mats_open, mats_phase2')

    @cached_property
    def _get__state_sizes(self):
        return array([mats.get_state_array_size() for mats in self._mats_list],
                     dtype='int_')

    # state array map with the sizes of the array
    _state_offsets = Property(
        depends_on='mats_phase1, mats_slip, mats_open, mats_phase2')

    @cached_property
    def _get__state_offsets(self):
        offsets = zeros_like(self._state_sizes)
        offsets[1:] = self._state_sizes[:-1].cumsum()
        return offsets

    #-------------------------------------------------------------------------
    # Setup for computation within a supplied spatial context
    #-------------------------------------------------------------------------

    def get_state_array_size(self):
        '''
        Return the number of floats to be saved
        '''
        return self._state_sizes.cumsum()[-1]

    #-------------------------------------------------------------------------
    # Evaluation - get the corrector and predictor
    #-------------------------------------------------------------------------

    def get_corr_pred(self, sctx, eps_app_eng, d_eps_app_eng, tn, tn1, *args,
                      **kw):
        '''
        Corrector predictor computation.
        @param eps_app_eng input variable - engineering strain
        '''

        sig_app_eng = zeros_like(eps_app_eng)
        # @todo [rch] dirty - when called form response tracer
        if isinstance(d_eps_app_eng, int) and d_eps_app_eng == 0:
            d_eps_app_eng = zeros_like(eps_app_eng)

        D_mtx = zeros((eps_app_eng.shape[0], eps_app_eng.shape[0]),
                      dtype='float_')

        mats_state_array = sctx.mats_state_array

        for i, mats in enumerate(self._mats_list):

            # extract the stress components
            eps, d_eps = eps_app_eng[i], d_eps_app_eng[i]
            size = self._state_sizes[i]
            offset = self._state_offsets[i]
            sctx.mats_state_array = mats_state_array[offset:offset + size]

            sig_app_eng[i], D_mtx[i, i] = mats.get_corr_pred(
                sctx, eps, d_eps, tn, tn1)

        sctx.mats_state_array = mats_state_array

        return sig_app_eng, D_mtx

    def get_sig1(self, sctx, eps_app_eng, *args, **kw):
        sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0)
        return sig_eng[0:1]

    def get_sig2(self, sctx, eps_app_eng, *args, **kw):
        sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0)
        return sig_eng[3:]

    def get_shear_flow(self, sctx, eps_app_eng, *args, **kw):
        sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0)
        return sig_eng[1:2]

    def get_cohesive_stress(self, sctx, eps_app_eng, *args, **kw):
        sig_eng, D_mtx = self.get_corr_pred(sctx, eps_app_eng, 0, 0, 0)
        return sig_eng[2:3]

    rte_dict = Property

    def _get_rte_dict(self):

        rte_dict = {}
        ix_maps = [0, 1, 2, 3]
        for name, mats, ix_map, size, offset in \
            zip(self._mats_names, self._mats_list, ix_maps, self._state_sizes,
                self._state_offsets):
            for key, v_eval in mats.rte_dict.items():

                __call_v_eval = RTE1D5Bond(v_eval=v_eval,
                                           name=name + '_' + key,
                                           size=size,
                                           offset=offset,
                                           ix_map=ix_map)

                rte_dict[name + '_' + key] = __call_v_eval

        # sigma is also achievable through phase1_sig_app and phase_2_sig_app
        extra_rte_dict = {
            'sig1': self.get_sig1,
            'sig2': self.get_sig2,
            'shear_flow': self.get_shear_flow,
            'cohesive_stress': self.get_cohesive_stress,
        }
        rte_dict.update(extra_rte_dict)
        return rte_dict

    #-------------------------------------------------------------------------
    # Methods required by the mats_explore tool
    #-------------------------------------------------------------------------

    def new_cntl_var(self):
        return zeros(4, 'float_')

    def new_resp_var(self):
        return zeros(4, 'float_')
Esempio n. 13
0
class RFModelView( ModelView ):

    title = Str( 'RF browser' )

    model = Instance( IRF )

    child = Instance( SPIRRID )
    def _child_default( self ):
        return SPIRRID()

    rf = EitherType( names = ['brittle filament',
                              'pullout short fiber',
                              'crack bridge short fiber',
                              'pullout clamped fiber',
                              'crack bridge clamped fiber',
                              'pullout infinite fiber',
                              'crack bridge infinite fiber',
                              ],

                            klasses = [Filament,
                                       POShortFiber,
                                       CBShortFiber,
                                       POClampedFiber,
                                       CBClampedFiber,
                                       POInfiniteFiber,
                                       CBInfiniteFiber,
                                       ],

                            config_change = True )

    def _model_default( self ):
        return self.rf

    def _rf_changed( self ):
        self.model = self.rf
        self.child.rf = self.model
        for name in self.model.param_keys:
            self.on_trait_change( self._redraw, 'rf.' + name )

    def init( self, info ):
        for name in self.model.param_keys:
            self.on_trait_change( self._redraw, 'rf.' + name )

    def close( self, info, is_ok ):
        for name in self.model.param_keys:
            self.on_trait_change( self._redraw, 'rf.' + name, remove = True )
        return is_ok

    figure = Instance( Figure )
    def _figure_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.08, 0.13, 0.85, 0.74] )
        return figure

    data_changed = Event( True )

    max_x = Float( 0.04, enter_set = True, auto_set = False, config_change = True )
    x_points = Int( 80, enter_set = True, auto_set = False, config_change = True )

    @on_trait_change( '+config_change' )
    def _redraw( self ):
        in_arr = linspace( 0.0, self.max_x, self.x_points )
        self.model = self.rf
        args = [ in_arr ] + self.model.param_values

        # get the number of parameters of the response function
        n_args = len( args )
        fn = frompyfunc( self.model.__call__, n_args, 1 )

        out_arr = fn( *args )

        axes = self.figure.axes[0]
        axes.plot( in_arr, out_arr,
                   linewidth = 2, label = self.model.title )

        axes.set_xlabel( self.model.x_label )
        axes.set_ylabel( self.model.y_label )
        #axes.legend( loc = 'best' )

        self.data_changed = True
    show = Button
    def _show_fired( self ):
        self._redraw()

    clear = Button
    def _clear_fired( self ):
        axes = self.figure.axes[0]
        axes.clear()
        self.data_changed = True

    def default_traits_view( self ):
        '''
        Generates the view from the param items.
        '''
        #rf_param_items = [ Item( 'model.' + name, format_str = '%g' ) for name in self.model.param_keys ]
        D2_plot_param_items = [ VGroup( Item( 'max_x' , label = 'max x value' ),
                                       Item( 'x_points', label = 'No of plot points' ) ) ]

        if hasattr( self.rf, 'get_q_x' ):
            D3_plot_param_items = [ VGroup( Item( 'min_x', label = 'min x value' ),
                                       Item( 'max_x', label = 'max x value' ),
                                       Item( 'min_y', label = 'min y value' ),
                                       Item( 'max_y', label = 'max y value' ) )
                                       ]
        else:
            D3_plot_param_items = []

        control_items = [
                        Item( 'show', show_label = False ),
                        Item( 'clear', show_label = False ),
                        ]
        view = View( HSplit( VGroup( Item( '@rf', show_label = False ),
                                     label = 'Function parameters',
                                     id = 'stats.spirrid.rf_model_view.rf_params',
                                     scrollable = True
                                     ),
                             VGroup( HGroup( *D2_plot_param_items ),
                                     label = 'plot parameters',
                                     id = 'stats.spirrid.rf_model_view.2Dplot_params'
                                     ),
#                            VGroup( HGroup( *D3_plot_param_items ),
#                                     label = '3D plot parameters',
#                                     id = 'stats.spirrid.rf_model_view.3Dplot_params' ),
                             VGroup( Item( 'model.comment', show_label = False,
                                           style = 'readonly' ),
                                     label = 'Comment',
                                     id = 'stats.spirrid.rf_model_view.comment',
                                     scrollable = True,
                                     ),
                             VGroup( 
                                    HGroup( *control_items ),
                                    Item( 'figure', editor = MPLFigureEditor(),
                                     resizable = True, show_label = False ),
                                     label = 'Plot',
                                     id = 'stats.spirrid.rf_model_view.plot'
                                     ),
                             dock = 'tab',
                             id = 'stats.spirrid.rf_model_view.split'
                             ),
                    kind = 'modal',
                    resizable = True,
                    dock = 'tab',
                    buttons = [OKButton],
                    id = 'stats.spirrid.rf_model_view'
                    )
        return view
Esempio n. 14
0
class SCM(HasTraits):
    '''
    Stochastic Cracking Theory
    '''
    E_f = Float(
        120e+3,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='the E-Modulus of the fiber [MPa]',
        modified=True)

    E_m = Float(
        34.e+3,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='E-Modulus of the matrix [MPa]',
        modified=True)

    tau = Float(
        8.0,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='the frictional stress between fiber and matrix [MPa]',
        modified=True)

    r = Float(
        0.5,
        auto_set=False,
        enter_set=True,  # [mm]
        desc='the radius of the fiber',
        modified=True)

    m = Float(
        2.3,
        auto_set=False,
        enter_set=True,  # [-]
        desc=
        'the Weibull modulus defining the scatter of the matrix strength [-]',
        modified=True)

    orientation = Range(
        low=0.0,
        high=Pi / 2,
        value=0.0,
        auto_set=False,
        enter_set=True,  # [-]
        desc='Fiber orientation [rad]',
        modified=True)

    sigma_mu = Float(
        12.0,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='the matrix tensional strength as a scale parameter'
        ' of the Weibull distribution [MPa]',
        modified=True)

    sigma_fu = Float(
        720.0,
        auto_set=False,
        enter_set=True,  # [N/mm^2]
        desc='the fiber tensional strength [MPa]',
        modified=True)

    reinf_ratio = EitherType(names=['grid fiber layout', 'explicit value'],
                             klasses=[GridReinforcement, SimplyRatio],
                             modified=True)

    Pf = Range(
        low=0.0,
        high=1.0 - 1e-15,
        value=0.9,
        auto_set=False,
        enter_set=True,  # [-]
        desc='probability of crack spacing to be of final range',
        modified=True)

    rho = Property(Float, depends_on='reinf_ratio.rho,orientation')

    def _get_rho(self):
        if self.reinf_ratio.rho * cos(self.orientation) == 0:
            return 1e-15
        else:
            return self.reinf_ratio.rho * cos(self.orientation)

    V_f = Property(Float, depends_on='rho')

    @cached_property
    def _get_V_f(self):
        return self.rho

    V_m = Property(Float, depends_on='rho')

    @cached_property
    def _get_V_m(self):
        return 1 - self.rho

    alpha = Property(Float, depends_on='E_m,E_f,rho')

    @cached_property
    def _get_alpha(self):
        return (self.E_m * self.V_m) / (self.E_f * self.V_f)

    E_c = Property(Float, depends_on='E_m,E_f,rho')

    @cached_property
    def _get_E_c(self):
        return self.E_f * self.V_f + self.E_m * self.V_m

    delta_final = Property(Float, depends_on='E_m,E_f,rho,r,sigma_mu,tau,m')

    @cached_property
    def _get_delta_final(self):
        return self.sigma_mu * (self.V_m * self.r) / (self.V_f * 2 * self.tau)

    cs_final = Property(Float)

    def _get_cs_final(self):
        return 1.337 * self.delta_final

    def _get_delta(self, sigma_c):
        return sigma_c * (self.V_m * self.r * self.E_m) / (self.V_f * 2 *
                                                           self.tau * self.E_c)

    # matrix strength scale parameter for the Weibull distribution with sigma_mu as
    # mean and m as shape parameter
    scale_sigma_m = Property(Float, depends_on='sigma_mu, m')

    @cached_property
    def _get_scale_sigma_m(self):
        return self.sigma_mu / gamma(1. + 1. / self.m)

    # composite scale parameter for the Weibull distribution with sigma_mu as
    # mean and m as shape parameter
    # TODO: the mean composite cracking stress increases with increasing
    # reinforcement ratio - this has yet to be implemented
    scale_sigma_c = Property(Float, depends_on='sigma_mu, m, E_m, E_f, rho')

    @cached_property
    def _get_scale_sigma_c(self):
        return self.scale_sigma_m / self.E_m * self.E_c

    def _get_cs(self, sigma_c):
        Pf = weibull_min.cdf(sigma_c, self.m, scale=self.scale_sigma_c)
        if Pf == 0:
            Pf = 1e-15
        return self.cs_final * 1.0 / Pf

    def eps_c(self, sigma_c):
        cs = self._get_cs(sigma_c)
        delta = self._get_delta(sigma_c)
        print('delta')
        print(delta)
        if cs > 2 * delta:
            print(sigma_c / self.E_c * (1 + self.alpha * delta / cs))
            return sigma_c / self.E_c * (1 + self.alpha * delta / cs)
        else:
            print(sigma_c * (1. / (self.E_f * self.V_f) - (self.alpha * cs) /
                             (4. * delta * self.E_c)))

            return sigma_c * (1. / (self.E_f * self.V_f) - (self.alpha * cs) /
                              (4. * delta * self.E_c))

    def _get_epsilon_c(self, sigma_c):
        get_epsilon_c = frompyfunc(self.eps_c, 1, 1)
        return get_epsilon_c(sigma_c)

    sigma_cu = Property(depends_on='rho, orientation, sigma_fu')

    @cached_property
    def _get_sigma_cu(self):
        '''Ultimate composite strength.

        The strength is given by the fiber strength related to the composite
        cross section by the reinforcement ratio rho and projected
        by the cosine of the fiber inclination into the loading direction.
        '''
        # 0.05 quantile strength of the matrix as a criterion for matrix failure
        # when this value is higher than the composite strength governed by the
        # reinforcement stress
        quantile = weibull_min.ppf(0.05, self.m, scale=self.scale_sigma_m)
        # composite failure due to matrix failure
        if self.sigma_fu * self.V_f * cos(
                self.orientation) < quantile / self.V_m:
            return quantile / self.V_m
        else:
            # composite failure due to fiber failure
            return self.sigma_fu * self.V_f * cos(self.orientation)

    csf = Property(
        depends_on='m, sigma_mu, Pf, sigma_fu, orientation, E_f, E_m')

    @cached_property
    def _get_csf(self):
        # composite stress at Pf probability for CS to be of final range
        # scale parameter for composite stress
        scale_sigma_c = self.scale_sigma_m / self.E_m * self.E_c

        sigma = weibull_min.ppf(self.Pf, self.m, scale=scale_sigma_c)

        # point of reaching final crack spacing
        epsilon_csf = hstack(
            (0, self._get_epsilon_c(sigma), self._get_epsilon_c(sigma)))
        sigma_csf = hstack((sigma, sigma, 0))
        return epsilon_csf, sigma_csf

    sig_eps_fn = Property(depends_on='+modified, reinf_ratio.+modified')

    @cached_property
    def _get_sig_eps_fn(self):
        '''Get the stress and strain arrays'''
        print('update')
        n_points = 100
        sigma_c_arr = linspace(0, self.sigma_cu, n_points)
        if self.sigma_cu == self.sigma_fu * self.V_f * cos(self.orientation):
            epsilon_c_arr = self._get_epsilon_c(sigma_c_arr)
        else:
            epsilon_c_arr = sigma_c_arr / self.E_c

        # stress with respect to reinforcement
        sigma_f_arr = sigma_c_arr / self.rho

        # stress of reinforcement with no matrix interaction
        sigma_fiber = epsilon_c_arr[[0, -1]] * self.E_f * self.rho

        print(epsilon_c_arr)

        return epsilon_c_arr, sigma_c_arr, sigma_f_arr, sigma_fiber

    traits_view = View(Group(
        Tabbed(
            VGroup(
                Group(
                    Item('E_f',
                         resizable=True,
                         full_size=True,
                         label='E-modulus',
                         tooltip="Young's modulus of the fiber"),
                    Item('sigma_fu',
                         resizable=True,
                         label='strength',
                         help="Strength of the fibers"),
                    label='fibers',
                ),
                Group(
                    Item('E_m',
                         resizable=True,
                         full_size=True,
                         label='E-modulus',
                         help="Young's modulus of the matrix"),
                    Item('sigma_mu',
                         resizable=True,
                         label='strength',
                         help="Scale parameter of the matrix strength"
                         'roughly corresponding to the mean strength'),
                    Item('m',
                         resizable=True,
                         label='Weibull-modulus',
                         help=
                         "Weibull modulus of the matrix strength distribution"
                         'defining the scatter of the strength'),
                    label='matrix',
                    scrollable=False,
                ),
                label='Components',
                dock='tab',
                id='scm.model.component_params',
            ),
            VGroup(
                Item('tau', resizable=True, full_size=True, springy=False),
                Item('r', resizable=False, springy=False),
                springy=True,
                label='Bond',
                dock='tab',
                id='scm.model.params',
            ),
            id='scm.model.allparams',
        ),
        VGroup(
            Item('reinf_ratio@', show_label=False, resizable=True),
            label='Cross section parameters',
            dock='tab',
            id='scm.model.reinf_ratio',
        ),
        VGroup(Item('orientation', label='fiber orientation'), ),
        id='scm.model.splitter',
        springy=False,
        layout='split',
    ),
                       id='scm.model',
                       dock='fixed',
                       scrollable=True,
                       resizable=True,
                       buttons=[OKButton],
                       height=0.8,
                       width=0.8)
Esempio n. 15
0
class RFModelView(ModelView):

    model = Instance(IRF)

    def _model_default(self):
        return Filament()

    resp_func = EitherType(
        names=['brittle filament', 'dbl pullout const friction short fiber'],
        klasses=[Filament, ConstantFrictionFiniteFiber],
        config_change=True)

    def init(self, info):
        for name in self.model.param_keys:
            self.on_trait_change(self._redraw, 'model.' + name)

    def close(self, info, is_ok):
        for name in self.model.param_keys:
            self.on_trait_change(self._redraw, 'model.' + name, remove=True)
        return is_ok

    figure = Instance(Figure)

    def _figure_default(self):
        figure = Figure(facecolor='white')
        figure.add_axes([0.08, 0.13, 0.85, 0.74])
        return figure

    data_changed = Event(True)

    max_x = Float(0.01, enter_set=True, auto_set=False, config_change=True)
    n_points = Int(20, enter_set=True, auto_set=False, config_change=True)

    @on_trait_change('+config_change')
    def _redraw(self):

        self.model = self.resp_func
        figure = self.figure
        axes = self.figure.axes[0]

        in_arr = linspace(0.0, self.max_x, self.n_points)

        args = [in_arr] + self.model.param_values

        # get the number of parameters of the response function

        n_args = len(args)
        fn = frompyfunc(self.model.__call__, n_args, 1)

        out_arr = fn(*args)

        axes = self.figure.axes[0]
        axes.plot(in_arr, out_arr, linewidth=2)

        axes.set_xlabel(self.model.x_label)
        axes.set_ylabel(self.model.y_label)
        axes.legend(loc='best')

        self.data_changed = True

    show = Button

    def _show_fired(self):
        self._redraw()

    clear = Button

    def _clear_fired(self):
        axes = self.figure.axes[0]
        axes.clear()
        self.data_changed = True

    def default_traits_view(self):
        '''
        Generates the view from the param items.
        '''
        #rf_param_items = [ Item( 'model.' + name, format_str = '%g' ) for name in self.model.param_keys ]
        plot_param_items = [
            Item('max_x', label='max x value'),
            Item('n_points', label='No of plot points')
        ]
        control_items = [
            Item('show', show_label=False),
            Item('clear', show_label=False),
        ]
        view = View(
            HSplit(
                VGroup(
                    Item('@resp_func', show_label=False),  #*rf_param_items,
                    label='Function Parameters',
                    id='stats.spirrid_bak.rf_model_view.rf_params',
                    scrollable=True),
                VGroup(*plot_param_items,
                       label='Plot Parameters',
                       id='stats.spirrid_bak.rf_model_view.plot_params'),
                VGroup(
                    Item('model.comment', show_label=False, style='readonly'),
                    label='Comment',
                    id='stats.spirrid_bak.rf_model_view.comment',
                    scrollable=True,
                ),
                VGroup(HGroup(*control_items),
                       Item('figure',
                            editor=MPLFigureEditor(),
                            resizable=True,
                            show_label=False),
                       label='Plot',
                       id='stats.spirrid_bak.rf_model_view.plot'),
                dock='tab',
                id='stats.spirrid_bak.rf_model_view.split'),
            kind='modal',
            resizable=True,
            dock='tab',
            buttons=[OKButton],
            id='stats.spirrid_bak.rf_model_view')
        return view
Esempio n. 16
0
class MATS2DScalarDamage(MATS2DEval):
    '''
    Scalar Damage Model.
    '''

    implements(IMATSEval)

    #---------------------------------------------------------------------------
    # Parameters of the numerical algorithm (integration)
    #---------------------------------------------------------------------------

    stress_state = Enum("plane_stress", "plane_strain")
    stiffness = Enum("secant", "algoritmic")

    #---------------------------------------------------------------------------
    # Material parameters
    #---------------------------------------------------------------------------

    E = Float(34e+3, label="E", desc="Young's Modulus", auto_set=False)
    nu = Float(0.2, label='nu', desc="Poison's ratio", auto_set=False)
    epsilon_0 = Float(59e-6,
                      label="eps_0",
                      desc="Breaking Strain",
                      auto_set=False)

    epsilon_f = Float(191e-4,
                      label="eps_f",
                      desc="Shape Factor",
                      auto_set=False)

    strain_norm = EitherType(
        klasses=[Mazars, Euclidean, Energy, Mises, Rankine])

    D_el = Property(Array(float), depends_on='E, nu, stress_state')

    @cached_property
    def _get_D_el(self):
        if self.stress_state == "plane_stress":
            return self._get_D_plane_stress()
        else:
            return self._get_D_plane_strain()

    # This event can be used by the clients to trigger an action upon
    # the completed reconfiguration of the material model
    #
    changed = Event

    #--------------------------------------------------------------------------
    # View specification
    #--------------------------------------------------------------------------

    view_traits = View(VSplit(
        Group(Item('E'), Item('nu'), Item('epsilon_0'), Item('epsilon_f'),
              Item('strain_norm')),
        Group(
            Item('stress_state', style='custom'),
            Item('stiffness', style='custom'),
            Spring(resizable=True),
            label='Configuration parameters',
            show_border=True,
        ),
    ),
                       resizable=True)

    #--------------------------------------------------------------------------
    # Private initialization methods
    #--------------------------------------------------------------------------

    #--------------------------------------------------------------------------
    # Setup for computation within a supplied spatial context
    #--------------------------------------------------------------------------

    def get_state_array_size(self):
        '''
        Return number of number to be stored in state array
        @param sctx:spatial context
        '''
        return 2

    def setup(self, sctx):
        '''
        Intialize state variables.
        @param sctx:spatial context
        '''
        state_arr_size = self.get_state_array_size()
        sctx.mats_state_array = zeros(state_arr_size, 'float_')
        # sctx.update_state_on = False

    def new_cntl_var(self):
        '''
        Return contoll variable array
        '''
        return zeros(3, float_)

    def new_resp_var(self):
        '''
        Return contoll response array
        '''
        return zeros(3, float_)

    #--------------------------------------------------------------------------
    # Evaluation - get the corrector and predictor
    #--------------------------------------------------------------------------

    def get_corr_pred(self, sctx, eps_app_eng, d_eps, tn, tn1, eps_avg=None):
        '''
        Corrector predictor computation.
        @param eps_app_eng input variable - engineering strain
        '''
        if eps_avg != None:
            pass
        else:
            eps_avg = eps_app_eng

        if sctx.update_state_on:

            eps_n = eps_avg - d_eps

            e_max, omega = self._get_state_variables(sctx, eps_n)

            sctx.mats_state_array[0] = e_max
            sctx.mats_state_array[1] = omega

        e_max, omega = self._get_state_variables(sctx, eps_app_eng)

        if self.stiffness == "algorithmic" and \
                    e_max > self.epsilon_0 and \
                    e_max > sctx.mats_state_array[0]:
            D_e_dam = self._get_alg_stiffness(eps_app_eng, e_max, omega)
        else:
            D_e_dam = (1 - omega) * self.D_el

        sigma = dot(((1 - omega) * self.D_el), eps_app_eng)

        # You print the stress you just computed and the value of the apparent E
        return sigma, D_e_dam

    #--------------------------------------------------------------------------
    # Subsidiary methods realizing configurable features
    #--------------------------------------------------------------------------
    def _get_state_variables(self, sctx, eps_app_eng):
        e_max = sctx.mats_state_array[0]
        omega = sctx.mats_state_array[1]

        f_trial = self.strain_norm.get_f_trial(eps_app_eng, self.D_el, self.E,
                                               self.nu, e_max)
        if f_trial > 0:
            e_max += f_trial
            omega = self._get_omega(e_max)

        return e_max, omega

    def _get_omega(self, kappa):
        '''
        Return new value of damage parameter
        @param kappa:
        '''
        epsilon_0 = self.epsilon_0
        epsilon_f = self.epsilon_f
        if kappa >= epsilon_0:
            # return 1.-epsilon_0/kappa*exp(-1*(kappa-epsilon_0)/epsilon_f)
            return 1. - epsilon_0 / kappa * exp(-1 * (kappa - epsilon_0) / \
                                                  (epsilon_f - epsilon_0))
        else:
            return 0.

    def _get_alg_stiffness(self, eps_app_eng, e_max, omega):
        '''
        Return algorithmic stiffness matrix
        @param eps_app_eng:strain
        @param e_max:kappa
        @param omega:damage parameter
        '''
        epsilon_0 = self.epsilon_0
        epsilon_f = self.epsilon_f
        dodk = epsilon_0 / (e_max * e_max) * exp(-(e_max - epsilon_0) / epsilon_f) + \
                epsilon_0 / e_max / epsilon_f * exp(-(e_max - epsilon_0) / epsilon_f)
        dede = self.strain_norm.get_dede(eps_app_eng, self.D_el, self.E,
                                         self.nu)
        D_alg = (1 - omega) * self.D_el - \
                dot(dot(self.D_el, eps_app_eng), dede) * dodk
        return D_alg

    def _get_D_plane_stress(self):
        '''
        Elastic Matrix - Plane Stress
        '''
        E = self.E
        nu = self.nu
        D_stress = zeros([3, 3])
        D_stress[0][0] = E / (1.0 - nu * nu)
        D_stress[0][1] = E / (1.0 - nu * nu) * nu
        D_stress[1][0] = E / (1.0 - nu * nu) * nu
        D_stress[1][1] = E / (1.0 - nu * nu)
        D_stress[2][2] = E / (1.0 - nu * nu) * (1.0 / 2.0 - nu / 2.0)
        return D_stress

    def _get_D_plane_strain(self):
        '''
        Elastic Matrix - Plane Strain
        '''
        E = self.E
        nu = self.nu
        D_strain = zeros([3, 3])
        D_strain[0][0] = E * (1.0 - nu) / (1.0 + nu) / (1.0 - 2.0 * nu)
        D_strain[0][1] = E / (1.0 + nu) / (1.0 - 2.0 * nu) * nu
        D_strain[1][0] = E / (1.0 + nu) / (1.0 - 2.0 * nu) * nu
        D_strain[1][1] = E * (1.0 - nu) / (1.0 + nu) / (1.0 - 2.0 * nu)
        D_strain[2][2] = E * (1.0 - nu) / (1.0 + nu) / (2.0 - 2.0 * nu)
        return D_strain

    #--------------------------------------------------------------------------
    # Response trace evaluators
    #--------------------------------------------------------------------------

    def get_omega(self, sctx, eps_app_eng, *args, **kw):
        '''
        Return damage parameter for RT
        @param sctx:spatial context
        @param eps_app_eng:actual strain
        '''
        return array([sctx.mats_state_array[1]])

    # Declare and fill-in the rte_dict - it is used by the clients to
    # assemble all the available time-steppers.
    #
    rte_dict = Trait(Dict)

    def _rte_dict_default(self):
        return {
            'sig_app': self.get_sig_app,
            'eps_app': self.get_eps_app,
            'omega': self.get_omega
        }
Esempio n. 17
0
class ClampedFibre(BaseBC):

    type = EitherType(names=['one sided', 'double sided'],
                      klasses=[FinClampOne, FinClampDbl])
Esempio n. 18
0
class FiniteEmbeddedLength(BaseBC):

    type = EitherType(names=['double sided', 'one sided'],
                      klasses=[FinFreeDbl, FinFreeOne])
Esempio n. 19
0
class MATS3DScalarDamage(MATS3DEval):
    r'''
    Isotropic damage model.
    '''
    node_name = 'Scalar damage'

    stiffness = tr.Enum("secant", "algorithmic", input=True)
    r'''Selector of the stiffness calculation.
    '''
    strain_norm = EitherType(klasses=[
        Rankine,
    ], input=True)
    r'''Selector of the strain norm defining the load surface.
    '''

    epsilon_0 = tr.Float(5e-2,
                         label="eps_0",
                         desc="Strain at the onset of damage",
                         auto_set=False,
                         input=True)
    r'''Damage function parameter - slope of the damage function.
    '''

    epsilon_f = tr.Float(191e-1,
                         label="eps_f",
                         desc="Slope of the damage function",
                         auto_set=False,
                         input=True)
    r'''Damage function parameter - slope of the damage function.
    '''

    changed = tr.Event
    r'''This event can be used by the clients to trigger 
    an action upon the completed reconfiguration of 
    the material model
    '''

    state_var_shapes = {'kappa': (), 'omega': ()}
    r'''
    Shapes of the state variables
    to be stored in the global array at the level 
    of the domain.
    '''
    def init(self, kappa, omega):
        r'''
        Initialize the state variables.
        '''
        kappa[...] = 0
        omega[...] = 0

    def get_corr_pred(self, eps_Emab_n1, tn1, kappa, omega):
        r'''
        Corrector predictor computation.
        '''
        I = self.update_state_variables(eps_Emab_n1, kappa, omega)
        phi_Em = (1.0 - omega)
        D_Emabcd = np.einsum('...,abcd->...abcd', phi_Em, self.D_abef)
        sigma_Emab = np.einsum('...abcd,...cd->...ab', D_Emabcd, eps_Emab_n1)

        # algorithmic switched off - because the derivative
        # of the strain norm is still not available
        if False:  # algorithmic:
            D_Emabcd_red_I = self._get_D_abcd_alg_reduction(
                kappa[I], eps_Emab_n1[I])
            D_Emabcd[I] -= D_Emabcd_red_I

        return sigma_Emab, D_Emabcd

    def update_state_variables(self, eps_Emab, kappa, omega):
        eps_eq_Em = self.strain_norm.get_eps_eq(eps_Emab, kappa)
        f_trial_Em = eps_eq_Em - self.epsilon_0
        I = np.where(f_trial_Em > 0)
        kappa[I] = eps_eq_Em[I]
        omega[I] = self._get_omega(eps_eq_Em[I])
        return I

    def _get_omega(self, kappa_Em):
        r'''
        Return new value of damage parameter
        @param kappa_Em: maximum strain norm achieved so far 
        '''
        omega_Em = np.zeros_like(kappa_Em)
        epsilon_0 = self.epsilon_0
        epsilon_f = self.epsilon_f
        I = np.where(kappa_Em >= epsilon_0)
        omega_Em[I] = (
            1.0 - (epsilon_0 / kappa_Em[I] * np.exp(-1.0 *
                                                    (kappa_Em[I] - epsilon_0) /
                                                    (epsilon_f - epsilon_0))))
        return omega_Em

    def _get_domega(self, kappa_Em):
        '''
        Return new value of damage parameter derivative
        @param kappa_Em: maximum strain norm achieved so far
        '''
        epsilon_0 = self.epsilon_0
        epsilon_f = self.epsilon_f
        domega_Em = np.zeros_like(kappa_Em)
        I = np.where(kappa_Em >= epsilon_0)
        factor_1 = epsilon_0 / (kappa_Em[I] * kappa_Em[I])
        factor_2 = epsilon_0 / (kappa_Em[I] * (epsilon_f - epsilon_0))
        domega_Em[I] = ((factor_1 + factor_2) *
                        np.exp(-(kappa_Em[I] - epsilon_0) /
                               (epsilon_f - epsilon_0)))
        return domega_Em

    def _get_D_abcd_alg_reduction(self, kappa_Em, eps_Emab_n1):
        '''Calculate the stiffness term to be subtracted
        from the secant stiffness to get the algorithmic stiffness.
        '''
        domega_Em = self._get_domega(kappa_Em)
        deps_eq_Emcd = self.strain_norm.get_deps_eq(eps_Emab_n1)
        return np.einsum('...,...cd,abcd,...cd->...abcd', domega_Em,
                         deps_eq_Emcd, self.D_abef, eps_Emab_n1)

    traits_view = View(VSplit(
        Group(Item('E'), Item('nu'), Item('epsilon_0'), Item('epsilon_f'),
              Item('strain_norm')),
        Group(
            Item('stiffness', style='custom'),
            Spring(resizable=True),
            label='Configuration parameters',
            show_border=True,
        ),
    ),
                       resizable=True)

    tree_view = View(
        Group(Item('E', full_size=True, resizable=True), Item('nu'),
              Item('epsilon_0'), Item('epsilon_f'), Item('strain_norm')), )

    # Declare and fill-in the rte_dict - it is used by the clients to
    # assemble all the available time-steppers.
    #
    rte_dict = tr.Trait(tr.Dict)

    def _rte_dict_default(self):
        return {'sig_app': self.get_sig_app, 'omega': self.get_omega}
Esempio n. 20
0
class RespFunc(ResponseFunctionBase):

    listener_string = 'boundary.+modified,'\
        'approach.+modified,'\
        'material.+modified,'\
        'plot.+modified,'\
        'geometry.+modified,'\
        'boundary.type.+modified'

    def __init__(self, **kw):
        super(RespFunc, self).__init__(**kw)
        self.material.add_listeners = self.add_listeners
        self.material.remove_listeners = self.remove_listeners
        self.material.get_value = self.get_value
        self._boundary_changed()

    boundary = EitherType(
        names=['infinite length', 'finite length', 'clamped fibre end'],
        klasses=[InfiniteEmbeddedLength, FiniteEmbeddedLength, ClampedFibre])

    def _boundary_changed(self):
        self.remove_listeners()
        self.geometry = self.boundary.geometry
        self.plot = self.boundary.plot
        self.get_value()
        self.add_listeners()

    def update_parameters(self):
        self.remove_listeners()
        self.approach.material = self.material
        self.boundary.type.geometry = self.geometry
        self.boundary.type.plot = self.plot
        self.approach.geometry = self.geometry
        self.approach.plot = self.plot
        self.add_listeners()

    approach = EitherType(names=['stress criterion', 'energy criterion'],
                          klasses=[
                              StressCriterion,
                              EnergyCriterion,
                          ])

    geometry = Instance(Geometry)

    def _geometry_default(self):
        return Geometry()

    material = Instance(Material)

    def _material_default(self):
        return Material()

    plot = Instance(Plot)

    def _plot_default(self):
        return Plot()

    values = Tuple(Array, Array)

    def get_value(self):
        self.update_parameters()
        self.remove_listeners()
        if self.boundary.type.BC == 'double-sided pull-out with infinite embedded length':
            self.approach.clamp = False
            l = self.geometry.l
            self.geometry.l = 0.0
            u_plot = self.plot.u_plot
            self.plot.u_plot = self.plot.w_plot / 2.0
            self.approach.bool_infinite = True
            x, y = self.approach.get_value()
            self.approach.bool_infinite = False
            x *= 2.0
            self.values = (x, y)
            self.geometry.l = l
            self.plot.u_plot = u_plot
        elif self.boundary.type.BC == 'double-sided pull-out with finite embedded length':
            # todo: not complete
            self.approach.clamp = False
            l = self.geometry.l
            L = self.geometry.L
            self.geometry.l = 0.0
            u_plot = self.plot.u_plot
            self.geometry.L = self.boundary.type.Le
            self.approach.bool_finite = True
            x1, y1 = self.approach.get_value()
            self.geometry.L = self.boundary.geometry.Lf - self.boundary.type.Le
            x2, y2 = self.approach.get_value()
            self.values = self.approach.get_value()
            self.approach.bool_finite = False
            self.geometry.l = l
            self.geometry.L = L
        elif self.boundary.type.BC == 'double-sided pull-out with clamped fibre end':
            # todo: not complete
            self.approach.clamp = True
            self.approach.bool_clamp = True
            self.values = self.approach.get_value()
            self.approach.bool_clamp = False
        elif self.boundary.type.BC == 'one-sided pull-out with clamped fibre end':
            self.approach.clamp = True
            self.approach.bool_clamp = True
            self.approach.L = self.boundary.type.Le
            self.values = self.approach.get_value()
            self.approach.bool_clamp = False
        elif self.boundary.type.BC == 'one-sided pull-out with finite embedded length':
            self.approach.clamp = False
            self.approach.bool_finite = True
            self.values = self.approach.get_value()
            self.approach.bool_finite = False
        elif self.boundary.type.BC == 'one-sided pull-out with infinite embedded length':
            self.approach.clamp = False
            self.approach.bool_infinite = True
            self.values = self.approach.get_value()
            self.approach.bool_infinite = False
        else:
            # place holder
            self.values = self.approach.get_value()
        self.add_listeners()