Exemplo n.º 1
0
class SimCrackLoc( IBVModel ):
    '''Model assembling the components for studying the restrained crack localization.
    '''
    shape = Int( 1, desc = 'Number of finite elements',
                   ps_levsls = ( 10, 40, 4 ) )
    length = Float( 1, desc = 'Length of the simulated region' )

    #-------------------------------------------------------
    # Material model for the matrix
    #-------------------------------------------------------
    mats_m = Instance( MATS1DCrackLoc )
    def _mats_m_default( self ):
        E_m = 1
        mats_m = MATS1DCrackLoc( E = E_m,
                                 R = 0.5,
                                 epsilon_0 = 0.001,
                                 epsilon_f = 0.01 )
        return mats_m

    mats_f = Instance( MATS1DElastic )
    def _mats_f_default( self ):
        E_f = 0
        mats_f = MATS1DElastic( E = E_f )
        return mats_f

    mats_b = Instance( MATS1DElastic )
    def _mats_b_default( self ):
        E_b = 0
        mats_b = MATS1DElastic( E = E_b )
        return mats_b

    mats = Instance( MATS1D5Bond )
    def _mats_default( self ):

        # Material model construction
        mats = MATS1D5Bond( mats_phase1 = self.mats_m,
                            mats_phase2 = self.mats_f,
                            mats_ifslip = self.mats_b,
                            mats_ifopen = MATS1DElastic( E = 0 )   # elastic function of open - inactive
                            )
        return mats
    #-------------------------------------------------------
    # Finite element type
    #-------------------------------------------------------
    fets = Instance( FETSEval )
    def _fets_default( self ):
        #return FETS1D52L8ULRH( mats_eval = self.mats )        
        return FETS1D52L4ULRH( mats_eval = self.mats )
        #return FETS1D2L3U( mats_eval = self.mats ) 

    run = Button

    @on_trait_change( 'run' )
    def peval( self ):
        '''Evaluation procedure.
        '''
        #mv = MATS1DDamageView( model = mats_eval )
        #mv.configure_traits()

        self.mats_m.reset_state()
        # Discretization
        #
        length = self.length
        domain = FEGrid( coord_min = ( 0., length / 5. ),
                          coord_max = ( length, 0. ),
                          shape = ( self.shape, 1 ),
                          fets_eval = self.fets )

        right_dofs = domain[-1, -1, -1, :].dofs[0, :, 0]
        print 'concrete_dofs', id( domain ), domain[:, 0, :, 0].dofs
        # Response tracers
        self.stress_strain = RTraceGraph( name = 'Fi,right over u_right (iteration)' ,
                                   var_y = 'F_int', idx_y = right_dofs[0],
                                   var_x = 'U_k', idx_x = right_dofs[0] )
        self.eps_m_field = RTraceDomainListField( name = 'eps_m' , position = 'int_pnts',
                                           var = 'eps1', idx = 0,
                                           warp = True )

        self.eps_f_field = RTraceDomainListField( name = 'eps_f' , position = 'int_pnts',
                                           var = 'eps2', idx = 0,
                                           warp = True )

        # Response tracers
        self.sig_m_field = RTraceDomainListField( name = 'sig_m' , position = 'int_pnts',
                                              var = 'mats_phase1_sig_app', idx = 0 )
        self.sig_f_field = RTraceDomainListField( name = 'sig_f' , position = 'int_pnts',
                                              var = 'mats_phase2_sig_app', idx = 0 )
        self.omega_m_field = RTraceDomainListField( name = 'omega_m' , position = 'int_pnts',
                                           var = 'mats_phase1_omega', idx = 0,
                                           warp = True )
        # 

        damage_onset_displ = self.mats_m.epsilon_0 * self.length
        go_behind = 1.5
        finish_displ = go_behind * damage_onset_displ
        n_steps = 20
        step_size = ( finish_displ - damage_onset_displ ) / n_steps
        tmax = 1 + n_steps

        def ls( t ):
            if t <= 1:
                return t
            else:
                return 1.0 + ( t - 1.0 ) / n_steps * ( go_behind - 1 )

        ts = TSCrackLoc( 
                 dof_resultants = True,
                 on_update = self.plot,
                 sdomain = domain,
                 bcond_list = [# define the left clamping 
                                BCSlice( var = 'u', value = 0., dims = [0], slice = domain[ 0, 0, 0, :] ),
                                # loading at the right edge
                                 BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0],
                                         time_function = ls ),
#                                 BCSlice(var='u', value = finish_displ, dims = [0], slice = domain[-1,-1,-1, 0],
#                                         time_function = ls ),
                                # fix horizontal displacement in the top layer
                                 BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ),
                                # fix the vertical displacement all over the domain
                                 BCSlice( var = 'u', value = 0., dims = [1], slice = domain[ :, :, :, :] )
                                ],
                 rtrace_list = [ self.stress_strain,
                                  self.eps_m_field,
                                  self.eps_f_field,
                                  self.sig_m_field,
                                  self.sig_f_field,
                                  self.omega_m_field ]
                )

        # Add the time-loop control
        tloop = TLoop( tstepper = ts, KMAX = 200, debug = True, tolerance = 1e-5,
                       tline = TLine( min = 0.0, step = 1.0, max = 1.0 ) )

        print ts.rte_dict.keys()
        U = tloop.eval()

        self.plot()

        return array( [ U[right_dofs[-1]] ], dtype = 'float_' )

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_ld = Instance( Figure )
    def _figure_ld_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_eps = Instance( Figure )
    def _figure_eps_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_omega = Instance( Figure )
    def _figure_omega_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_sig = Instance( Figure )
    def _figure_sig_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    def plot( self ):
        self.stress_strain.refresh()
        t = self.stress_strain.trace
        ax = self.figure_ld.axes[0]
        ax.clear()
        ax.plot( t.xdata, t.ydata, linewidth = 2, color = 'blue' )

        ax = self.figure_eps.axes[0]
        ax.clear()

        ef = self.eps_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' )

        ef = self.eps_f_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' )
        ax.legend( ['eps_m', 'eps_f'] )

        ax = self.figure_sig.axes[0]
        ax.clear()

        ef = self.sig_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' )

        ef = self.sig_f_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' )
        ax.legend( ['sig_m', 'sig_f'] )


        ax = self.figure_omega.axes[0]
        ax.clear()

        ef = self.omega_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'brown' )
        ax.legend( ['omega_m'] )


        self.data_changed = True

    def get_sim_outputs( self ):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [ SimOut( name = 'right end displacement', unit = 'm' ) ]

    data_changed = Event

    toolbar = ToolBar( 
                      Action( name = "Run",
                             tooltip = 'Start computation',
                             image = ImageResource( 'kt-start' ),
                             action = "start_study" ),
                      Action( name = "Pause",
                             tooltip = 'Pause computation',
                             image = ImageResource( 'kt-pause' ),
                             action = "pause_study" ),
                      Action( name = "Stop",
                             tooltip = 'Stop computation',
                             image = ImageResource( 'kt-stop' ),
                             action = "stop_study" ),
                      image_size = ( 32, 32 ),
                      show_tool_names = False,
                      show_divider = True,
                      name = 'view_toolbar' ),

    traits_view = View( 
                    HSplit( 
                        VSplit( 
                                Item( 'run', show_label = False ),
                            VGroup( 
                                 Item( 'shape' ),
                                 Item( 'n_sjteps' ),
                                 Item( 'length' ),
                                 label = 'parameters',
                                 id = 'crackloc.viewmodel.factor.geometry',
                                 dock = 'tab',
                                 scrollable = True,
                                 ),
                            VGroup( 
                                 Item( 'mats_m@', show_label = False ),
                                 label = 'Matrix',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.matrix',
                                 scrollable = True
                                 ),
                            VGroup( 
                                 Item( 'mats_f@', show_label = False ),
                                 label = 'Fiber',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.fiber',
                                 scrollable = True
                                 ),
                            VGroup( 
                                 Item( 'mats_b@', show_label = False ),
                                 label = 'Bond',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.bond',
                                 scrollable = True
                                ),
                            id = 'crackloc.viewmodel.left',
                            label = 'studied factors',
                            layout = 'tabbed',
                            dock = 'tab',
                            ),
                               VSplit( 
                                    VGroup( 
                                        Item( 'figure_ld', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'stress-strain',
                                            id = 'crackloc.viewmode.figure_ld_window',
                                            dock = 'tab',
                                    ),
                                    VGroup( 
                                        Item( 'figure_eps', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'strains profile',
                                            id = 'crackloc.viewmode.figure_eps_window',
                                            dock = 'tab',
                                        ),
                                    VGroup( 
                                        Item( 'figure_sig', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'stress profile',
                                            id = 'crackloc.viewmode.figure_sig_window',
                                            dock = 'tab',
                                        ),
                                    VGroup( 
                                        Item( 'figure_omega', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'omega profile',
                                            id = 'crackloc.viewmode.figure_omega_window',
                                            dock = 'tab',
                                        ),
                                   id = 'crackloc.viewmodel.right',
                                 ),
                            id = 'crackloc.viewmodel.splitter',
                        ),
                        title = 'SimVisage Component: Crack localization',
                        id = 'crackloc.viewmodel',
                        dock = 'tab',
                        resizable = True,
                        height = 0.8, width = 0.8,
                        buttons = [OKButton] )
Exemplo n.º 2
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')
        ]
Exemplo n.º 3
0
class SimCrackLoc( IBVModel ):
    '''Model assembling the components for studying the restrained crack localization.
    '''
    shape = Int( 1, desc = 'Number of finite elements',
                   ps_levsls = ( 10, 40, 4 ) )
    length = Float( 1, desc = 'Length of the simulated region' )

    #-------------------------------------------------------
    # Material model for the matrix
    #-------------------------------------------------------
    mats_m = Instance( MATS1DCrackLoc )
    def _mats_m_default( self ):
        E_m = 1
        mats_m = MATS1DCrackLoc( E = E_m,
                                 R = 0.5,
                                 epsilon_0 = 0.001,
                                 epsilon_f = 0.01 )
        return mats_m

    mats_f = Instance( MATS1DElastic )
    def _mats_f_default( self ):
        E_f = 0
        mats_f = MATS1DElastic( E = E_f )
        return mats_f

    mats_b = Instance( MATS1DElastic )
    def _mats_b_default( self ):
        E_b = 0
        mats_b = MATS1DElastic( E = E_b )
        return mats_b

    mats = Instance( MATS1D5Bond )
    def _mats_default( self ):

        # Material model construction
        mats = MATS1D5Bond( mats_phase1 = self.mats_m,
                            mats_phase2 = self.mats_f,
                            mats_ifslip = self.mats_b,
                            mats_ifopen = MATS1DElastic( E = 0 )   # elastic function of open - inactive
                            )
        return mats
    #-------------------------------------------------------
    # Finite element type
    #-------------------------------------------------------
    fets = Instance( FETSEval )
    def _fets_default( self ):
        #return FETS1D52L8ULRH( mats_eval = self.mats )        
        return FETS1D52L4ULRH( mats_eval = self.mats )
        #return FETS1D2L3U( mats_eval = self.mats ) 

    run = Button

    @on_trait_change( 'run' )
    def peval( self ):
        '''Evaluation procedure.
        '''
        #mv = MATS1DDamageView( model = mats_eval )
        #mv.configure_traits()

        self.mats_m.reset_state()
        # Discretization
        #
        length = self.length
        domain = FEGrid( coord_min = ( 0., length / 5. ),
                          coord_max = ( length, 0. ),
                          shape = ( self.shape, 1 ),
                          fets_eval = self.fets )

        right_dofs = domain[-1, -1, -1, :].dofs[0, :, 0]
        print 'concrete_dofs', id( domain ), domain[:, 0, :, 0].dofs
        # Response tracers
        self.stress_strain = RTraceGraph( name = 'Fi,right over u_right (iteration)' ,
                                   var_y = 'F_int', idx_y = right_dofs[0],
                                   var_x = 'U_k', idx_x = right_dofs[0] )
        self.eps_m_field = RTraceDomainListField( name = 'eps_m' , position = 'int_pnts',
                                           var = 'eps1', idx = 0,
                                           warp = True )

        self.eps_f_field = RTraceDomainListField( name = 'eps_f' , position = 'int_pnts',
                                           var = 'eps2', idx = 0,
                                           warp = True )

        # Response tracers
        self.sig_m_field = RTraceDomainListField( name = 'sig_m' , position = 'int_pnts',
                                              var = 'mats_phase1_sig_app', idx = 0 )
        self.sig_f_field = RTraceDomainListField( name = 'sig_f' , position = 'int_pnts',
                                              var = 'mats_phase2_sig_app', idx = 0 )
        self.omega_m_field = RTraceDomainListField( name = 'omega_m' , position = 'int_pnts',
                                           var = 'mats_phase1_omega', idx = 0,
                                           warp = True )
        # 

        damage_onset_displ = self.mats_m.epsilon_0 * self.length
        go_behind = 1.5
        finish_displ = go_behind * damage_onset_displ
        n_steps = 20
        step_size = ( finish_displ - damage_onset_displ ) / n_steps
        tmax = 1 + n_steps

        def ls( t ):
            if t <= 1:
                return t
            else:
                return 1.0 + ( t - 1.0 ) / n_steps * ( go_behind - 1 )

        ts = TSCrackLoc( 
                 dof_resultants = True,
                 on_update = self.plot,
                 sdomain = domain,
                 bcond_list = [# define the left clamping 
                                BCSlice( var = 'u', value = 0., dims = [0], slice = domain[ 0, 0, 0, :] ),
                                # loading at the right edge
                                 BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0],
                                         time_function = ls ),
#                                 BCSlice(var='u', value = finish_displ, dims = [0], slice = domain[-1,-1,-1, 0],
#                                         time_function = ls ),
                                # fix horizontal displacement in the top layer
                                 BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ),
                                # fix the vertical displacement all over the domain
                                 BCSlice( var = 'u', value = 0., dims = [1], slice = domain[ :, :, :, :] )
                                ],
                 rtrace_list = [ self.stress_strain,
                                  self.eps_m_field,
                                  self.eps_f_field,
                                  self.sig_m_field,
                                  self.sig_f_field,
                                  self.omega_m_field ]
                )

        # Add the time-loop control
        tloop = TLoop( tstepper = ts, KMAX = 200, debug = True, tolerance = 1e-5,
                       tline = TLine( min = 0.0, step = 1.0, max = 1.0 ) )

        print ts.rte_dict.keys()
        U = tloop.eval()

        self.plot()

        return array( [ U[right_dofs[-1]] ], dtype = 'float_' )

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_ld = Instance( Figure )
    def _figure_ld_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_eps = Instance( Figure )
    def _figure_eps_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_omega = Instance( Figure )
    def _figure_omega_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_sig = Instance( Figure )
    def _figure_sig_default( self ):
        figure = Figure( facecolor = 'white' )
        figure.add_axes( [0.12, 0.13, 0.85, 0.74] )
        return figure

    def plot( self ):
        self.stress_strain.refresh()
        t = self.stress_strain.trace
        ax = self.figure_ld.axes[0]
        ax.clear()
        ax.plot( t.xdata, t.ydata, linewidth = 2, color = 'blue' )

        ax = self.figure_eps.axes[0]
        ax.clear()

        ef = self.eps_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' )

        ef = self.eps_f_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' )
        ax.legend( ['eps_m', 'eps_f'] )

        ax = self.figure_sig.axes[0]
        ax.clear()

        ef = self.sig_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'grey' )

        ef = self.sig_f_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'red' )
        ax.legend( ['sig_m', 'sig_f'] )


        ax = self.figure_omega.axes[0]
        ax.clear()

        ef = self.omega_m_field.subfields[0]
        xdata = ef.vtk_X[:, 0]
        ydata = ef.field_arr[:, 0]
        idata = argsort( xdata )
        ax.plot( xdata[idata], ydata[idata], linewidth = 2, color = 'brown' )
        ax.legend( ['omega_m'] )


        self.data_changed = True

    def get_sim_outputs( self ):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [ SimOut( name = 'right end displacement', unit = 'm' ) ]

    data_changed = Event

    toolbar = ToolBar( 
                      Action( name = "Run",
                             tooltip = 'Start computation',
                             image = ImageResource( 'kt-start' ),
                             action = "start_study" ),
                      Action( name = "Pause",
                             tooltip = 'Pause computation',
                             image = ImageResource( 'kt-pause' ),
                             action = "pause_study" ),
                      Action( name = "Stop",
                             tooltip = 'Stop computation',
                             image = ImageResource( 'kt-stop' ),
                             action = "stop_study" ),
                      image_size = ( 32, 32 ),
                      show_tool_names = False,
                      show_divider = True,
                      name = 'view_toolbar' ),

    traits_view = View( 
                    HSplit( 
                        VSplit( 
                                Item( 'run', show_label = False ),
                            VGroup( 
                                 Item( 'shape' ),
                                 Item( 'n_sjteps' ),
                                 Item( 'length' ),
                                 label = 'parameters',
                                 id = 'crackloc.viewmodel.factor.geometry',
                                 dock = 'tab',
                                 scrollable = True,
                                 ),
                            VGroup( 
                                 Item( 'mats_m@', show_label = False ),
                                 label = 'Matrix',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.matrix',
                                 scrollable = True
                                 ),
                            VGroup( 
                                 Item( 'mats_f@', show_label = False ),
                                 label = 'Fiber',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.fiber',
                                 scrollable = True
                                 ),
                            VGroup( 
                                 Item( 'mats_b@', show_label = False ),
                                 label = 'Bond',
                                 dock = 'tab',
                                 id = 'crackloc.viewmodel.factor.bond',
                                 scrollable = True
                                ),
                            id = 'crackloc.viewmodel.left',
                            label = 'studied factors',
                            layout = 'tabbed',
                            dock = 'tab',
                            ),
                               VSplit( 
                                    VGroup( 
                                        Item( 'figure_ld', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'stress-strain',
                                            id = 'crackloc.viewmode.figure_ld_window',
                                            dock = 'tab',
                                    ),
                                    VGroup( 
                                        Item( 'figure_eps', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'strains profile',
                                            id = 'crackloc.viewmode.figure_eps_window',
                                            dock = 'tab',
                                        ),
                                    VGroup( 
                                        Item( 'figure_sig', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'stress profile',
                                            id = 'crackloc.viewmode.figure_sig_window',
                                            dock = 'tab',
                                        ),
                                    VGroup( 
                                        Item( 'figure_omega', editor = MPLFigureEditor(),
                                             resizable = True, show_label = False ),
                                             label = 'omega profile',
                                            id = 'crackloc.viewmode.figure_omega_window',
                                            dock = 'tab',
                                        ),
                                   id = 'crackloc.viewmodel.right',
                                 ),
                            id = 'crackloc.viewmodel.splitter',
                        ),
                        title = 'SimVisage Component: Crack localization',
                        id = 'crackloc.viewmodel',
                        dock = 'tab',
                        resizable = True,
                        height = 0.8, width = 0.8,
                        buttons = [OKButton] )
Exemplo n.º 4
0
class SimBT3PT(IBVModel):
    '''Simulation: Bending Test Three Point
    '''

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

    implements(ISimModel)

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

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


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

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

    # support discretization in xy-direction:
    # NOTE: chose '2' for 2x2-grid or '4' for 4x4-grid
    #
    shape_supprt_x = Int(2, input=True,
                      ps_levels=(2, 4, 2))

    #-----------------
    # geometry:
    #-----------------
    #
    # edge length of the bending specimen (beam) (entire length without symmetry)
    length = Float(1.15, input=True)
    elstmr_length = Float(0.05, input=True)
    elstmr_thickness = Float(0.005, input=True,
                                enter_set=True, auto_set=False)
    width = Float(0.20, input=True)
    thickness = Float(0.06, input=True,
                      ps_levels=(0.054, 0.060, 0.066))

    # thickness of the tappered support
    #
    thickness_supprt = Float(0.02, 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.

    # 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.

    #-----------------
    # specify the refinement of the idealization
    #-----------------

    # specify weather elastomer is to be modeled for load introduction
    #
    elstmr_flag = True

    # specify weather steel support is to be modeled
    #
    supprt_flag = False

    #-----------------
    # 'geo_transform'
    #-----------------

    # geometry transformation for four sided tappered support with reduced stiffness towards the edges (if modeled)
    #
    geo_supprt = Property(Instance(GeoSUPPRT), depends_on='+ps_levels, +input')
    @cached_property
    def _get_geo_supprt(self):
        # element length within the range of the slab without the area of the
        # load introduction plate
        #
        elem_size = self.sym_specmn_length / self.shape_x
        width_supprt = self.shape_supprt_x * elem_size
        print 'width_supprt = ', width_supprt
        return GeoSUPPRT(thickness_supprt=self.thickness_supprt,
                         width_supprt=width_supprt,
                         xyoffset=0.,
                         zoffset= -self.thickness_supprt)

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

    # age of the specimen at the time of testing
    # determines the E-modulus and nu based on the time dependent function stored
    # in 'CCSUniteCell' if params are not explicitly set
    #
    age = Int(28, input=True)

    # composite E-modulus / Poisson's ratio
    # NOTE 1: value are retrieved from the database
    #         same values are used for calibration (as taken from tensile test) and for slab test
    # NOTE 2: alternatively the same phi-function could be used independent of age. This would assume
    #         an afine/proportional damage evolution for different ages, i.e. a different E would be
    #         used in the simulation of the slab test and within the calibration procedure.

    # 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(None, np.inf)

    # number of microplanes
    #
    n_mp = Int(30., auto_set=False, enter_set=True, input=True)

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

    # @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,  # relevant for compressive behavior/used for calibration of phi_fn
                                nu=self.nu,
                                # corresponding to settings in "MatsCalib"
                                n_mp=30,
                                symmetrization='sum-type',
                                model_version='compliance',
                                phi_fn=self.phi_fn)

    E_elstmr = Float(3000., input=True)

    elstmr_mats = Property(Instance(MATS3DElastic),
                                   depends_on='input_change')
    @cached_property
    def _get_elstmr_mats(self):
        E_elstmr = self.E_elstmr
        print 'effective elastomer E_modulus', E_elstmr
        return MATS3DElastic(E=E_elstmr,
                             nu=0.4)

    # E-modulus and nu of steel support
    E_s = Float(210000., auto_set=False, enter_set=True, input=True)
    nu_s = Float(0.20, auto_set=False, enter_set=True, input=True)

    supprt_mats = Property(Instance(MATS3DElastic),
                                    depends_on='input_change')
    @cached_property
    def _get_supprt_mats(self):
        return MATS3DElastic(E=self.E_s,
                             nu=self.nu_s)

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

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

    # use quadratic serendipity elements
    # NOTE: 2D5 elements behave linear elastic in out of plane direction!
    #
    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

    supprt_fets = Property(Instance(FETSEval),
                           depends_on='input_change')
    @cached_property
    def _get_supprt_fets(self):
        # linear-elastic behavior quadratic serendipity elements
        fets = FETS3D8H20U(mats_eval=self.supprt_mats)
        fets.vtk_r *= self.vtk_r
        return fets

    #-----------------
    # fe_grid:
    #-----------------

    fe_domain = Property(depends_on='+ps_levels, +input')
    @cached_property
    def _get_fe_domain(self):
        return FEDomain()

    mid_specmn_fe_level = Property(depends_on='+ps_levels, +input')
    @cached_property
    def _get_mid_specmn_fe_level(self):
        return  FERefinementGrid(name='middle specimen patch',
                                 fets_eval=self.specmn_fets,
                                 domain=self.fe_domain)

    mid_specmn_fe_grid = Property(Instance(FEGrid), depends_on='+ps_levels, +input')
    @cached_property
    def _get_mid_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_elstmr_length,
                                      self.width / 2,
                                      self.thickness),
                         shape=(self.mid_shape_x, self.shape_y, self.shape_z),
                         level=self.mid_specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

    specmn_fe_level = Property(depends_on='+ps_levels, +input')
    @cached_property
    def _get_specmn_fe_level(self):
        return  FERefinementGrid(name='specimen patch',
                                 fets_eval=self.specmn_fets,
                                 domain=self.fe_domain)

    specmn_fe_grid = Property(Instance(FEGrid), depends_on='+ps_levels, +input')
    @cached_property
    def _get_specmn_fe_grid(self):
        # only a quarter of the beam is simulated due to symmetry:
        fe_grid = FEGrid(coord_min=(self.sym_elstmr_length,
                                      0.,
                                      0.),
                         coord_max=(self.sym_specmn_length,
                                      self.sym_width,
                                      self.thickness),
                         shape=(self.shape_x, self.shape_y, self.shape_z),
                         level=self.specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

#    if elstmr_flag:
    elstmr_fe_level = Property(depends_on='+ps_levels, +input')
    @cached_property
    def _get_elstmr_fe_level(self):
        return  FERefinementGrid(name='elastomer patch',
                                 fets_eval=self.elstmr_fets,
                                 domain=self.fe_domain)

    elstmr_fe_grid = Property(Instance(FEGrid), depends_on='+ps_levels, +input')
    @cached_property
    def _get_elstmr_fe_grid(self):
        x_max = self.sym_elstmr_length
        y_max = self.width / 2.
        z_max = self.thickness + self.elstmr_thickness
        fe_grid = FEGrid(coord_min=(0, 0, self.thickness),
                         coord_max=(x_max, y_max, z_max),
                         level=self.elstmr_fe_level,
                         shape=(self.mid_shape_x, self.shape_y, 1),
                         fets_eval=self.elstmr_fets)
        return fe_grid

    if supprt_flag:
        supprt_fe_level = Property(depends_on='+ps_levels, +input')
        @cached_property
        def _get_supprt_fe_level(self):
            return  FERefinementGrid(name='elastomer patch',
                                     fets_eval=self.supprt_fets,
                                     domain=self.fe_domain)

        supprt_fe_grid = Property(Instance(FEGrid), depends_on='+ps_levels, +input')
        @cached_property
        def _get_supprt_fe_grid(self):
            return FEGrid(coord_min=(0, 0, 0),
                          coord_max=(1, 1, 1),
                          level=self.supprt_fe_level,
                          # use shape (2,2) in order to place support in the center of the steel support
                          # corresponding to 4 elements of the slab mesh
                          #
                          shape=(self.shape_supprt_x, self.shape_supprt_x, 1),
                          geo_transform=self.geo_supprt,
                          fets_eval=self.supprt_fets)

    #===========================================================================
    # Boundary conditions
    #===========================================================================

    # w_max = center displacement:
    #
    w_max = Float(-0.010, input=True)  # [m]

    bc_list = Property(depends_on='+ps_levels, +input')
    @cached_property
    def _get_bc_list(self):
        specmn = self.specmn_fe_grid
        mid_specmn = self.mid_specmn_fe_grid
        if self.elstmr_flag:
            elstmr = self.elstmr_fe_grid

        #--------------------------------------------------------------
        # boundary conditions for the symmetry
        #--------------------------------------------------------------
        # the x-axis corresponds to the axis of symmetry along the longitudinal axis of the beam:
        bc_symplane_xz = BCSlice(var='u', value=0., dims=[1],
                                 slice=specmn[:, 0, :, :, 0, :])

        bc_mid_symplane_xz = BCSlice(var='u', value=0., dims=[1],
                                 slice=mid_specmn[:, 0, :, :, 0, :])

        bc_mid_symplane_yz = BCSlice(var='u', value=0., dims=[0],
                                 slice=mid_specmn[0, :, :, 0, :, :])

        if self.elstmr_flag:
            bc_el_symplane_xz = BCSlice(var='u', value=0., dims=[1],
                                        slice=elstmr[:, 0, :, :, 0, :])
            bc_el_symplane_yz = BCSlice(var='u', value=0., dims=[0],
                                        slice=elstmr[0, :, :, 0, :, :])

        #--------------------------------------------------------------
        # boundary conditions for the support
        #--------------------------------------------------------------
        bc_support_0y0 = BCSlice(var='u', value=0., dims=[2],
                                 slice=specmn[-1, :, 0, -1, :, 0])

        #--------------------------------------------------------------
        # link domains
        #--------------------------------------------------------------
        link_msp_sp = BCDofGroup(var='u', value=0., dims=[0, 1, 2],
                                 get_dof_method=mid_specmn.get_right_dofs,
                                 get_link_dof_method=specmn.get_left_dofs,
                                 link_coeffs=[1.])

#        link_msp_sp_xyz = BCSlice(var = 'u', value = 0., dims = [0, 1, 2],
#                             slice = specmn[0, :, :, 0, :, :],
#                             link_slice = mid_specmn[-1 :, :, -1, :, :],
#                             link_dims = [0, 1, 2],
#                             link_coeffs = [1.])

#        link_msp_sp_y = BCSlice(var = 'u', value = 0., dims = [1],
#                             slice = specmn[0, :, :, 0, :, :],
#                             link_slice = mid_specmn[-1 :, :, -1, :, :],
#                             link_dims = [1],
#                             link_coeffs = [1.])
#
#        link_msp_sp_z = BCSlice(var = 'u', value = 0., dims = [2],
#                             slice = specmn[0, :, :, 0, :, :],
#                             link_slice = mid_specmn[-1 :, :, -1, :, :],
#                             link_dims = [2],
#                             link_coeffs = [1.])

#        link_msp_sp = [ link_msp_sp_xyz ]

        if self.elstmr_flag:
            link_el_sp = BCDofGroup(var='u', value=0., dims=[2],
                                    get_dof_method=elstmr.get_back_dofs,
                                    get_link_dof_method=mid_specmn.get_front_dofs,
                                    link_coeffs=[1.])

        #--------------------------------------------------------------
        # loading
        #--------------------------------------------------------------
        w_max = self.w_max
#        f_max = -0.010 / 0.10 # [MN/m]

        if self.elstmr_flag:
            # apply displacement at all top node (surface load)
            #
            bc_w = BCSlice(var='u', value=w_max, dims=[2],
                           slice=elstmr[:, :, -1, :, :, -1])
            # apply a single force at the center of the beam (system origin at top of the elastomer
            # and us elastomer-domain as load distribution plate with a high stiffness (e.g. steel)
#            F_max = -0.010 #[MN]
#            bc_F = BCSlice(var = 'f', value = F_max, dims = [2],
#                           slice = elstmr[0, 0, -1, 0, 0, -1])
        else:
            # center top nodes (line load)
            #
            bc_w = BCSlice(var='u', value=w_max, dims=[2],
                            slice=mid_specmn[0, :, -1, 0, :, -1])
            # NOTE: the entire symmetry axis (yz)-plane is moved downwards
            # in order to avoid large indentations at the top nodes
            #
#          bc_center_w = BCSlice( var = 'w', value = w_max, dims = [2], slice = mid_specmn[0, :, :, 0, :, :] )

        bc_list = [bc_symplane_xz, bc_mid_symplane_xz, bc_mid_symplane_yz,
                   bc_support_0y0, link_msp_sp, bc_w ]

        if self.elstmr_flag:
            bc_list_elstmr = [ link_el_sp, bc_el_symplane_xz, bc_el_symplane_yz ]
            bc_list += bc_list_elstmr

        return bc_list

    tloop = Property(depends_on='input_change')
    @cached_property
    def _get_tloop(self):

        #--------------------------------------------------------------
        # ts
        #--------------------------------------------------------------

        specmn = self.specmn_fe_grid
        mid_specmn = self.mid_specmn_fe_grid

        if self.supprt_flag:
            supprt = self.supprt_fe_grid
            supprt_dofs_z = np.unique(supprt[self.shape_supprt_x / 2, self.shape_y / 2, 0, 0, 0, 0].dofs[:, :, 2].flatten())
        else:
            supprt_dofs_z = np.unique(specmn[-1, :, 0, -1, :, 0].dofs[:, :, 2].flatten())
        print 'supprt_dofs_z (unique)', supprt_dofs_z

        if self.elstmr_flag:
            elstmr = self.elstmr_fe_grid
            load_dofs_z = np.unique(elstmr[:, :, -1, :, :, -1].dofs[:, :, 2].flatten())
        else:
            # center_top_line_dofs
            #
            load_dofs_z = np.unique(mid_specmn[0, :, -1, 0, :, -1].dofs[:, :, 2].flatten())
        print 'load_dofs_z used for integration of force: ', load_dofs_z

        # center top z-dof
        #
        center_top_dof_z = mid_specmn[0, 0, 0, 0, 0, 0].dofs[0, 0, 2]
        print 'center_top_dof used for displacement tracing: ', center_top_dof_z

        # force-displacement-diagram (LOAD)
        # (surface load on the elstmr or line load at specimen center)
        #
        self.f_w_diagram_center = RTraceGraph(name='displacement (center) - reaction 2',
                                       var_x='U_k'  , idx_x=center_top_dof_z,
                                       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 (SUPPORT)
        # (dofs at support line of the specmn used to integrate the force)
        #
        self.f_w_diagram_supprt = RTraceGraph(name='displacement (center) - reaction 2',
                                       var_x='U_k'  , idx_x=center_top_dof_z,
                                       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')

        ts = TS(
                sdomain=self.fe_domain,
                bcond_list=self.bc_list,
                rtrace_list=[
                             self.f_w_diagram_center,
                             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)
                      )

        return tloop

    #--------------------------------------------------------------
    # prepare pstudy
    #--------------------------------------------------------------

    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') ]
Exemplo n.º 5
0
           RESETMAX = 0, 
           tolerance = 0.01, # 5e-4, 
           debug = False,
           tline  = TLine( min = 0.0,  step = 0.02, max = 1.0 ) )                   

    from pickle import dump, load

    do = 'show_last_result'
#    do = 'eval'
    
    if do == 'eval':
        print 'dof_number', upper_left_corner
        U = tloop.eval()
        #print 'U', U[ upper_left_corner ]
    
        f_w_diagram.refresh()
        file = open( 'f_w_diagram.pickle', 'w' )
        dump( f_w_diagram.trace, file )
        file.close()

    if do == 'show_last_result':
        from promod.exdb.ex_run import ExRun
        import pylab as p

#        f_w_diagram.trace.mpl_plot( p, color = 'red' )

        file = open( 'f_w_diagram.pickle', 'r' )
        trace = load( file )
        p.plot( trace.xdata, trace.ydata, color = 'blue' )

        file = open( 'f_w_diagram_TT11-10a.pickle', 'r' )
Exemplo n.º 6
0
    def eval( self ):

        elem_length = self.length / float( self.shape )
        flaw_radius = self.flaw_radius

        mats = MATS1DElasticWithFlaw( E = 10.,
                                     flaw_position = self.flaw_position,
                                     flaw_radius = flaw_radius,
                                     reduction_factor = self.reduction_factor )

        #fets_eval = FETS1D2L( mats_eval = mats )
        fets_eval = FETS1D2L3U( mats_eval = mats )

        domain = FEGrid( coord_max = ( self.length, 0., 0. ),
                               shape = ( self.shape, ),
                               fets_eval = fets_eval )

        avg_processor = RTNonlocalAvg( avg_fn = QuarticAF( radius = self.avg_radius,
                                                           correction = True ) )

        eps_app = RTraceDomainListField( name = 'Strain' ,
                                         position = 'int_pnts',
                                         var = 'eps_app',
                                         warp = False )

        damage = RTraceDomainListField( name = 'Damage' ,
                                        position = 'int_pnts',
                                      var = 'omega',
                                        warp = False )

        disp = RTraceDomainListField( name = 'Displacement' ,
                                      position = 'int_pnts',
                                      var = 'u',
                                      warp = False )

        sig_app = RTraceDomainListField( name = 'Stress' ,
                                         position = 'int_pnts',
                                         var = 'sig_app' )

        right_dof = domain[-1, -1].dofs[0, 0, 0]
        rt_fu = RTraceGraph( name = 'Fi,right over u_right (iteration)' ,
                             var_y = 'F_int', idx_y = right_dof,
                             var_x = 'U_k', idx_x = right_dof )

        ts = TS( u_processor = avg_processor,
                 dof_resultants = True,
                 sdomain = domain,
             # conversion to list (square brackets) is only necessary for slicing of 
             # single dofs, e.g "get_left_dofs()[0,1]"
    #         bcond_list =  [ BCDof(var='u', dof = 0, value = 0.)     ] +  
    #                    [ BCDof(var='u', dof = 2, value = 0.001 ) ]+
    #                    [ )     ],
             bcond_list = [BCDof( var = 'u', dof = 0, value = 0. ),
    #                        BCDof(var='u', dof = 1, link_dofs = [2], link_coeffs = [0.5],
    #                              value = 0. ),
    #                        BCDof(var='u', dof = 2, link_dofs = [3], link_coeffs = [1.],
    #                              value = 0. ),
                            BCDof( var = 'u', dof = right_dof, value = 0.01,
                                       ) ],
             rtrace_list = [ rt_fu,
                             eps_app,
                             # damage,
                             sig_app,
                             disp,
                    ]
                )

        # Add the time-loop control
        tloop = TLoop( tstepper = ts, KMAX = 100, tolerance = 1e-5,
                       verbose_iteration = False,
                       tline = TLine( min = 0.0, step = 1.0, max = 1.0 ) )

        U = tloop.eval()

        p.subplot( 221 )
        rt_fu.refresh()
        rt_fu.trace.plot( p )

        eps = eps_app.subfields[0]
        xdata = eps.vtk_X[:, 0]
        ydata = eps.field_arr[:, 0, 0]
        idata = argsort( xdata )

        p.subplot( 222 )
        p.plot( xdata[idata], ydata[idata], 'o-' )

        disp = disp.subfields[0]
        xdata = disp.vtk_X[:, 0]
        ydata = disp.field_arr[:, 0]
        idata = argsort( xdata )

        p.subplot( 223 )
        p.plot( xdata[idata], ydata[idata], 'o-' )

        sig = sig_app.subfields[0]
        xdata = sig.vtk_X[:, 0]
        ydata = sig.field_arr[:, 0, 0]
        idata = argsort( xdata )

        p.subplot( 224 )
        p.plot( xdata[idata], ydata[idata], 'o-' )
Exemplo n.º 7
0
class SimCrackLoc(IBVModel):
    '''Model assembling the components for studying the restrained crack localization.
    '''

    geo_transform = Instance(FlawCenteredGeoTransform)

    def _geo_transform_default(self):
        return FlawCenteredGeoTransform()

    shape = Int(10,
                desc='Number of finite elements',
                ps_levsls=(10, 40, 4),
                input=True)

    length = Float(1000,
                   desc='Length of the simulated region',
                   unit='mm',
                   input=True)

    flaw_position = Float(500, input=True, unit='mm')

    flaw_radius = Float(100, input=True, unit='mm')

    reduction_factor = Float(0.9, input=True)

    elastic_fraction = Float(0.9, input=True)

    avg_radius = Float(400, input=True, unit='mm')

    # tensile strength of concrete
    f_m_t = Float(3.0, input=True, unit='MPa')

    epsilon_0 = Property(unit='-')

    def _get_epsilon_0(self):
        return self.f_m_t / self.E_m

    epsilon_f = Float(10, input=True, unit='-')

    h_m = Float(10, input=True, unit='mm')

    b_m = Float(8, input=True, unit='mm')

    A_m = Property(unit='m^2')

    def _get_A_m(self):
        return self.b_m * self.h_m

    E_m = Float(30.0e5, input=True, unit='MPa')

    E_f = Float(70.0e6, input=True, unit='MPa')

    A_f = Float(1.0, input=True, unit='mm^2')

    s_crit = Float(0.009, input=True, unit='mm')

    P_f = Property(depends_on='+input')

    @cached_property
    def _get_P_f(self):
        return sqrt(4 * self.A_f * pi)

    K_b = Property(depends_on='+input')

    @cached_property
    def _get_K_b(self):
        return self.T_max / self.s_crit

    tau_max = Float(0.0, input=True, unit='MPa')

    T_max = Property(depends_on='+input', unit='N/mm')

    @cached_property
    def _get_T_max(self):
        return self.tau_max * self.P_f

    rho = Property(depends_on='+input')

    @cached_property
    def _get_rho(self):
        return self.A_f / (self.A_f + self.A_m)

    #-------------------------------------------------------
    # Material model for the matrix
    #-------------------------------------------------------
    mats_m = Property(Instance(MATS1DDamageWithFlaw), depends_on='+input')

    @cached_property
    def _get_mats_m(self):
        mats_m = MATS1DDamageWithFlaw(E=self.E_m * self.A_m,
                                      flaw_position=self.flaw_position,
                                      flaw_radius=self.flaw_radius,
                                      reduction_factor=self.reduction_factor,
                                      epsilon_0=self.epsilon_0,
                                      epsilon_f=self.epsilon_f)
        return mats_m

    mats_f = Instance(MATS1DElastic)

    def _mats_f_default(self):
        mats_f = MATS1DElastic(E=self.E_f * self.A_f)
        return mats_f

    mats_b = Instance(MATS1DEval)

    def _mats_b_default(self):
        mats_b = MATS1DElastic(E=self.K_b)
        mats_b = MATS1DPlastic(E=self.K_b,
                               sigma_y=self.T_max,
                               K_bar=0.,
                               H_bar=0.)  # plastic function of slip
        return mats_b

    mats_fb = Property(Instance(MATS1D5Bond), depends_on='+input')

    @cached_property
    def _get_mats_fb(self):

        # Material model construction
        return MATS1D5Bond(
            mats_phase1=MATS1DElastic(E=0),
            mats_phase2=self.mats_f,
            mats_ifslip=self.mats_b,
            mats_ifopen=MATS1DElastic(
                E=0)  # elastic function of open - inactive
        )

    #-------------------------------------------------------
    # Finite element type
    #-------------------------------------------------------
    fets_m = Property(depends_on='+input')

    @cached_property
    def _get_fets_m(self):
        fets_eval = FETS1D2L(mats_eval=self.mats_m)
        #fets_eval = FETS1D2L3U( mats_eval = self.mats_m )
        return fets_eval

    fets_fb = Property(depends_on='+input')

    @cached_property
    def _get_fets_fb(self):
        return FETS1D52L4ULRH(mats_eval=self.mats_fb)
        #return FETS1D52L6ULRH( mats_eval = self.mats_fb )
        #return FETS1D52L8ULRH( mats_eval = self.mats_fb )

    #--------------------------------------------------------------------------------------
    # Mesh integrator
    #--------------------------------------------------------------------------------------
    fe_domain_structure = Property(depends_on='+input')

    @cached_property
    def _get_fe_domain_structure(self):
        '''Root of the domain hierarchy
        '''
        elem_length = self.length / float(self.shape)

        fe_domain = FEDomain()

        fe_m_level = FERefinementGrid(name='matrix domain',
                                      domain=fe_domain,
                                      fets_eval=self.fets_m)

        fe_grid_m = FEGrid(name='matrix grid',
                           coord_max=(self.length, ),
                           shape=(self.shape, ),
                           level=fe_m_level,
                           fets_eval=self.fets_m,
                           geo_transform=self.geo_transform)

        fe_fb_level = FERefinementGrid(name='fiber bond domain',
                                       domain=fe_domain,
                                       fets_eval=self.fets_fb)

        fe_grid_fb = FEGrid(coord_min=(0., length / 5.),
                            coord_max=(length, 0.),
                            shape=(self.shape, 1),
                            level=fe_fb_level,
                            fets_eval=self.fets_fb,
                            geo_transform=self.geo_transform)

        return fe_domain, fe_grid_m, fe_grid_fb, fe_m_level, fe_fb_level

    fe_domain = Property

    def _get_fe_domain(self):
        return self.fe_domain_structure[0]

    fe_grid_m = Property

    def _get_fe_grid_m(self):
        return self.fe_domain_structure[1]

    fe_grid_fb = Property

    def _get_fe_grid_fb(self):
        return self.fe_domain_structure[2]

    fe_m_level = Property

    def _get_fe_m_level(self):
        return self.fe_domain_structure[3]

    fe_fb_level = Property

    def _get_fe_fb_level(self):
        return self.fe_domain_structure[4]

    #---------------------------------------------------------------------------
    # Load scaling adapted to the elastic and inelastic regime
    #---------------------------------------------------------------------------
    final_displ = Property(depends_on='+input')

    @cached_property
    def _get_final_displ(self):
        damage_onset_displ = self.mats_m.epsilon_0 * self.length
        return damage_onset_displ / self.elastic_fraction

    step_size = Property(depends_on='+input')

    @cached_property
    def _get_step_size(self):
        n_steps = self.n_steps
        return 1.0 / float(n_steps)

    time_function = Property(depends_on='+input')

    @cached_property
    def _get_time_function(self):
        '''Get the time function so that the elastic regime 
        is skipped in a single step.
        '''
        step_size = self.step_size

        elastic_value = self.elastic_fraction * 0.98 * self.reduction_factor
        inelastic_value = 1.0 - elastic_value

        def ls(t):
            if t <= step_size:
                return (elastic_value / step_size) * t
            else:
                return elastic_value + (t - step_size) * (inelastic_value) / (
                    1 - step_size)

        return ls

    def plot_time_function(self, p):
        '''Plot the time function.
        '''
        n_steps = self.n_steps
        mats = self.mats
        step_size = self.step_size

        ls_t = linspace(0, step_size * n_steps, n_steps + 1)
        ls_fn = frompyfunc(self.time_function, 1, 1)
        ls_v = ls_fn(ls_t)

        p.subplot(321)
        p.plot(ls_t, ls_v, 'ro-')

        final_epsilon = self.final_displ / self.length

        kappa = linspace(mats.epsilon_0, final_epsilon, 10)
        omega_fn = frompyfunc(lambda kappa: mats._get_omega(None, kappa), 1, 1)
        omega = omega_fn(kappa)
        kappa_scaled = (step_size + (1 - step_size) *
                        (kappa - mats.epsilon_0) /
                        (final_epsilon - mats.epsilon_0))
        xdata = hstack([array([0.0], dtype=float), kappa_scaled])
        ydata = hstack([array([0.0], dtype=float), omega])
        p.plot(xdata, ydata, 'g')
        p.xlabel('regular time [-]')
        p.ylabel('scaled time [-]')

    run = Button

    @on_trait_change('run')
    def peval(self):
        '''Evaluation procedure.
        '''
        #mv = MATS1DDamageView( model = mats_eval )
        #mv.configure_traits()

        right_dof_m = self.fe_grid_m[-1, -1].dofs[0, 0, 0]

        right_dof_fb = self.fe_grid_fb[-1, -1, -1, -1].dofs[0, 0, 0]
        # Response tracers
        A = self.A_m + self.A_f
        self.sig_eps_m = RTraceGraph(name='F_u_m',
                                     var_y='F_int',
                                     idx_y=right_dof_m,
                                     var_x='U_k',
                                     idx_x=right_dof_m,
                                     transform_y='y / %g' % A)

        # Response tracers
        self.sig_eps_f = RTraceGraph(name='F_u_f',
                                     var_y='F_int',
                                     idx_y=right_dof_fb,
                                     var_x='U_k',
                                     idx_x=right_dof_fb,
                                     transform_y='y / %g' % A)

        self.eps_m_field = RTraceDomainListField(name='eps_m',
                                                 position='int_pnts',
                                                 var='eps_app',
                                                 warp=False)

        self.eps_f_field = RTraceDomainListField(name='eps_f',
                                                 position='int_pnts',
                                                 var='mats_phase2_eps_app',
                                                 warp=False)
        # Response tracers
        self.sig_m_field = RTraceDomainListField(name='sig_m',
                                                 position='int_pnts',
                                                 var='sig_app')

        self.sig_f_field = RTraceDomainListField(name='sig_f',
                                                 position='int_pnts',
                                                 var='mats_phase2_sig_app')

        self.omega_m_field = RTraceDomainListField(name='omega_m',
                                                   position='int_pnts',
                                                   var='omega',
                                                   warp=False)

        self.shear_flow_field = RTraceDomainListField(name='shear flow',
                                                      position='int_pnts',
                                                      var='shear_flow',
                                                      warp=False)

        self.slip_field = RTraceDomainListField(name='slip',
                                                position='int_pnts',
                                                var='slip',
                                                warp=False)

        avg_processor = None
        if self.avg_radius > 0.0:
            n_dofs = self.fe_domain.n_dofs
            avg_processor = RTUAvg(sd=self.fe_m_level,
                                   n_dofs=n_dofs,
                                   avg_fn=QuarticAF(radius=self.avg_radius))

        ts = TStepper(
            u_processor=avg_processor,
            dof_resultants=True,
            sdomain=self.fe_domain,
            bcond_list=[  # define the left clamping 
                BCSlice(var='u',
                        value=0.,
                        dims=[0],
                        slice=self.fe_grid_fb[0, 0, 0, :]),
                #                                BCSlice( var = 'u', value = 0., dims = [0], slice = self.fe_grid_m[ 0, 0 ] ),
                # loading at the right edge
                #                                 BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0],
                #                                         time_function = ls ),
                BCSlice(var='u',
                        value=self.final_displ,
                        dims=[0],
                        slice=self.fe_grid_fb[-1, -1, -1, :],
                        time_function=self.time_function),
                #                                 BCSlice( var = 'u', value = self.final_displ, dims = [0], slice = self.fe_grid_m[-1, -1],
                #                                         time_function = self.time_function ),
                # fix horizontal displacement in the top layer
                #                                 BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ),
                # fix the vertical displacement all over the domain
                BCSlice(var='u',
                        value=0.,
                        dims=[1],
                        slice=self.fe_grid_fb[:, :, :, :]),
                #                            # Connect bond and matrix domains
                BCDofGroup(var='u',
                           value=0.,
                           dims=[0],
                           get_link_dof_method=self.fe_grid_fb.get_bottom_dofs,
                           get_dof_method=self.fe_grid_m.get_all_dofs,
                           link_coeffs=[1.])
            ],
            rtrace_list=[
                self.sig_eps_m,
                self.sig_eps_f,
                self.eps_m_field,
                self.eps_f_field,
                self.sig_m_field,
                self.sig_f_field,
                self.omega_m_field,
                self.shear_flow_field,
                self.slip_field,
            ])

        # Add the time-loop control
        tloop = TLoop(tstepper=ts,
                      KMAX=300,
                      tolerance=1e-5,
                      debug=False,
                      verbose_iteration=True,
                      verbose_time=False,
                      tline=TLine(min=0.0, step=self.step_size, max=1.0))

        tloop.on_accept_time_step = self.plot

        U = tloop.eval()

        self.sig_eps_f.refresh()
        max_sig_m = max(self.sig_eps_m.trace.ydata)
        return array([U[right_dof_m], max_sig_m], dtype='float_')

    #--------------------------------------------------------------------------------------
    # Tracers
    #--------------------------------------------------------------------------------------

    def plot_sig_eps(self, p):
        p.set_xlabel('control displacement [mm]')
        p.set_ylabel('stress [MPa]')

        self.sig_eps_m.refresh()
        self.sig_eps_m.trace.plot(p, 'o-')

        self.sig_eps_f.refresh()
        self.sig_eps_f.trace.plot(p, 'o-')

        p.plot(self.sig_eps_m.trace.xdata,
               self.sig_eps_m.trace.ydata + self.sig_eps_f.trace.ydata, 'o-')

    def plot_eps(self, p):
        eps_m = self.eps_m_field.subfields[0]
        xdata = eps_m.vtk_X[:, 0]
        ydata = eps_m.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], 'o-')

        eps_f = self.eps_f_field.subfields[1]
        xdata = eps_f.vtk_X[:, 0]
        ydata = eps_f.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], 'o-')

        p.set_ylim(ymin=0)
        p.set_xlabel('bar axis [mm]')
        p.set_ylabel('strain [-]')

    def plot_omega(self, p):
        omega_m = self.omega_m_field.subfields[0]
        xdata = omega_m.vtk_X[:, 0]
        ydata = omega_m.field_arr[:]
        idata = argsort(xdata)
        p.fill(xdata[idata], ydata[idata], facecolor='gray', alpha=0.2)

        print 'max omega', max(ydata[idata])

        p.set_ylim(ymin=0, ymax=1.0)
        p.set_xlabel('bar axis [mm]')
        p.set_ylabel('omega [-]')

    def plot_sig(self, p):
        sig_m = self.sig_m_field.subfields[0]
        xdata = sig_m.vtk_X[:, 0]
        ydata = sig_m.field_arr[:, 0, 0]
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], 'o-')

        sig_f = self.sig_f_field.subfields[1]
        xdata = sig_f.vtk_X[:, 0]
        ydata = sig_f.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], 'o-')

        xdata = sig_f.vtk_X[:, 0]
        ydata = sig_f.field_arr[:, 0, 0] + sig_m.field_arr[:, 0, 0]
        p.plot(xdata[idata], ydata[idata], 'ro-')

        p.set_ylim(ymin=0)  # , ymax = 1.2 * ymax )
        p.set_xlabel('bar axis [mm]')
        p.set_ylabel('stress [MPa]')

    def plot_shear_flow(self, p):
        shear_flow = self.shear_flow_field.subfields[1]
        xdata = shear_flow.vtk_X[:, 0]
        ydata = shear_flow.field_arr[:, 0] / self.P_f
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], 'o-')

        p.set_xlabel('bar axis [mm]')
        p.set_ylabel('shear flow [N/m]')

    def plot_slip(self, p):
        slip = self.slip_field.subfields[1]
        xdata = slip.vtk_X[:, 0]
        ydata = slip.field_arr[:, 0]
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], 'ro-')

        p.set_xlabel('bar axis [mm]')
        p.set_ylabel('slip [N/m]')

    def plot_tracers(self, p=p):

        p.subplot(221)
        self.plot_sig_eps(p)

        p.subplot(223)
        self.plot_eps(p)

        p.subplot(224)
        self.plot_sig(p)

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_ld = Instance(Figure)

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

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_eps = Instance(Figure)

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

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_shear_flow = Instance(Figure)

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

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_sig = Instance(Figure)

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

    #---------------------------------------------------------------
    # PLOT OBJECT
    #-------------------------------------------------------------------
    figure_shear_flow = Instance(Figure)

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

    def plot(self):

        self.figure_ld.clear()
        ax = self.figure_ld.gca()
        self.plot_sig_eps(ax)

        self.figure_eps.clear()
        ax = self.figure_eps.gca()
        self.plot_eps(ax)
        ax2 = ax.twinx()
        self.plot_omega(ax2)

        self.figure_sig.clear()
        ax = self.figure_sig.gca()
        self.plot_sig(ax)
        ax2 = ax.twinx()
        self.plot_omega(ax2)

        self.figure_shear_flow.clear()
        ax = self.figure_shear_flow.gca()
        self.plot_shear_flow(ax)
        ax2 = ax.twinx()
        self.plot_slip(ax2)

        self.data_changed = True

    def get_sim_outputs(self):
        '''
        Specifies the results and their order returned by the model
        evaluation.
        '''
        return [
            SimOut(name='right end displacement', unit='m'),
            SimOut(name='peak load', uni='MPa')
        ]

    data_changed = Event

    toolbar = ToolBar(Action(name="Run",
                             tooltip='Start computation',
                             image=ImageResource('kt-start'),
                             action="start_study"),
                      Action(name="Pause",
                             tooltip='Pause computation',
                             image=ImageResource('kt-pause'),
                             action="pause_study"),
                      Action(name="Stop",
                             tooltip='Stop computation',
                             image=ImageResource('kt-stop'),
                             action="stop_study"),
                      image_size=(32, 32),
                      show_tool_names=False,
                      show_divider=True,
                      name='view_toolbar'),

    traits_view = View(HSplit(
        VSplit(
            Item('run', show_label=False),
            VGroup(
                Item('shape'),
                Item('n_steps'),
                Item('length'),
                label='parameters',
                id='crackloc.viewmodel.factor.geometry',
                dock='tab',
                scrollable=True,
            ),
            VGroup(Item('E_m'),
                   Item('f_m_t'),
                   Item('avg_radius'),
                   Item('h_m'),
                   Item('b_m'),
                   Item('A_m', style='readonly'),
                   Item('mats_m', show_label=False),
                   label='Matrix',
                   dock='tab',
                   id='crackloc.viewmodel.factor.matrix',
                   scrollable=True),
            VGroup(Item('E_f'),
                   Item('A_f'),
                   Item('mats_f', show_label=False),
                   label='Fiber',
                   dock='tab',
                   id='crackloc.viewmodel.factor.fiber',
                   scrollable=True),
            VGroup(Group(
                Item('tau_max'),
                Item('s_crit'),
                Item('P_f', style='readonly', show_label=True),
                Item('K_b', style='readonly', show_label=True),
                Item('T_max', style='readonly', show_label=True),
            ),
                   Item('mats_b', show_label=False),
                   label='Bond',
                   dock='tab',
                   id='crackloc.viewmodel.factor.bond',
                   scrollable=True),
            VGroup(Item('rho', style='readonly', show_label=True),
                   label='Composite',
                   dock='tab',
                   id='crackloc.viewmodel.factor.jcomposite',
                   scrollable=True),
            id='crackloc.viewmodel.left',
            label='studied factors',
            layout='tabbed',
            dock='tab',
        ),
        VSplit(
            VGroup(
                Item('figure_ld',
                     editor=MPLFigureEditor(),
                     resizable=True,
                     show_label=False),
                label='stress-strain',
                id='crackloc.viewmode.figure_ld_window',
                dock='tab',
            ),
            VGroup(
                Item('figure_eps',
                     editor=MPLFigureEditor(),
                     resizable=True,
                     show_label=False),
                label='strains profile',
                id='crackloc.viewmode.figure_eps_window',
                dock='tab',
            ),
            VGroup(
                Item('figure_sig',
                     editor=MPLFigureEditor(),
                     resizable=True,
                     show_label=False),
                label='stress profile',
                id='crackloc.viewmode.figure_sig_window',
                dock='tab',
            ),
            VGroup(
                Item('figure_shear_flow',
                     editor=MPLFigureEditor(),
                     resizable=True,
                     show_label=False),
                label='bond shear and slip profiles',
                id='crackloc.viewmode.figure_shear_flow_window',
                dock='tab',
            ),
            id='crackloc.viewmodel.right',
        ),
        id='crackloc.viewmodel.splitter',
    ),
                       title='SimVisage Component: Crack localization',
                       id='crackloc.viewmodel',
                       dock='tab',
                       resizable=True,
                       height=0.8,
                       width=0.8,
                       buttons=[OKButton])
Exemplo n.º 8
0
class SimCrackLoc(IBVModel):
    """Model assembling the components for studying the restrained crack localization.
    """

    geo_transform = Instance(FlawCenteredGeoTransform)

    def _geo_transform_default(self):
        return FlawCenteredGeoTransform()

    shape = Int(10, desc="Number of finite elements", ps_levsls=(10, 40, 4), input=True)

    length = Float(1000, desc="Length of the simulated region", unit="mm", input=True)

    flaw_position = Float(500, input=True, unit="mm")

    flaw_radius = Float(100, input=True, unit="mm")

    reduction_factor = Float(0.9, input=True)

    elastic_fraction = Float(0.9, input=True)

    avg_radius = Float(400, input=True, unit="mm")

    # tensile strength of concrete
    f_m_t = Float(3.0, input=True, unit="MPa")

    epsilon_0 = Property(unit="-")

    def _get_epsilon_0(self):
        return self.f_m_t / self.E_m

    epsilon_f = Float(10, input=True, unit="-")

    h_m = Float(10, input=True, unit="mm")

    b_m = Float(8, input=True, unit="mm")

    A_m = Property(unit="m^2")

    def _get_A_m(self):
        return self.b_m * self.h_m

    E_m = Float(30.0e5, input=True, unit="MPa")

    E_f = Float(70.0e6, input=True, unit="MPa")

    A_f = Float(1.0, input=True, unit="mm^2")

    s_crit = Float(0.009, input=True, unit="mm")

    P_f = Property(depends_on="+input")

    @cached_property
    def _get_P_f(self):
        return sqrt(4 * self.A_f * pi)

    K_b = Property(depends_on="+input")

    @cached_property
    def _get_K_b(self):
        return self.T_max / self.s_crit

    tau_max = Float(0.0, input=True, unit="MPa")

    T_max = Property(depends_on="+input", unit="N/mm")

    @cached_property
    def _get_T_max(self):
        return self.tau_max * self.P_f

    rho = Property(depends_on="+input")

    @cached_property
    def _get_rho(self):
        return self.A_f / (self.A_f + self.A_m)

    # -------------------------------------------------------
    # Material model for the matrix
    # -------------------------------------------------------
    mats_m = Property(Instance(MATS1DDamageWithFlaw), depends_on="+input")

    @cached_property
    def _get_mats_m(self):
        mats_m = MATS1DDamageWithFlaw(
            E=self.E_m * self.A_m,
            flaw_position=self.flaw_position,
            flaw_radius=self.flaw_radius,
            reduction_factor=self.reduction_factor,
            epsilon_0=self.epsilon_0,
            epsilon_f=self.epsilon_f,
        )
        return mats_m

    mats_f = Instance(MATS1DElastic)

    def _mats_f_default(self):
        mats_f = MATS1DElastic(E=self.E_f * self.A_f)
        return mats_f

    mats_b = Instance(MATS1DEval)

    def _mats_b_default(self):
        mats_b = MATS1DElastic(E=self.K_b)
        mats_b = MATS1DPlastic(E=self.K_b, sigma_y=self.T_max, K_bar=0.0, H_bar=0.0)  # plastic function of slip
        return mats_b

    mats_fb = Property(Instance(MATS1D5Bond), depends_on="+input")

    @cached_property
    def _get_mats_fb(self):

        # Material model construction
        return MATS1D5Bond(
            mats_phase1=MATS1DElastic(E=0),
            mats_phase2=self.mats_f,
            mats_ifslip=self.mats_b,
            mats_ifopen=MATS1DElastic(E=0),  # elastic function of open - inactive
        )

    # -------------------------------------------------------
    # Finite element type
    # -------------------------------------------------------
    fets_m = Property(depends_on="+input")

    @cached_property
    def _get_fets_m(self):
        fets_eval = FETS1D2L(mats_eval=self.mats_m)
        # fets_eval = FETS1D2L3U( mats_eval = self.mats_m )
        return fets_eval

    fets_fb = Property(depends_on="+input")

    @cached_property
    def _get_fets_fb(self):
        return FETS1D52L4ULRH(mats_eval=self.mats_fb)
        # return FETS1D52L6ULRH( mats_eval = self.mats_fb )
        # return FETS1D52L8ULRH( mats_eval = self.mats_fb )

    # --------------------------------------------------------------------------------------
    # Mesh integrator
    # --------------------------------------------------------------------------------------
    fe_domain_structure = Property(depends_on="+input")

    @cached_property
    def _get_fe_domain_structure(self):
        """Root of the domain hierarchy
        """
        elem_length = self.length / float(self.shape)

        fe_domain = FEDomain()

        fe_m_level = FERefinementGrid(name="matrix domain", domain=fe_domain, fets_eval=self.fets_m)

        fe_grid_m = FEGrid(
            name="matrix grid",
            coord_max=(self.length,),
            shape=(self.shape,),
            level=fe_m_level,
            fets_eval=self.fets_m,
            geo_transform=self.geo_transform,
        )

        fe_fb_level = FERefinementGrid(name="fiber bond domain", domain=fe_domain, fets_eval=self.fets_fb)

        fe_grid_fb = FEGrid(
            coord_min=(0.0, length / 5.0),
            coord_max=(length, 0.0),
            shape=(self.shape, 1),
            level=fe_fb_level,
            fets_eval=self.fets_fb,
            geo_transform=self.geo_transform,
        )

        return fe_domain, fe_grid_m, fe_grid_fb, fe_m_level, fe_fb_level

    fe_domain = Property

    def _get_fe_domain(self):
        return self.fe_domain_structure[0]

    fe_grid_m = Property

    def _get_fe_grid_m(self):
        return self.fe_domain_structure[1]

    fe_grid_fb = Property

    def _get_fe_grid_fb(self):
        return self.fe_domain_structure[2]

    fe_m_level = Property

    def _get_fe_m_level(self):
        return self.fe_domain_structure[3]

    fe_fb_level = Property

    def _get_fe_fb_level(self):
        return self.fe_domain_structure[4]

    # ---------------------------------------------------------------------------
    # Load scaling adapted to the elastic and inelastic regime
    # ---------------------------------------------------------------------------
    final_displ = Property(depends_on="+input")

    @cached_property
    def _get_final_displ(self):
        damage_onset_displ = self.mats_m.epsilon_0 * self.length
        return damage_onset_displ / self.elastic_fraction

    step_size = Property(depends_on="+input")

    @cached_property
    def _get_step_size(self):
        n_steps = self.n_steps
        return 1.0 / float(n_steps)

    time_function = Property(depends_on="+input")

    @cached_property
    def _get_time_function(self):
        """Get the time function so that the elastic regime 
        is skipped in a single step.
        """
        step_size = self.step_size

        elastic_value = self.elastic_fraction * 0.98 * self.reduction_factor
        inelastic_value = 1.0 - elastic_value

        def ls(t):
            if t <= step_size:
                return (elastic_value / step_size) * t
            else:
                return elastic_value + (t - step_size) * (inelastic_value) / (1 - step_size)

        return ls

    def plot_time_function(self, p):
        """Plot the time function.
        """
        n_steps = self.n_steps
        mats = self.mats
        step_size = self.step_size

        ls_t = linspace(0, step_size * n_steps, n_steps + 1)
        ls_fn = frompyfunc(self.time_function, 1, 1)
        ls_v = ls_fn(ls_t)

        p.subplot(321)
        p.plot(ls_t, ls_v, "ro-")

        final_epsilon = self.final_displ / self.length

        kappa = linspace(mats.epsilon_0, final_epsilon, 10)
        omega_fn = frompyfunc(lambda kappa: mats._get_omega(None, kappa), 1, 1)
        omega = omega_fn(kappa)
        kappa_scaled = step_size + (1 - step_size) * (kappa - mats.epsilon_0) / (final_epsilon - mats.epsilon_0)
        xdata = hstack([array([0.0], dtype=float), kappa_scaled])
        ydata = hstack([array([0.0], dtype=float), omega])
        p.plot(xdata, ydata, "g")
        p.xlabel("regular time [-]")
        p.ylabel("scaled time [-]")

    run = Button

    @on_trait_change("run")
    def peval(self):
        """Evaluation procedure.
        """
        # mv = MATS1DDamageView( model = mats_eval )
        # mv.configure_traits()

        right_dof_m = self.fe_grid_m[-1, -1].dofs[0, 0, 0]

        right_dof_fb = self.fe_grid_fb[-1, -1, -1, -1].dofs[0, 0, 0]
        # Response tracers
        A = self.A_m + self.A_f
        self.sig_eps_m = RTraceGraph(
            name="F_u_m", var_y="F_int", idx_y=right_dof_m, var_x="U_k", idx_x=right_dof_m, transform_y="y / %g" % A
        )

        # Response tracers
        self.sig_eps_f = RTraceGraph(
            name="F_u_f", var_y="F_int", idx_y=right_dof_fb, var_x="U_k", idx_x=right_dof_fb, transform_y="y / %g" % A
        )

        self.eps_m_field = RTraceDomainListField(name="eps_m", position="int_pnts", var="eps_app", warp=False)

        self.eps_f_field = RTraceDomainListField(
            name="eps_f", position="int_pnts", var="mats_phase2_eps_app", warp=False
        )
        # Response tracers
        self.sig_m_field = RTraceDomainListField(name="sig_m", position="int_pnts", var="sig_app")

        self.sig_f_field = RTraceDomainListField(name="sig_f", position="int_pnts", var="mats_phase2_sig_app")

        self.omega_m_field = RTraceDomainListField(name="omega_m", position="int_pnts", var="omega", warp=False)

        self.shear_flow_field = RTraceDomainListField(
            name="shear flow", position="int_pnts", var="shear_flow", warp=False
        )

        self.slip_field = RTraceDomainListField(name="slip", position="int_pnts", var="slip", warp=False)

        avg_processor = None
        if self.avg_radius > 0.0:
            n_dofs = self.fe_domain.n_dofs
            avg_processor = RTUAvg(sd=self.fe_m_level, n_dofs=n_dofs, avg_fn=QuarticAF(radius=self.avg_radius))

        ts = TStepper(
            u_processor=avg_processor,
            dof_resultants=True,
            sdomain=self.fe_domain,
            bcond_list=[  # define the left clamping
                BCSlice(var="u", value=0.0, dims=[0], slice=self.fe_grid_fb[0, 0, 0, :]),
                #                                BCSlice( var = 'u', value = 0., dims = [0], slice = self.fe_grid_m[ 0, 0 ] ),
                # loading at the right edge
                #                                 BCSlice( var = 'f', value = 1, dims = [0], slice = domain[-1, -1, -1, 0],
                #                                         time_function = ls ),
                BCSlice(
                    var="u",
                    value=self.final_displ,
                    dims=[0],
                    slice=self.fe_grid_fb[-1, -1, -1, :],
                    time_function=self.time_function,
                ),
                #                                 BCSlice( var = 'u', value = self.final_displ, dims = [0], slice = self.fe_grid_m[-1, -1],
                #                                         time_function = self.time_function ),
                # fix horizontal displacement in the top layer
                #                                 BCSlice( var = 'u', value = 0., dims = [0], slice = domain[:, -1, :, -1] ),
                # fix the vertical displacement all over the domain
                BCSlice(var="u", value=0.0, dims=[1], slice=self.fe_grid_fb[:, :, :, :]),
                #                            # Connect bond and matrix domains
                BCDofGroup(
                    var="u",
                    value=0.0,
                    dims=[0],
                    get_link_dof_method=self.fe_grid_fb.get_bottom_dofs,
                    get_dof_method=self.fe_grid_m.get_all_dofs,
                    link_coeffs=[1.0],
                ),
            ],
            rtrace_list=[
                self.sig_eps_m,
                self.sig_eps_f,
                self.eps_m_field,
                self.eps_f_field,
                self.sig_m_field,
                self.sig_f_field,
                self.omega_m_field,
                self.shear_flow_field,
                self.slip_field,
            ],
        )

        # Add the time-loop control
        tloop = TLoop(
            tstepper=ts,
            KMAX=300,
            tolerance=1e-5,
            debug=False,
            verbose_iteration=True,
            verbose_time=False,
            tline=TLine(min=0.0, step=self.step_size, max=1.0),
        )

        tloop.on_accept_time_step = self.plot

        U = tloop.eval()

        self.sig_eps_f.refresh()
        max_sig_m = max(self.sig_eps_m.trace.ydata)
        return array([U[right_dof_m], max_sig_m], dtype="float_")

    # --------------------------------------------------------------------------------------
    # Tracers
    # --------------------------------------------------------------------------------------

    def plot_sig_eps(self, p):
        p.set_xlabel("control displacement [mm]")
        p.set_ylabel("stress [MPa]")

        self.sig_eps_m.refresh()
        self.sig_eps_m.trace.plot(p, "o-")

        self.sig_eps_f.refresh()
        self.sig_eps_f.trace.plot(p, "o-")

        p.plot(self.sig_eps_m.trace.xdata, self.sig_eps_m.trace.ydata + self.sig_eps_f.trace.ydata, "o-")

    def plot_eps(self, p):
        eps_m = self.eps_m_field.subfields[0]
        xdata = eps_m.vtk_X[:, 0]
        ydata = eps_m.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], "o-")

        eps_f = self.eps_f_field.subfields[1]
        xdata = eps_f.vtk_X[:, 0]
        ydata = eps_f.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], "o-")

        p.set_ylim(ymin=0)
        p.set_xlabel("bar axis [mm]")
        p.set_ylabel("strain [-]")

    def plot_omega(self, p):
        omega_m = self.omega_m_field.subfields[0]
        xdata = omega_m.vtk_X[:, 0]
        ydata = omega_m.field_arr[:]
        idata = argsort(xdata)
        p.fill(xdata[idata], ydata[idata], facecolor="gray", alpha=0.2)

        print "max omega", max(ydata[idata])

        p.set_ylim(ymin=0, ymax=1.0)
        p.set_xlabel("bar axis [mm]")
        p.set_ylabel("omega [-]")

    def plot_sig(self, p):
        sig_m = self.sig_m_field.subfields[0]
        xdata = sig_m.vtk_X[:, 0]
        ydata = sig_m.field_arr[:, 0, 0]
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], "o-")

        sig_f = self.sig_f_field.subfields[1]
        xdata = sig_f.vtk_X[:, 0]
        ydata = sig_f.field_arr[:, 0, 0]
        idata = argsort(xdata)
        p.plot(xdata[idata], ydata[idata], "o-")

        xdata = sig_f.vtk_X[:, 0]
        ydata = sig_f.field_arr[:, 0, 0] + sig_m.field_arr[:, 0, 0]
        p.plot(xdata[idata], ydata[idata], "ro-")

        p.set_ylim(ymin=0)  # , ymax = 1.2 * ymax )
        p.set_xlabel("bar axis [mm]")
        p.set_ylabel("stress [MPa]")

    def plot_shear_flow(self, p):
        shear_flow = self.shear_flow_field.subfields[1]
        xdata = shear_flow.vtk_X[:, 0]
        ydata = shear_flow.field_arr[:, 0] / self.P_f
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], "o-")

        p.set_xlabel("bar axis [mm]")
        p.set_ylabel("shear flow [N/m]")

    def plot_slip(self, p):
        slip = self.slip_field.subfields[1]
        xdata = slip.vtk_X[:, 0]
        ydata = slip.field_arr[:, 0]
        idata = argsort(xdata)
        ymax = max(ydata)
        p.plot(xdata[idata], ydata[idata], "ro-")

        p.set_xlabel("bar axis [mm]")
        p.set_ylabel("slip [N/m]")

    def plot_tracers(self, p=p):

        p.subplot(221)
        self.plot_sig_eps(p)

        p.subplot(223)
        self.plot_eps(p)

        p.subplot(224)
        self.plot_sig(p)

    # ---------------------------------------------------------------
    # PLOT OBJECT
    # -------------------------------------------------------------------
    figure_ld = Instance(Figure)

    def _figure_ld_default(self):
        figure = Figure(facecolor="white")
        figure.add_axes([0.12, 0.13, 0.85, 0.74])
        return figure

    # ---------------------------------------------------------------
    # PLOT OBJECT
    # -------------------------------------------------------------------
    figure_eps = Instance(Figure)

    def _figure_eps_default(self):
        figure = Figure(facecolor="white")
        figure.add_axes([0.12, 0.13, 0.85, 0.74])
        return figure

    # ---------------------------------------------------------------
    # PLOT OBJECT
    # -------------------------------------------------------------------
    figure_shear_flow = Instance(Figure)

    def _figure_shear_flow_default(self):
        figure = Figure(facecolor="white")
        figure.add_axes([0.12, 0.13, 0.85, 0.74])
        return figure

    # ---------------------------------------------------------------
    # PLOT OBJECT
    # -------------------------------------------------------------------
    figure_sig = Instance(Figure)

    def _figure_sig_default(self):
        figure = Figure(facecolor="white")
        figure.add_axes([0.12, 0.13, 0.85, 0.74])
        return figure

    # ---------------------------------------------------------------
    # PLOT OBJECT
    # -------------------------------------------------------------------
    figure_shear_flow = Instance(Figure)

    def _figure_shear_flow_default(self):
        figure = Figure(facecolor="white")
        figure.add_axes([0.12, 0.13, 0.85, 0.74])
        return figure

    def plot(self):

        self.figure_ld.clear()
        ax = self.figure_ld.gca()
        self.plot_sig_eps(ax)

        self.figure_eps.clear()
        ax = self.figure_eps.gca()
        self.plot_eps(ax)
        ax2 = ax.twinx()
        self.plot_omega(ax2)

        self.figure_sig.clear()
        ax = self.figure_sig.gca()
        self.plot_sig(ax)
        ax2 = ax.twinx()
        self.plot_omega(ax2)

        self.figure_shear_flow.clear()
        ax = self.figure_shear_flow.gca()
        self.plot_shear_flow(ax)
        ax2 = ax.twinx()
        self.plot_slip(ax2)

        self.data_changed = True

    def get_sim_outputs(self):
        """
        Specifies the results and their order returned by the model
        evaluation.
        """
        return [SimOut(name="right end displacement", unit="m"), SimOut(name="peak load", uni="MPa")]

    data_changed = Event

    toolbar = (
        ToolBar(
            Action(name="Run", tooltip="Start computation", image=ImageResource("kt-start"), action="start_study"),
            Action(name="Pause", tooltip="Pause computation", image=ImageResource("kt-pause"), action="pause_study"),
            Action(name="Stop", tooltip="Stop computation", image=ImageResource("kt-stop"), action="stop_study"),
            image_size=(32, 32),
            show_tool_names=False,
            show_divider=True,
            name="view_toolbar",
        ),
    )

    traits_view = View(
        HSplit(
            VSplit(
                Item("run", show_label=False),
                VGroup(
                    Item("shape"),
                    Item("n_steps"),
                    Item("length"),
                    label="parameters",
                    id="crackloc.viewmodel.factor.geometry",
                    dock="tab",
                    scrollable=True,
                ),
                VGroup(
                    Item("E_m"),
                    Item("f_m_t"),
                    Item("avg_radius"),
                    Item("h_m"),
                    Item("b_m"),
                    Item("A_m", style="readonly"),
                    Item("mats_m", show_label=False),
                    label="Matrix",
                    dock="tab",
                    id="crackloc.viewmodel.factor.matrix",
                    scrollable=True,
                ),
                VGroup(
                    Item("E_f"),
                    Item("A_f"),
                    Item("mats_f", show_label=False),
                    label="Fiber",
                    dock="tab",
                    id="crackloc.viewmodel.factor.fiber",
                    scrollable=True,
                ),
                VGroup(
                    Group(
                        Item("tau_max"),
                        Item("s_crit"),
                        Item("P_f", style="readonly", show_label=True),
                        Item("K_b", style="readonly", show_label=True),
                        Item("T_max", style="readonly", show_label=True),
                    ),
                    Item("mats_b", show_label=False),
                    label="Bond",
                    dock="tab",
                    id="crackloc.viewmodel.factor.bond",
                    scrollable=True,
                ),
                VGroup(
                    Item("rho", style="readonly", show_label=True),
                    label="Composite",
                    dock="tab",
                    id="crackloc.viewmodel.factor.jcomposite",
                    scrollable=True,
                ),
                id="crackloc.viewmodel.left",
                label="studied factors",
                layout="tabbed",
                dock="tab",
            ),
            VSplit(
                VGroup(
                    Item("figure_ld", editor=MPLFigureEditor(), resizable=True, show_label=False),
                    label="stress-strain",
                    id="crackloc.viewmode.figure_ld_window",
                    dock="tab",
                ),
                VGroup(
                    Item("figure_eps", editor=MPLFigureEditor(), resizable=True, show_label=False),
                    label="strains profile",
                    id="crackloc.viewmode.figure_eps_window",
                    dock="tab",
                ),
                VGroup(
                    Item("figure_sig", editor=MPLFigureEditor(), resizable=True, show_label=False),
                    label="stress profile",
                    id="crackloc.viewmode.figure_sig_window",
                    dock="tab",
                ),
                VGroup(
                    Item("figure_shear_flow", editor=MPLFigureEditor(), resizable=True, show_label=False),
                    label="bond shear and slip profiles",
                    id="crackloc.viewmode.figure_shear_flow_window",
                    dock="tab",
                ),
                id="crackloc.viewmodel.right",
            ),
            id="crackloc.viewmodel.splitter",
        ),
        title="SimVisage Component: Crack localization",
        id="crackloc.viewmodel",
        dock="tab",
        resizable=True,
        height=0.8,
        width=0.8,
        buttons=[OKButton],
    )
Exemplo n.º 9
0
    def eval(self):

        elem_length = self.length / float(self.shape)
        flaw_radius = self.flaw_radius

        mats = MATS1DElasticWithFlaw(E=10.,
                                     flaw_position=self.flaw_position,
                                     flaw_radius=flaw_radius,
                                     reduction_factor=self.reduction_factor)

        #fets_eval = FETS1D2L( mats_eval = mats )
        fets_eval = FETS1D2L3U(mats_eval=mats)

        domain = FEGrid(coord_max=(self.length, 0., 0.),
                               shape=(self.shape,),
                               fets_eval=fets_eval)

        avg_processor = RTNonlocalAvg(avg_fn=QuarticAF(radius=self.avg_radius,
                                                           correction=True))

        eps_app = RTraceDomainListField(name='Strain' ,
                                         position='int_pnts',
                                         var='eps_app',
                                         warp=False)

        damage = RTraceDomainListField(name='Damage' ,
                                        position='int_pnts',
                                      var='omega',
                                        warp=False)

        disp = RTraceDomainListField(name='Displacement' ,
                                      position='int_pnts',
                                      var='u',
                                      warp=False)

        sig_app = RTraceDomainListField(name='Stress' ,
                                        position='int_pnts',
                                        var='sig_app')

        right_dof = domain[-1, -1].dofs[0, 0, 0]
        rt_fu = RTraceGraph(name='Fi,right over u_right (iteration)' ,
                             var_y='F_int', idx_y=right_dof,
                             var_x='U_k', idx_x=right_dof)

        ts = TS(u_processor=avg_processor,
                dof_resultants=True,
                sdomain=domain,
             # conversion to list (square brackets) is only necessary for slicing of 
             # single dofs, e.g "get_left_dofs()[0,1]"
    #         bcond_list =  [ BCDof(var='u', dof = 0, value = 0.)     ] +  
    #                    [ BCDof(var='u', dof = 2, value = 0.001 ) ]+
    #                    [ )     ],
             bcond_list=[BCDof(var='u', dof=0, value=0.),
    #                        BCDof(var='u', dof = 1, link_dofs = [2], link_coeffs = [0.5],
    #                              value = 0. ),
    #                        BCDof(var='u', dof = 2, link_dofs = [3], link_coeffs = [1.],
    #                              value = 0. ),
                            BCDof(var='u', dof=right_dof, value=0.01,
                                       ) ],
             rtrace_list=[ rt_fu,
                             eps_app,
                             # damage,
                             sig_app,
                             disp,
                    ]
                )

        # Add the time-loop control
        tloop = TLoop(tstepper=ts, KMAX=100, tolerance=1e-5,
                       verbose_iteration=False,
                       tline=TLine(min=0.0, step=1.0, max=1.0))

        U = tloop.eval()

        p.subplot(221)
        rt_fu.refresh()
        rt_fu.trace.plot(p)

        eps = eps_app.subfields[0]
        xdata = eps.vtk_X[:, 0]
        ydata = eps.field_arr[:, 0, 0]
        idata = argsort(xdata)

        p.subplot(222)
        p.plot(xdata[idata], ydata[idata], 'o-')

        disp = disp.subfields[0]
        xdata = disp.vtk_X[:, 0]
        ydata = disp.field_arr[:, 0]
        idata = argsort(xdata)

        p.subplot(223)
        p.plot(xdata[idata], ydata[idata], 'o-')

        sig = sig_app.subfields[0]
        xdata = sig.vtk_X[:, 0]
        ydata = sig.field_arr[:, 0, 0]
        idata = argsort(xdata)

        p.subplot(224)
        p.plot(xdata[idata], ydata[idata], 'o-')
Exemplo n.º 10
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') ]
Exemplo n.º 11
0
class SimBT3PT(IBVModel):
    '''Simulation: Bending Test Three Point
    '''

    input_change = Event

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

    implements(ISimModel)

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

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

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

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

    # support discretization in xy-direction:
    # NOTE: chose '2' for 2x2-grid or '4' for 4x4-grid
    #
    shape_supprt_x = Int(2, input=True, ps_levels=(2, 4, 2))

    #-----------------
    # geometry:
    #-----------------
    #
    # edge length of the bending specimen (beam) (entire length without symmetry)
    length = Float(1.15, input=True)
    elstmr_length = Float(0.05, input=True)
    elstmr_thickness = Float(0.005, input=True, enter_set=True, auto_set=False)
    width = Float(0.20, input=True)
    thickness = Float(0.06, input=True, ps_levels=(0.054, 0.060, 0.066))

    # thickness of the tappered support
    #
    thickness_supprt = Float(0.02, 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.

    # 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.

    #-----------------
    # specify the refinement of the idealization
    #-----------------

    # specify weather elastomer is to be modeled for load introduction
    #
    elstmr_flag = True

    # specify weather steel support is to be modeled
    #
    supprt_flag = False

    #-----------------
    # 'geo_transform'
    #-----------------

    # geometry transformation for four sided tappered support with reduced stiffness towards the edges (if modeled)
    #
    geo_supprt = Property(Instance(GeoSUPPRT), depends_on='+ps_levels, +input')

    @cached_property
    def _get_geo_supprt(self):
        # element length within the range of the slab without the area of the
        # load introduction plate
        #
        elem_size = self.sym_specmn_length / self.shape_x
        width_supprt = self.shape_supprt_x * elem_size
        print 'width_supprt = ', width_supprt
        return GeoSUPPRT(thickness_supprt=self.thickness_supprt,
                         width_supprt=width_supprt,
                         xyoffset=0.,
                         zoffset=-self.thickness_supprt)

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

    # age of the specimen at the time of testing
    # determines the E-modulus and nu based on the time dependent function stored
    # in 'CCSUniteCell' if params are not explicitly set
    #
    age = Int(28, input=True)

    # composite E-modulus / Poisson's ratio
    # NOTE 1: value are retrieved from the database
    #         same values are used for calibration (as taken from tensile test) and for slab test
    # NOTE 2: alternatively the same phi-function could be used independent of age. This would assume
    #         an afine/proportional damage evolution for different ages, i.e. a different E would be
    #         used in the simulation of the slab test and within the calibration procedure.

    # 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(None, np.inf)

    # number of microplanes
    #
    n_mp = Int(30., auto_set=False, enter_set=True, input=True)

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

    # @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,  # relevant for compressive behavior/used for calibration of phi_fn
            nu=self.nu,
            # corresponding to settings in "MatsCalib"
            n_mp=30,
            symmetrization='sum-type',
            model_version='compliance',
            phi_fn=self.phi_fn)

    E_elstmr = Float(3000., input=True)

    elstmr_mats = Property(Instance(MATS3DElastic), depends_on='input_change')

    @cached_property
    def _get_elstmr_mats(self):
        E_elstmr = self.E_elstmr
        print 'effective elastomer E_modulus', E_elstmr
        return MATS3DElastic(E=E_elstmr, nu=0.4)

    # E-modulus and nu of steel support
    E_s = Float(210000., auto_set=False, enter_set=True, input=True)
    nu_s = Float(0.20, auto_set=False, enter_set=True, input=True)

    supprt_mats = Property(Instance(MATS3DElastic), depends_on='input_change')

    @cached_property
    def _get_supprt_mats(self):
        return MATS3DElastic(E=self.E_s, nu=self.nu_s)

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

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

    # use quadratic serendipity elements
    # NOTE: 2D5 elements behave linear elastic in out of plane direction!
    #
    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

    supprt_fets = Property(Instance(FETSEval), depends_on='input_change')

    @cached_property
    def _get_supprt_fets(self):
        # linear-elastic behavior quadratic serendipity elements
        fets = FETS3D8H20U(mats_eval=self.supprt_mats)
        fets.vtk_r *= self.vtk_r
        return fets

    #-----------------
    # fe_grid:
    #-----------------

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

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

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

    @cached_property
    def _get_mid_specmn_fe_level(self):
        return FERefinementGrid(name='middle specimen patch',
                                fets_eval=self.specmn_fets,
                                domain=self.fe_domain)

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

    @cached_property
    def _get_mid_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_elstmr_length, self.width / 2,
                                    self.thickness),
                         shape=(self.mid_shape_x, self.shape_y, self.shape_z),
                         level=self.mid_specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

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

    @cached_property
    def _get_specmn_fe_level(self):
        return FERefinementGrid(name='specimen patch',
                                fets_eval=self.specmn_fets,
                                domain=self.fe_domain)

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

    @cached_property
    def _get_specmn_fe_grid(self):
        # only a quarter of the beam is simulated due to symmetry:
        fe_grid = FEGrid(coord_min=(self.sym_elstmr_length, 0., 0.),
                         coord_max=(self.sym_specmn_length, self.sym_width,
                                    self.thickness),
                         shape=(self.shape_x, self.shape_y, self.shape_z),
                         level=self.specmn_fe_level,
                         fets_eval=self.specmn_fets)
        return fe_grid

#    if elstmr_flag:

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

    @cached_property
    def _get_elstmr_fe_level(self):
        return FERefinementGrid(name='elastomer patch',
                                fets_eval=self.elstmr_fets,
                                domain=self.fe_domain)

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

    @cached_property
    def _get_elstmr_fe_grid(self):
        x_max = self.sym_elstmr_length
        y_max = self.width / 2.
        z_max = self.thickness + self.elstmr_thickness
        fe_grid = FEGrid(coord_min=(0, 0, self.thickness),
                         coord_max=(x_max, y_max, z_max),
                         level=self.elstmr_fe_level,
                         shape=(self.mid_shape_x, self.shape_y, 1),
                         fets_eval=self.elstmr_fets)
        return fe_grid

    if supprt_flag:
        supprt_fe_level = Property(depends_on='+ps_levels, +input')

        @cached_property
        def _get_supprt_fe_level(self):
            return FERefinementGrid(name='elastomer patch',
                                    fets_eval=self.supprt_fets,
                                    domain=self.fe_domain)

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

        @cached_property
        def _get_supprt_fe_grid(self):
            return FEGrid(
                coord_min=(0, 0, 0),
                coord_max=(1, 1, 1),
                level=self.supprt_fe_level,
                # use shape (2,2) in order to place support in the center of the steel support
                # corresponding to 4 elements of the slab mesh
                #
                shape=(self.shape_supprt_x, self.shape_supprt_x, 1),
                geo_transform=self.geo_supprt,
                fets_eval=self.supprt_fets)

    #===========================================================================
    # Boundary conditions
    #===========================================================================

    # w_max = center displacement:
    #
    w_max = Float(-0.010, input=True)  # [m]

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

    @cached_property
    def _get_bc_list(self):
        specmn = self.specmn_fe_grid
        mid_specmn = self.mid_specmn_fe_grid
        if self.elstmr_flag:
            elstmr = self.elstmr_fe_grid

        #--------------------------------------------------------------
        # boundary conditions for the symmetry
        #--------------------------------------------------------------
        # the x-axis corresponds to the axis of symmetry along the longitudinal axis of the beam:
        bc_symplane_xz = BCSlice(var='u',
                                 value=0.,
                                 dims=[1],
                                 slice=specmn[:, 0, :, :, 0, :])

        bc_mid_symplane_xz = BCSlice(var='u',
                                     value=0.,
                                     dims=[1],
                                     slice=mid_specmn[:, 0, :, :, 0, :])

        bc_mid_symplane_yz = BCSlice(var='u',
                                     value=0.,
                                     dims=[0],
                                     slice=mid_specmn[0, :, :, 0, :, :])

        if self.elstmr_flag:
            bc_el_symplane_xz = BCSlice(var='u',
                                        value=0.,
                                        dims=[1],
                                        slice=elstmr[:, 0, :, :, 0, :])
            bc_el_symplane_yz = BCSlice(var='u',
                                        value=0.,
                                        dims=[0],
                                        slice=elstmr[0, :, :, 0, :, :])

        #--------------------------------------------------------------
        # boundary conditions for the support
        #--------------------------------------------------------------
        bc_support_0y0 = BCSlice(var='u',
                                 value=0.,
                                 dims=[2],
                                 slice=specmn[-1, :, 0, -1, :, 0])

        #--------------------------------------------------------------
        # link domains
        #--------------------------------------------------------------
        link_msp_sp = BCDofGroup(var='u',
                                 value=0.,
                                 dims=[0, 1, 2],
                                 get_dof_method=mid_specmn.get_right_dofs,
                                 get_link_dof_method=specmn.get_left_dofs,
                                 link_coeffs=[1.])

        #        link_msp_sp_xyz = BCSlice(var = 'u', value = 0., dims = [0, 1, 2],
        #                             slice = specmn[0, :, :, 0, :, :],
        #                             link_slice = mid_specmn[-1 :, :, -1, :, :],
        #                             link_dims = [0, 1, 2],
        #                             link_coeffs = [1.])

        #        link_msp_sp_y = BCSlice(var = 'u', value = 0., dims = [1],
        #                             slice = specmn[0, :, :, 0, :, :],
        #                             link_slice = mid_specmn[-1 :, :, -1, :, :],
        #                             link_dims = [1],
        #                             link_coeffs = [1.])
        #
        #        link_msp_sp_z = BCSlice(var = 'u', value = 0., dims = [2],
        #                             slice = specmn[0, :, :, 0, :, :],
        #                             link_slice = mid_specmn[-1 :, :, -1, :, :],
        #                             link_dims = [2],
        #                             link_coeffs = [1.])

        #        link_msp_sp = [ link_msp_sp_xyz ]

        if self.elstmr_flag:
            link_el_sp = BCDofGroup(
                var='u',
                value=0.,
                dims=[2],
                get_dof_method=elstmr.get_back_dofs,
                get_link_dof_method=mid_specmn.get_front_dofs,
                link_coeffs=[1.])

        #--------------------------------------------------------------
        # loading
        #--------------------------------------------------------------
        w_max = self.w_max
        #        f_max = -0.010 / 0.10 # [MN/m]

        if self.elstmr_flag:
            # apply displacement at all top node (surface load)
            #
            bc_w = BCSlice(var='u',
                           value=w_max,
                           dims=[2],
                           slice=elstmr[:, :, -1, :, :, -1])
            # apply a single force at the center of the beam (system origin at top of the elastomer
            # and us elastomer-domain as load distribution plate with a high stiffness (e.g. steel)
#            F_max = -0.010 #[MN]
#            bc_F = BCSlice(var = 'f', value = F_max, dims = [2],
#                           slice = elstmr[0, 0, -1, 0, 0, -1])
        else:
            # center top nodes (line load)
            #
            bc_w = BCSlice(var='u',
                           value=w_max,
                           dims=[2],
                           slice=mid_specmn[0, :, -1, 0, :, -1])
            # NOTE: the entire symmetry axis (yz)-plane is moved downwards
            # in order to avoid large indentations at the top nodes
            #


#          bc_center_w = BCSlice( var = 'w', value = w_max, dims = [2], slice = mid_specmn[0, :, :, 0, :, :] )

        bc_list = [
            bc_symplane_xz, bc_mid_symplane_xz, bc_mid_symplane_yz,
            bc_support_0y0, link_msp_sp, bc_w
        ]

        if self.elstmr_flag:
            bc_list_elstmr = [link_el_sp, bc_el_symplane_xz, bc_el_symplane_yz]
            bc_list += bc_list_elstmr

        return bc_list

    tloop = Property(depends_on='input_change')

    @cached_property
    def _get_tloop(self):

        #--------------------------------------------------------------
        # ts
        #--------------------------------------------------------------

        specmn = self.specmn_fe_grid
        mid_specmn = self.mid_specmn_fe_grid

        if self.supprt_flag:
            supprt = self.supprt_fe_grid
            supprt_dofs_z = np.unique(supprt[self.shape_supprt_x / 2,
                                             self.shape_y / 2, 0, 0, 0,
                                             0].dofs[:, :, 2].flatten())
        else:
            supprt_dofs_z = np.unique(specmn[-1, :, 0, -1, :,
                                             0].dofs[:, :, 2].flatten())
        print 'supprt_dofs_z (unique)', supprt_dofs_z

        if self.elstmr_flag:
            elstmr = self.elstmr_fe_grid
            load_dofs_z = np.unique(elstmr[:, :, -1, :, :,
                                           -1].dofs[:, :, 2].flatten())
        else:
            # center_top_line_dofs
            #
            load_dofs_z = np.unique(mid_specmn[0, :, -1, 0, :,
                                               -1].dofs[:, :, 2].flatten())
        print 'load_dofs_z used for integration of force: ', load_dofs_z

        # center top z-dof
        #
        center_top_dof_z = mid_specmn[0, 0, 0, 0, 0, 0].dofs[0, 0, 2]
        print 'center_top_dof used for displacement tracing: ', center_top_dof_z

        # force-displacement-diagram (LOAD)
        # (surface load on the elstmr or line load at specimen center)
        #
        self.f_w_diagram_center = RTraceGraph(
            name='displacement (center) - reaction 2',
            var_x='U_k',
            idx_x=center_top_dof_z,
            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 (SUPPORT)
        # (dofs at support line of the specmn used to integrate the force)
        #
        self.f_w_diagram_supprt = RTraceGraph(
            name='displacement (center) - reaction 2',
            var_x='U_k',
            idx_x=center_top_dof_z,
            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')

        ts = TS(
            sdomain=self.fe_domain,
            bcond_list=self.bc_list,
            rtrace_list=[
                self.f_w_diagram_center,
                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))

        return tloop

    #--------------------------------------------------------------
    # prepare pstudy
    #--------------------------------------------------------------

    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')
        ]