Exemple #1
0
class TGrid(RegularGrid):
    '''
        Regular grid of random variables theta.
    '''
    theta_11 = Array(float)

    def _theta_11_default(self):
        ''' 'discretize the range (-1,1) symmetrically with n_int points '''
        n_int = self.randomization.n_int
        return np.linspace(-(1.0 - 1.0 / n_int), (1.0 - 1.0 / n_int), n_int)

    def get_theta_for_distrib(self, tvar):
        if tvar.n_int != None:
            n_int = tvar.n_int
        else:
            n_int = self.randomization.n_int
        min_theta, max_theta, d_theta = self.get_theta_range(tvar)
        return np.linspace(min_theta + 0.5 * d_theta,
                           max_theta - 0.5 * d_theta, n_int)

    dG_ogrid = Property(Array(float), depends_on='recalc')

    @cached_property
    def _get_dG_ogrid(self):
        dG_ogrid = [1.0 for i in range(len(self.theta))]
        for i, (tvar, theta) in \
            enumerate(zip(self.randomization.tvar_lst, self.theta)):
            if not isinstance(tvar, float):
                # get the size of the integration cell
                min_theta, max_theta, d_theta = self.get_theta_range(tvar)
                dG_ogrid[i] = tvar.pdf(theta) * d_theta
        return dG_ogrid
Exemple #2
0
class LatinHypercubeSampling(IrregularSampling):
    '''
        Latin hypercube sampling generated from the 
        samples of the individual random variables 
        with random perturbation.
    '''

    pi = Array(float)

    def _pi_default(self):
        return np.linspace(0.5 / self.n_sim, 1. - 0.5 / self.n_sim, self.n_sim)

    theta = Property(Array(float), depends_on='recalc')

    @cached_property
    def _get_theta(self):

        theta_list = []
        for tvar in self.randomization.tvar_lst:
            if isinstance(tvar, float):
                theta_list.append(tvar)
            else:
                # point probability function
                theta_arr = tvar.ppf(self.pi)
                theta_list.append(np.random.permutation(theta_arr))
        return theta_list
Exemple #3
0
class RV(HasTraits):
    '''Class representing the definition and discretization of a random variable.
    '''
    name = Str

    pd = Instance(IPDistrib)

    def _pd_changed(self):
        self.pd.n_segments = self._n_int

    changed = Event

    @on_trait_change('pd.changed')
    def _set_changed(self):
        self.changed = True

    _n_int = Int
    n_int = Property

    def _set_n_int(self, value):
        if self.pd:
            self.pd.n_segments = value
        self._n_int = value

    def _get_n_int(self):
        return self.pd.n_segments

    # index within the randomization
    idx = Int(0)

    theta_arr = Property(Array('float_'), depends_on='changed')

    @cached_property
    def _get_theta_arr(self):
        '''Get the discretization from pdistrib and shift it
        such that the midpoints of the segments are used for the
        integration.
        '''
        x_array = self.pd.x_array
        # Note assumption of equidistant discretization
        theta_array = x_array[:-1] + self.pd.dx / 2.0
        return theta_array

    pdf_arr = Property(Array('float_'), depends_on='changed')

    @cached_property
    def _get_pdf_arr(self):
        return self.pd.get_pdf_array(self.theta_arr)

    dG_arr = Property(Array('float_'), depends_on='changed')

    @cached_property
    def _get_dG_arr(self):
        d_theta = self.theta_arr[1] - self.theta_arr[0]
        return self.pdf_arr * d_theta

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

        if self.flag_ASC_file:
            for i, factor in enumerate(self.factor_list_ASC):
                self.add_trait(
                    factor,
                    Array(value=self.data_array_ASC[:, i], transient=True))
Exemple #5
0
class RegularGrid(RandomSampling):
    '''Grid shape randomization
    '''
    theta_list = Property(Array(float), depends_on='recalc')
    @cached_property
    def _get_theta_list(self):
        '''Get the orthogonally oriented arrays of random variables. 
        '''
        theta_list = []
        for tvar in self.randomization.tvar_lst:
            if isinstance(tvar, float):
                theta_list.append(tvar)
            elif isinstance(tvar, int):
                theta_list.append(float(tvar))
            elif isinstance(tvar, RV):
                theta_list.append(self.get_theta_for_distrib(tvar))
            else:
                raise TypeError, 'bad random variable specification: %s' % tvar

        return theta_list

    theta = Property(Array(float), depends_on='recalc')
    @cached_property
    def _get_theta(self):
        return make_ogrid(self.theta_list)

    dG = Property(Array(float), depends_on='recalc')
    @cached_property
    def _get_dG(self):
        if len(self.dG_ogrid) == 0:
            # deterministic case
            return 1.0
        else:
            # cross product of dG marginal values
            return reduce(lambda x, y: x * y, self.dG_ogrid)

    def get_samples(self, n):
        '''Get the fully expanded samples.
        '''
        # make the random permutation of the simulations and take n of them
        idx = np.random.permutation(np.arange(self.n_sim))[:n]
        # full orthogonalization (including scalars)
        otheta = make_ogrid_full(self.theta_list)
        # array of ones used for expansion
        oarray = np.ones(np.broadcast(*otheta).shape, dtype=float)
        # expand (broadcast), flatten and stack the arrays
        return np.vstack([ (t * oarray).flatten()[idx] for t in otheta ])
Exemple #6
0
class PGrid(RegularGrid):
    '''
        Regular grid of probabilities
    '''
    pi = Array(float)
    def _pi_default(self):
        n_int = self.randomization.n_int
        return np.linspace(0.5 / n_int,
                            1. - 0.5 / n_int, n_int)

    def get_theta_for_distrib(self, distrib):
        return distrib.ppf(self.pi)

    dG_ogrid = Property(Array(float), depends_on='recalc')
    @cached_property
    def _get_dG_ogrid(self):
        return np.repeat(1. / self.randomization.n_int, self.n_rand_vars)

    def _get_dG(self):
        return 1.0 / self.n_sim
Exemple #7
0
class ECBLPiecewiseLinear(ECBLBase):
    '''Effective crack bridge Law using a piecewise linear function.'''

    sig_level_arr = Array(float, input=True)

    def _sig_level_arr_default(self):
        E_eff = self.sig_tex_u / self.eps_tex_u
        return E_eff * self.eps_arr

    sig_tex_u = Float(800.0, input=True)
    eps_tex_u = Float(0.01, input=True)
    n_eps = Int(2, input=True)

    eps_fraction_arr = Property(depends_on='n_eps')

    @cached_property
    def _get_eps_fraction_arr(self):
        return np.linspace(0.0, 1.0, self.n_eps)

    cnames = ['eps_tex_u', 'sig_level_arr']

    u0 = Property(depends_on='eps_tex_u, sig_tex_u, eps_fraction_list')

    @cached_property
    def _get_u0(self):
        return self.sig_level_arr[1:]

    eps_arr = Array(float)

    def _eps_arr_default(self):
        return self.eps_fraction_arr * self.eps_tex_u

    sig_arr = Array(float)

    def _sig_arr_default(self):
        return self.sig_level_arr

    def set_sig_eps_arr(self, eps_arr, sig_arr):
        self.eps_arr = eps_arr
        self.sig_arr = sig_arr
Exemple #8
0
class IrregularSampling(RandomSampling):
    '''Irregular sampling based on Monte Carlo concept
    '''
    dG = Property(Array(float))
    @cached_property
    def _get_dG(self):
        return 1. / self.n_sim

    def get_samples(self, n):
        n = min(self.n_sim, n)
        idx = np.random.permutation(np.arange(self.n_sim))[:n]
        s_list = []
        for t in self.theta:
            if isinstance(t, np.ndarray):
                s_list.append(t[idx])
            else:
                s_list.append(np.repeat(t, n))
        return np.vstack(s_list)
class NDIdxInterp(HasTraits):

    # nd array of values (measured, computed..) of
    # size orthogonalize(axes_values)
    data = Array

    # list of control input parameter values
    axes_values = List(Array(float))

    def __call__(self, *gcoords, **kw):
        '''kw: dictionary of values to interpolate for;
        len(kw) has to be equal the data dimension
        '''
        order = kw.get('order', 1)
        mode = kw.get('mode', 'nearest')

        # check if the number of dimensions to interpolate
        # in equals the number of given coordinates
        if len(self.axes_values) != len(gcoords):
            raise TypeError('''method takes {req} arguments
            ({given} given)'''.format(req=len(self.axes_values),
                                      given=len(gcoords)))
        icoords = self.get_icoords(gcoords)

        # create a meshgrid for the interpolation
        icoords = orthogonalize_filled(icoords)
        data = self.data
        # interpolate the value (linear)
        # a, b, c = [0.5, 0.5, 0.5], [0, 0, 0], [0, 1, 2]
        # icoords = [a, b, c]
        val = ndimage.map_coordinates(data, icoords, order=order, mode=mode)
        return val

    def get_icoords(self, gcoords):
        '''
        gcoords: values to be interpolated for
        this method transforms the global coords to "index" coords
        '''
        icoords = [
            np.interp(gcoord, axis_values, np.arange(len(axis_values)))
            for gcoord, axis_values in zip(gcoords, self.axes_values)
        ]
        return icoords
Exemple #10
0
class MonteCarlo(IrregularSampling):
    '''
        Standard Monte Carlo randomization:
        For each variable generate n_sim = n_int ** n_rv 
        number of sampling points.
    '''

    theta = Property(Array(float), depends_on='recalc')
    @cached_property
    def _get_theta(self):

        theta_list = []
        for tvar in self.randomization.tvar_lst:
            if isinstance(tvar, types.FloatType):
                theta_list.append(tvar)
            else:
                theta_arr = tvar.rvs(self.n_sim)
                theta_list.append(theta_arr)
        return theta_list
Exemple #11
0
class GEOColumn( HasTraits ):

    h_col = Float( 3.00, unit = 'm' )
    X0 = Array( float, value = [ 4., 4., -3.0 ] )
    width_top = Float( 0.45, unit = 'm' )
    width_bottom = Float( 0.35, unit = 'm' )
    r_pipe = Float( 0.1, unit = 'm' )

    def __call__( self, points ):

        xi, yi, zi = points[:, 0], points[:, 1], points[:, 2]

        # grid from 0 to 1, shift origin for rotation
        # 
        xi -= 0.5
        yi -= 0.5

        # setting of global coordinates different width over h_col 
        # f_QS:
        #
        xi = ( ( self.width_top - self.width_bottom ) * zi + self.width_bottom ) * xi
        yi = ( ( self.width_top - self.width_bottom ) * zi + self.width_bottom ) * yi
        zi *= self.h_col

        # rotation of 45 with global coordinates
        #
        x = cos( pi / 4.0 ) * xi + sin( pi / 4.0 ) * yi
        y = -sin( pi / 4.0 ) * xi + cos( pi / 4.0 ) * yi
        z = zi + self.X0[2]

        # @TODO: kill element in the center of the columns:
        #shift of internal elements
        #
#        r_0 = where( ( xi ** 2 + yi ** 2 ) ** 0.5 >= self.r_pipe, self.r_pipe , ( xi ** 2 + yi ** 2 ) ** 0.5 )
#        scale_r = where ( r_0 == 0, 0, self.r_pipe / r_0 )
#        x = scale_r * x + self.X0[0]
#        y = scale_r * y + self.X0[1]

        x = x + self.X0[0]
        y = y + self.X0[1]
        return c_[x, y, z]
Exemple #12
0
class MRone(MushRoofModel):

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

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

    shift_elems = True

    vtk_r = Float(1.00)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        F_int = self.tloop.tstepper.F_int

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

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

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

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

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

    rtrace_list = List

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

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

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

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

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

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

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

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

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

        bc_plate_roof_link_list = slice_1 + slice_2 + slice_3 + slice_4 + slice_5

        return bc_plate_roof_link_list

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

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

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

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

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

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

        bc_roof_top_roof_low_link_list = slice_1 + slice_2 + slice_3 + slice_4 + slice_5

        return bc_roof_top_roof_low_link_list

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

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

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

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

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

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

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

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

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

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

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

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

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

        return constraint

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

        return tloop
Exemple #13
0
class PDistrib(HasTraits):

    implements = IPDistrib

    # puts all chosen continuous distributions distributions defined
    # in the scipy.stats.distributions module as a list of strings
    # into the Enum trait
    distr_choice = Enum(distr_enum)
    distr_dict = Dict(distr_dict)

    #    distr_choice = Enum('sin2x', 'weibull_min', 'sin_distr', 'uniform', 'norm')
    #    distr_dict = {'sin2x' : sin2x,
    #                  'uniform' : uniform,
    #                  'norm' : norm,
    #                  'weibull_min' : weibull_min,
    #                  'sin_distr' : sin_distr}

    # instantiating the continuous distributions
    distr_type = Property(Instance(Distribution), depends_on='distr_choice')

    @cached_property
    def _get_distr_type(self):
        return Distribution(self.distr_dict[self.distr_choice])

    # change monitor - accumulate the changes in a single event trait
    changed = Event

    @on_trait_change('distr_choice, distr_type.changed, quantile, n_segments')
    def _set_changed(self):
        self.changed = True

    # ------------------------------------------------------------------------
    # Methods setting the statistical modments
    # ------------------------------------------------------------------------
    mean = Property

    def _get_mean(self):
        return self.distr_type.mean

    def _set_mean(self, value):
        self.distr_type.mean = value

    variance = Property

    def _get_variance(self):
        return self.distr_type.mean

    def _set_variance(self, value):
        self.distr_type.mean = value

    # ------------------------------------------------------------------------
    # Methods preparing visualization
    # ------------------------------------------------------------------------

    quantile = Float(0.00001, auto_set=False, enter_set=True)
    range = Property(Tuple(Float), depends_on='distr_type.changed, quantile')

    @cached_property
    def _get_range(self):
        return (self.distr_type.distr.ppf(self.quantile),
                self.distr_type.distr.ppf(1 - self.quantile))

    n_segments = Int(500, auto_set=False, enter_set=True)

    dx = Property(Float, depends_on='distr_type.changed, quantile, n_segments')

    @cached_property
    def _get_dx(self):
        range_length = self.range[1] - self.range[0]
        return range_length / self.n_segments

    # -------------------------------------------------------------------------
    # Discretization of the distribution domain
    # -------------------------------------------------------------------------
    x_array = Property(Array('float_'),
                       depends_on='distr_type.changed,'
                       'quantile, n_segments')

    @cached_property
    def _get_x_array(self):
        '''Get the intrinsic discretization of the distribution
        respecting its  bounds.
        '''
        return linspace(self.range[0], self.range[1], self.n_segments + 1)

    # ===========================================================================
    # Access function to the scipy distribution
    # ===========================================================================
    def pdf(self, x):
        return self.distr_type.distr.pdf(x)

    def cdf(self, x):
        return self.distr_type.distr.cdf(x)

    def rvs(self, n):
        return self.distr_type.distr.rvs(n)

    def ppf(self, e):
        return self.distr_type.distr.ppf(e)

    # ===========================================================================
    # PDF - permanent array
    # ===========================================================================

    pdf_array = Property(Array('float_'),
                         depends_on='distr_type.changed,'
                         'quantile, n_segments')

    @cached_property
    def _get_pdf_array(self):
        '''Get pdf values in intrinsic positions'''
        return self.distr_type.distr.pdf(self.x_array)

    def get_pdf_array(self, x_array):
        '''Get pdf values in externally specified positions'''
        return self.distr_type.distr.pdf(x_array)

    # ===========================================================================
    # CDF permanent array
    # ===========================================================================
    cdf_array = Property(Array('float_'),
                         depends_on='distr_type.changed,'
                         'quantile, n_segments')

    @cached_property
    def _get_cdf_array(self):
        '''Get cdf values in intrinsic positions'''
        return self.distr_type.distr.cdf(self.x_array)

    def get_cdf_array(self, x_array):
        '''Get cdf values in externally specified positions'''
        return self.distr_type.distr.cdf(x_array)

    # -------------------------------------------------------------------------
    # Randomization
    # -------------------------------------------------------------------------
    def get_rvs_array(self, n_samples):
        return self.distr_type.distr.rvs(n_samples)
Exemple #14
0
class SPIRRID( Randomization ):

    #---------------------------------------------------------------------------------------------
    # Range of the control process variable epsilon
    # Define particular control variable points with
    # the cv array or an equidistant range with (min, max, n)
    #---------------------------------------------------------------------------------------------

    cv = Array( eps_range = True )
    min_eps = Float( 0.0, eps_range = True )
    max_eps = Float( 0.0, eps_range = True )
    n_eps = Float( 80, eps_range = True )

    eps_arr = Property( depends_on = 'eps_change' )
    @cached_property
    def _get_eps_arr( self ):

        # @todo: !!! 
        # This is a side-effect in a property - CRIME !! [rch]
        # No clear access interface points - naming inconsistent.
        # define a clean property with a getter and setter
        # 
        # if the array of control variable points is not given
        if len( self.cv ) == 0:

            n_eps = self.n_eps
            min_eps = self.min_eps
            max_eps = self.max_eps

            return linspace( min_eps, max_eps, n_eps )
        else:
            return self.cv

    #------------------------------------------------------------------------------------
    # Configuration of the algorithm
    #------------------------------------------------------------------------------------
    # 
    # cached_dG_grid:
    # If set to True, the cross product between the pdf values of all random variables
    # will be precalculated and stored in an n-dimensional grid
    # otherwise the product is performed for every epsilon in the inner loop anew
    # 
    cached_dG = Bool( True, alg_option = True )

    # compiled_eps_loop:
    # If set True, the loop over the control variable epsilon is compiled
    # otherwise, python loop is used.
    compiled_eps_loop = Bool( False, alg_option = True )

    # compiled_QdG_loop:
    # If set True, the integration loop over the product between the response function
    # and the pdf . theta product is performed in c
    # otherwise the numpy arrays are used.
    compiled_QdG_loop = Bool( False, alg_option = True )
    def _compiled_QdG_loop_changed( self ):
        '''If the inner loop is not compiled, the outer loop 
        must not be compiled as well.
        '''
        if self.compiled_QdG_loop == False:
            self.compiled_eps = False

    arg_list = Property( depends_on = 'rf_change, rand_change, conf_change' )
    @cached_property
    def _get_arg_list( self ):

        arg_list = []
        # create argument string for inline function
        if self.compiled_eps_loop:
            arg_list += [ 'mu_q_arr', 'e_arr' ]
        else:
            arg_list.append( 'e' )

        arg_list += ['%s_flat' % name for name in self.rv_keys ]

        if self.cached_dG:
            arg_list += [ 'dG_grid' ]
        else:
            arg_list += [ '%s_pdf' % name for name in self.rv_keys ]

        return arg_list

    dG_C_code = Property( depends_on = 'rf_change, rand_change, conf_change' )
    @cached_property
    def _get_dG_C_code( self ):
        if self.cached_dG: # q_g - blitz matrix used to store the grid
            code_str = '\tdouble pdf = dG_grid(' + \
                       ','.join( [ 'i_%s' % name
                                  for name in self.rv_keys ] ) + \
                       ');\n'
        else: # qg
            code_str = '\tdouble pdf = ' + \
                       '*'.join( [ ' *( %s_pdf + i_%s)' % ( name, name )
                                  for name in self.rv_keys ] ) + \
                       ';\n'
        return code_str

    #------------------------------------------------------------------------------------
    # Configurable generation of C-code for mean curve evaluation
    #------------------------------------------------------------------------------------
    C_code = Property( depends_on = 'rf_change, rand_change, conf_change, eps_change' )
    @cached_property
    def _get_C_code( self ):

        code_str = ''
        if self.compiled_eps_loop:

            # create code string for inline function
            #
            code_str += 'for( int i_eps = 0; i_eps < %g; i_eps++){\n' % self.n_eps

            if self.cached_dG:

                # multidimensional index needed for dG_grid 
                # blitz arrays must be used also for other arrays
                #
                code_str += 'double eps = e_arr( i_eps );\n'

            else:
                # pointer access possible for single dimensional arrays 
                # use the pointer arithmetics for accessing the pdfs
                code_str += '\tdouble eps = *( e_arr + i_eps );\n'

        else:

            # create code string for inline function
            #
            code_str += 'double eps = e;\n'

        code_str += 'double mu_q(0);\n'
        code_str += 'double q(0);\n'

        code_str += '#line 100\n'
        # create code for constant params
        for name, value in list(self.const_param_dict.items()):
            code_str += 'double %s = %g;\n' % ( name, value )

        # generate loops over random params

        for rv in self.rv_list:

            name = rv.name
            n_int = rv.n_int

            # create the loop over the random variable
            #
            code_str += 'for( int i_%s = 0; i_%s < %g; i_%s++){\n' % ( name, name, n_int, name )
            if self.cached_dG:

                # multidimensional index needed for pdf_grid - use blitz arrays
                #
                code_str += '\tdouble %s = %s_flat( i_%s );\n' % ( name, name, name )
            else:

                # pointer access possible for single dimensional arrays 
                # use the pointer arithmetics for accessing the pdfs
                code_str += '\tdouble %s = *( %s_flat + i_%s );\n' % ( name, name, name )

        if len( self.rv_keys ) > 0:
            code_str += self.dG_C_code
            code_str += self.rf.C_code + \
                       '// Store the values in the grid\n' + \
                       '\tmu_q +=  q * pdf;\n'
        else:
            code_str += self.rf.C_code + \
                       '\tmu_q += q;\n'

        # close the random loops
        #
        for name in self.rv_keys:
            code_str += '};\n'

        if self.compiled_eps_loop:
            if self.cached_dG: # blitz matrix
                code_str += 'mu_q_arr(i_eps) = mu_q;\n'
            else:
                code_str += '*(mu_q_arr + i_eps) = mu_q;\n'
            code_str += '};\n'
        else:
            code_str += 'return_val = mu_q;'
        return code_str

    compiler_verbose = Int( 0 )
    compiler = Str( 'gcc' )

    # Option of eval that induces the calculation of variation
    # in parallel with the mean value so that interim values of Q_grid 
    # are directly used for both.
    #
    implicit_var_eval = Bool( False, alg_option = True )

    def _eval( self ):
        '''Evaluate the integral based on the configuration of algorithm.
        '''
        if self.cached_dG == False and self.compiled_QdG_loop == False:
            raise NotImplementedError('Configuration for pure Python integration is too slow and is not implemented')

        self._set_compiler()
        # prepare the array of the control variable discretization
        #
        eps_arr = self.eps_arr
        mu_q_arr = zeros_like( eps_arr )

        # prepare the variable for the variance
        var_q_arr = None
        if self.implicit_var_eval:
            var_q_arr = zeros_like( eps_arr )

        # prepare the parameters for the compiled function in 
        # a separate dictionary
        c_params = {}

        if self.compiled_eps_loop:

            # for compiled eps_loop the whole input and output array must be passed to c
            #
            c_params['e_arr'] = eps_arr
            c_params['mu_q_arr'] = mu_q_arr
            #c_params['n_eps' ] = n_eps

        if self.compiled_QdG_loop:

            # prepare the lengths of the arrays to set the iteration bounds
            #
            for rv in self.rv_list:
                c_params[ '%s_flat' % rv.name ] = rv.theta_arr

        if len( self.rv_list ) > 0:
            if self.cached_dG:
                c_params[ 'dG_grid' ] = self.dG_grid
            else:
                for rv in self.rv_list:
                    c_params['%s_pdf' % rv.name] = rv.dG_arr
        else:
                c_params[ 'dG_grid' ] = self.dG_grid

        if self.cached_dG:
            conv = converters.blitz
        else:
            conv = converters.default

        t = time.clock()

        if self.compiled_eps_loop:

            # C loop over eps, all inner loops must be compiled as well
            #
            if self.implicit_var_eval:
                raise NotImplementedError('calculation of variance not available in the compiled version')

            inline( self.C_code, self.arg_list, local_dict = c_params,
                    type_converters = conv, compiler = self.compiler,
                    verbose = self.compiler_verbose )

        else:

            # Python loop over eps
            #
            for idx, e in enumerate( eps_arr ):

                if self.compiled_QdG_loop:

                    if self.implicit_var_eval:
                        raise NotImplementedError('calculation of variance not available in the compiled version')

                    # C loop over random dimensions
                    #
                    c_params['e'] = e # prepare the parameter
                    mu_q = inline( self.C_code, self.arg_list, local_dict = c_params,
                                   type_converters = conv, compiler = self.compiler,
                                   verbose = self.compiler_verbose )
                else:

                    # Numpy loops over random dimensions
                    #
                    # get the rf grid for all combinations of
                    # parameter values
                    #          
                    Q_grid = self.rf( e, **self.param_dict )

                    # multiply the response grid with the contributions
                    # of pdf distributions (weighted by the delta of the
                    # random variable disretization)
                    #

                    if not self.implicit_var_eval:
                        # only mean value needed, the multiplication can be done
                        # in-place
                        Q_grid *= self.dG_grid
                        # sum all the values to get the integral 
                        mu_q = sum( Q_grid )
                    else:
                        # get the square values of the grid
                        Q_grid2 = Q_grid ** 2
                        # make an inplace product of Q_grid with the weights
                        Q_grid *= self.dG_grid
                        # make an inplace product of the squared Q_grid with the weights
                        Q_grid2 *= self.dG_grid
                        # sum all values to get the mean
                        mu_q = sum( Q_grid )
                        # sum all squared values to get the variance
                        var_q = sum( Q_grid2 ) - mu_q ** 2

                # add the value to the return array
                mu_q_arr[idx] = mu_q

                if self.implicit_var_eval:
                    var_q_arr[idx] = var_q

        duration = time.clock() - t
        return  mu_q_arr, var_q_arr, duration

    def eval_i_dG_grid( self ):
        '''Get the integral of the pdf * theta grid.
        '''
        return sum( self.dG_grid )

    #---------------------------------------------------------------------------------------------
    # Output properties
    #---------------------------------------------------------------------------------------------

    # container for the data obtained in the integration
    #
    # This is not only the mean curve but also variance and 
    # execution statistics. Such an implementation 
    # concentrates the critical part of the algorithmic 
    # evaluation and avoids duplication of code and 
    # repeated calls. The results are cached in the tuple.
    # They are accessed by the convenience properties defined
    # below. 
    #  
    results = Property( depends_on = 'rand_change, conf_change, eps_change' )
    @cached_property
    def _get_results( self ):
        return self._eval()

    #---------------------------------------------------------------------------------------------
    # Output accessors
    #---------------------------------------------------------------------------------------------
    # the properties that access the cached results and give them a name

    mu_q_arr = Property()
    def _get_mu_q_arr( self ):
        '''mean of q at eps'''
        return self.results[0]

    var_q_arr = Property()
    def _get_var_q_arr( self ):
        '''variance of q at eps'''
        # switch on the implicit evaluation of variance 
        # if it has not been the case so far
        if not self.implicit_var_eval:
            self.implicit_var_eval = True

        return self.results[1]

    exec_time = Property()
    def _get_exec_time( self ):
        '''Execution time of the last evaluation.
        '''
        return self.results[2]

    mean_curve = Property()
    def _get_mean_curve( self ):
        '''Mean response curve.
        '''
        return MFnLineArray( xdata = self.eps_arr, ydata = self.mu_q_arr )

    var_curve = Property()
    def _get_var_curve( self ):
        '''variance of q at eps'''
        return MFnLineArray( xdata = self.eps_arr, ydata = self.var_q_arr )

    #---------------------------------------------------------------------------------------------
    # Auxiliary methods
    #---------------------------------------------------------------------------------------------
    def _set_compiler( self ):
        '''Catch eventual mismatch between scipy.weave and compiler 
        '''
        try:
            uname = os.uname()[3]
        except:
            # it is not Linux - just let it go and suffer
            return

        #if self.compiler == 'gcc':
            #os.environ['CC'] = 'gcc-4.1'
            #os.environ['CXX'] = 'g++-4.1'
            #os.environ['OPT'] = '-DNDEBUG -g -fwrapv -O3'

    traits_view = View( Item( 'rf@', show_label = False ),
                        width = 0.3, height = 0.3,
                        resizable = True,
                        scrollable = True,
                        )
Exemple #15
0
class SPIRRIDLAB(HasTraits):
    '''Class used for elementary parametric studies of spirrid.
    '''

    s = Instance(SPIRRID)

    evars = DelegatesTo('s')

    tvars = DelegatesTo('s')

    q = DelegatesTo('s')

    exact_arr = Array('float')

    dpi = Int

    plot_mode = Enum(['subplots', 'figures'])

    fig_output_dir = Directory('fig')

    @on_trait_change('fig_output_dir')
    def _check_dir(self):
        if os.access(self.fig_output_dir, os.F_OK) == False:
            os.mkdir(self.fig_output_dir)

    e_arr = Property

    def _get_e_arr(self):
        return self.s.evar_lst[0]

    hostname = Property

    def _get_hostname(self):
        return gethostname()

    qname = Str

    def get_qname(self):
        if self.qname == '':
            if isinstance(self.q, types.FunctionType):
                qname = self.q.__name__
            else:  # if isinstance(self.q, types.ClassType):
                qname = self.q.__class__.__name__
        else:
            qname = self.qname
        return qname

    show_output = False

    save_output = True

    plot_sampling_idx = Array(value=[0, 1], dtype=int)

    def _plot_sampling(self,
                       i,
                       n_col,
                       sampling_type,
                       p=p,
                       ylim=None,
                       xlim=None):
        '''Construct a spirrid object, run the calculation
        plot the mu_q / e curve and save it in the subdirectory.
        '''

        s = self.s
        s.sampling_type = sampling_type

        plot_idx = self.plot_sampling_idx

        qname = self.get_qname()

        # get n randomly selected realizations from the sampling
        theta = s.sampling.get_samples(500)
        tvar_x = s.tvar_lst[plot_idx[0]]
        tvar_y = s.tvar_lst[plot_idx[1]]
        min_x, max_x, d_x = s.sampling.get_theta_range(tvar_x)
        min_y, max_y, d_y = s.sampling.get_theta_range(tvar_y)
        # for vectorized execution add a dimension for control variable
        theta_args = [t[:, np.newaxis] for t in theta]
        q_arr = s.q(self.e_arr[None, :], *theta_args)
        if self.plot_mode == 'figures':
            f = p.figure(figsize=(7., 6.))
            f.subplots_adjust(left=0.15, right=0.97, bottom=0.15, top=0.92)
        if self.plot_mode == 'subplots':
            if i == 0:
                f = p.figure()
            p.subplot('2%i%i' % (n_col, (i + 1)))

        p.plot(theta[plot_idx[0]], theta[plot_idx[1]], 'o', color='grey')
        p.xlabel('$\lambda$')
        p.ylabel('$\\xi$')

        p.xlim(min_x, max_x)
        p.ylim(min_y, max_y)
        p.title(s.sampling_type)

        if self.save_output:
            fname = os.path.join(
                self.fig_output_dir,
                qname + '_sampling_' + s.sampling_type + '.png')
            p.savefig(fname, dpi=self.dpi)

        if self.plot_mode == 'figures':
            f = p.figure(figsize=(7., 5))
            f.subplots_adjust(left=0.15, right=0.97, bottom=0.18, top=0.91)
        elif self.plot_mode == 'subplots':
            p.subplot('2%i%i' % (n_col, (i + 5)))

        p.plot(self.e_arr, q_arr.T, color='grey')

        if len(self.exact_arr) > 0:
            p.plot(self.e_arr,
                   self.exact_arr,
                   label='exact solution',
                   color='black',
                   linestyle='--',
                   linewidth=2)

        # numerically obtained result
        p.plot(self.e_arr,
               s.mu_q_arr,
               label='numerical integration',
               linewidth=3,
               color='black')
        p.title(s.sampling_type)
        p.xlabel('$\\varepsilon$ [-]')
        p.ylabel(r'$q(\varepsilon;\, \lambda,\, \xi)$')
        if ylim:
            p.ylim(0.0, ylim)
        if xlim:
            p.xlim(0.0, xlim)
        p.xticks(position=(0, -.015))
        p.legend(loc=2)

        if self.save_output:
            fname = os.path.join(self.fig_output_dir,
                                 qname + '_' + s.sampling_type + '.png')
            p.savefig(fname, dpi=self.dpi)

    sampling_structure_btn = Button(label='compare sampling structure')

    @on_trait_change('sampling_structure_btn')
    def sampling_structure(self, **kw):
        '''Plot the response into the file in the fig subdirectory.
        '''
        if self.plot_mode == 'subplots':
            p.rcdefaults()
        else:
            fsize = 28
            p.rcParams['font.size'] = fsize
            rc('legend', fontsize=fsize - 8)
            rc('axes', titlesize=fsize)
            rc('axes', labelsize=fsize + 6)
            rc('xtick', labelsize=fsize - 8)
            rc('ytick', labelsize=fsize - 8)
            rc('xtick.major', pad=8)

        s_lst = ['TGrid', 'PGrid', 'MCS', 'LHS']

        for i, s in enumerate(s_lst):
            self._plot_sampling(i, len(s_lst), sampling_type=s, **kw)

        if self.show_output:
            p.show()

    n_int_range = Array()

    #===========================================================================
    # Output file names for sampling efficiency
    #===========================================================================
    fname_sampling_efficiency_time_nint = Property

    def _get_fname_sampling_efficiency_time_nint(self):
        return self.get_qname(
        ) + '_' + '%s' % self.hostname + '_time_nint' + '.png'

    fname_sampling_efficiency_error_nint = Property

    def _get_fname_sampling_efficiency_error_nint(self):
        return self.get_qname(
        ) + '_' + '%s' % self.hostname + '_error_nint' + '.png'

    fname_sampling_efficiency_error_time = Property

    def _get_fname_sampling_efficiency_error_time(self):
        return self.get_qname(
        ) + '_' + '%s' % self.hostname + '_error_time' + '.png'

    fnames_sampling_efficiency = Property

    def _get_fnames_sampling_efficiency(self):
        fnames = [self.fname_sampling_efficiency_time_nint]
        if len(self.exact_arr) > 0:
            fnames += [
                self.fname_sampling_efficiency_error_nint,
                self.fname_sampling_efficiency_error_time
            ]
        return fnames

    #===========================================================================
    # Run sampling efficiency studies
    #===========================================================================

    sampling_types = Array(value=['TGrid', 'PGrid', 'MCS', 'LHS'], dtype=str)

    sampling_efficiency_btn = Button(label='compare sampling efficiency')

    @on_trait_change('sampling_efficiency_btn')
    def sampling_efficiency(self):
        '''
        Run the code for all available sampling types.
        Plot the results.
        '''
        def run_estimation(n_int, sampling_type):
            # instantiate spirrid with samplingetization methods
            print 'running', sampling_type, n_int
            self.s.set(n_int=n_int, sampling_type=sampling_type)
            n_sim = self.s.sampling.n_sim
            exec_time = np.sum(self.s.exec_time)
            return self.s.mu_q_arr, exec_time, n_sim

        # vectorize the estimation to accept arrays
        run_estimation_vct = np.vectorize(run_estimation, [object, float, int])

        #===========================================================================
        # Generate the inspected domain of input parameters using broadcasting
        #===========================================================================

        run_estimation_vct([5], ['PGrid'])

        sampling_types = self.sampling_types
        sampling_colors = np.array(
            ['grey', 'black', 'grey', 'black'],
            dtype=str)  # 'blue', 'green', 'red', 'magenta'
        sampling_linestyle = np.array(['--', '--', '-', '-'], dtype=str)

        # run the estimation on all combinations of n_int and sampling_types
        mu_q, exec_time, n_sim_range = run_estimation_vct(
            self.n_int_range[:, None], sampling_types[None, :])

        p.rcdefaults()
        f = p.figure(figsize=(12, 6))
        f.subplots_adjust(left=0.06, right=0.94)

        #===========================================================================
        # Plot the results
        #===========================================================================
        p.subplot(1, 2, 1)
        p.title('response for %d $n_\mathrm{sim}$' % n_sim_range[-1, -1])
        for i, (sampling, color, linestyle) in enumerate(
                zip(sampling_types, sampling_colors, sampling_linestyle)):
            p.plot(self.e_arr,
                   mu_q[-1, i],
                   color=color,
                   label=sampling,
                   linestyle=linestyle)

        if len(self.exact_arr) > 0:
            p.plot(self.e_arr,
                   self.exact_arr,
                   color='black',
                   label='Exact solution')

        p.legend(loc=1)
        p.xlabel('e', fontsize=18)
        p.ylabel('q', fontsize=18)

        # @todo: get n_sim - x-axis
        p.subplot(1, 2, 2)
        for i, (sampling, color, linestyle) in enumerate(
                zip(sampling_types, sampling_colors, sampling_linestyle)):
            p.loglog(n_sim_range[:, i],
                     exec_time[:, i],
                     color=color,
                     label=sampling,
                     linestyle=linestyle)

        p.legend(loc=2)
        p.xlabel('$n_\mathrm{sim}$', fontsize=18)
        p.ylabel('$t$ [s]', fontsize=18)

        if self.save_output:
            basename = self.fname_sampling_efficiency_time_nint
            fname = os.path.join(self.fig_output_dir, basename)
            p.savefig(fname, dpi=self.dpi)

        #===========================================================================
        # Evaluate the error
        #===========================================================================

        if len(self.exact_arr) > 0:
            er = ErrorEval(exact_arr=self.exact_arr)

            def eval_error(mu_q, error_measure):
                return error_measure(mu_q)

            eval_error_vct = np.vectorize(eval_error)

            error_measures = np.array(
                [er.eval_error_max, er.eval_error_energy, er.eval_error_rms])
            error_table = eval_error_vct(mu_q[:, :, None],
                                         error_measures[None, None, :])

            f = p.figure(figsize=(14, 6))
            f.subplots_adjust(left=0.07, right=0.97, wspace=0.26)

            p.subplot(1, 2, 1)
            p.title('max rel. lack of fit')
            for i, (sampling, color, linestyle) in enumerate(
                    zip(sampling_types, sampling_colors, sampling_linestyle)):
                p.loglog(n_sim_range[:, i],
                         error_table[:, i, 0],
                         color=color,
                         label=sampling,
                         linestyle=linestyle)

            #p.ylim( 0, 10 )
            p.legend()
            p.xlabel('$n_\mathrm{sim}$', fontsize=18)
            p.ylabel('$\mathrm{e}_{\max}$ [-]', fontsize=18)

            p.subplot(1, 2, 2)
            p.title('rel. root mean square error')
            for i, (sampling, color, linestyle) in enumerate(
                    zip(sampling_types, sampling_colors, sampling_linestyle)):
                p.loglog(n_sim_range[:, i],
                         error_table[:, i, 2],
                         color=color,
                         label=sampling,
                         linestyle=linestyle)
            p.legend()
            p.xlabel('$n_{\mathrm{sim}}$', fontsize=18)
            p.ylabel('$\mathrm{e}_{\mathrm{rms}}$ [-]', fontsize=18)

            if self.save_output:
                basename = self.fname_sampling_efficiency_error_nint
                fname = os.path.join(self.fig_output_dir, basename)
                p.savefig(fname, dpi=self.dpi)

            f = p.figure(figsize=(14, 6))
            f.subplots_adjust(left=0.07, right=0.97, wspace=0.26)

            p.subplot(1, 2, 1)
            p.title('rel. max lack of fit')
            for i, (sampling, color, linestyle) in enumerate(
                    zip(sampling_types, sampling_colors, sampling_linestyle)):
                p.loglog(exec_time[:, i],
                         error_table[:, i, 0],
                         color=color,
                         label=sampling,
                         linestyle=linestyle)
            p.legend()
            p.xlabel('time [s]', fontsize=18)
            p.ylabel('$\mathrm{e}_{\max}$ [-]', fontsize=18)

            p.subplot(1, 2, 2)
            p.title('rel. root mean square error')
            for i, (sampling, color, linestyle) in enumerate(
                    zip(sampling_types, sampling_colors, sampling_linestyle)):
                p.loglog(exec_time[:, i],
                         error_table[:, i, 2],
                         color=color,
                         label=sampling,
                         linestyle=linestyle)
            p.legend()
            p.xlabel('time [s]', fontsize=18)
            p.ylabel('$\mathrm{e}_{\mathrm{rms}}$ [-]', fontsize=18)

            if self.save_output:
                basename = self.fname_sampling_efficiency_error_time
                fname = os.path.join(self.fig_output_dir, basename)
                p.savefig(fname, dpi=self.dpi)

        if self.show_output:
            p.show()

    #===========================================================================
    # Efficiency of numpy versus C code
    #===========================================================================
    run_lst_detailed_config = Property(List)

    def _get_run_lst_detailed_config(self):
        run_lst = []
        if hasattr(self.q, 'c_code'):
            run_lst += [
                #                ('c',
                #                 {'cached_dG'         : True,
                #                  'compiled_eps_loop' : True },
                #                  'go-',
                #                  '$\mathsf{C}_{\\varepsilon} \{\, \mathsf{C}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\}\,\} $ - %4.2f sec',
                #                  ),
                #                ('c',
                #                 {'cached_dG'         : True,
                #                  'compiled_eps_loop' : False },
                #                 'r-2',
                #                 '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{C}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\}\,\} $ - %4.2f sec'
                #                 ),
                #                ('c',
                #                 {'cached_dG'         : False,
                #                  'compiled_eps_loop' : True },
                #                 'r-2',
                #                 '$\mathsf{C}_{\\varepsilon} \{\, \mathsf{C}_{\\theta} \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\}\,\} $ - %4.2f sec'
                #                 ),
                (
                    'c',
                    {
                        'cached_dG': False,
                        'compiled_eps_loop': False
                    },
                    'bx-',
                    '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{C}_{\\theta}  \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\} \,\} $ - %4.2f sec',
                )
            ]
        if hasattr(self.q, 'cython_code'):
            run_lst += [
                #                ('cython',
                #                 {'cached_dG'         : True,
                #                  'compiled_eps_loop' : True },
                #                  'go-',
                #                  '$\mathsf{Cython}_{\\varepsilon} \{\, \mathsf{Cython}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\}\,\} $ - %4.2f sec',
                #                  ),
                #                ('cython',
                #                 {'cached_dG'         : True,
                #                  'compiled_eps_loop' : False },
                #                 'r-2',
                #                 '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{Cython}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\}\,\} $ - %4.2f sec'
                #                 ),
                #                ('cython',
                #                 {'cached_dG'         : False,
                #                  'compiled_eps_loop' : True },
                #                 'r-2',
                #                 '$\mathsf{Cython}_{\\varepsilon} \{\, \mathsf{Cython}_{\\theta} \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\}\,\} $ - %4.2f sec'
                #                 ),
                #                ('cython',
                #                 {'cached_dG'         : False,
                #                  'compiled_eps_loop' : False },
                #                  'bx-',
                #                  '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{Cython}_{\\theta}  \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\} \,\} $ - %4.2f sec',
                #                 )
            ]
        if hasattr(self.q, '__call__'):
            run_lst += [
                #                ('numpy',
                #                 {},
                #                 'y--',
                #                 '$\mathsf{Python}_{\\varepsilon} \{\,  \mathsf{Numpy}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\} \,\} $ - %4.2f sec'
                #                 )
            ]
        return run_lst

    # number of recalculations to get new time.
    n_recalc = Int(2)

    def codegen_efficiency(self):
        # define a tables with the run configurations to start in a batch

        basenames = []

        qname = self.get_qname()

        s = self.s

        legend = []
        legend_lst = []
        time_lst = []
        p.figure()

        for idx, run in enumerate(self.run_lst_detailed_config):
            code, run_options, plot_options, legend_string = run
            s.codegen_type = code
            s.codegen.set(**run_options)
            print 'run', idx, run_options

            for i in range(self.n_recalc):
                s.recalc = True  # automatically proagated within spirrid
                print 'execution time', s.exec_time

            p.plot(s.evar_lst[0], s.mu_q_arr, plot_options)

            # @todo: this is not portable!!
            #legend.append(legend_string % s.exec_time)
            #legend_lst.append(legend_string[:-12])
            time_lst.append(s.exec_time)

        p.xlabel('strain [-]')
        p.ylabel('stress')
        #p.legend(legend, loc = 2)
        p.title(qname)

        if self.save_output:
            print 'saving codegen_efficiency'
            basename = qname + '_' + 'codegen_efficiency' + '.png'
            basenames.append(basename)
            fname = os.path.join(self.fig_output_dir, basename)
            p.savefig(fname, dpi=self.dpi)

        self._bar_plot(legend_lst, time_lst)
        p.title('%s' % s.sampling_type)
        if self.save_output:
            basename = qname + '_' + 'codegen_efficiency_%s' % s.sampling_type + '.png'
            basenames.append(basename)
            fname = os.path.join(self.fig_output_dir, basename)
            p.savefig(fname, dpi=self.dpi)

        if self.show_output:
            p.show()

        return basenames

    #===========================================================================
    # Efficiency of numpy versus C code
    #===========================================================================
    run_lst_language_config = Property(List)

    def _get_run_lst_language_config(self):
        run_lst = []
        if hasattr(self.q, 'c_code'):
            run_lst += [(
                'c',
                {
                    'cached_dG': False,
                    'compiled_eps_loop': False
                },
                'bx-',
                '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{C}_{\\theta}  \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\} \,\} $ - %4.2f sec',
            )]
        if hasattr(self.q, 'cython_code'):
            run_lst += [(
                'cython',
                {
                    'cached_dG': False,
                    'compiled_eps_loop': False
                },
                'bx-',
                '$\mathsf{Python} _{\\varepsilon} \{\, \mathsf{Cython}_{\\theta}  \{\, q(\\varepsilon,\\theta) \cdot g[\\theta_1] \cdot \ldots \cdot g[\\theta_m] \,\} \,\} $ - %4.2f sec',
            )]
        if hasattr(self.q, '__call__'):
            run_lst += [(
                'numpy', {}, 'y--',
                '$\mathsf{Python}_{\\varepsilon} \{\,  \mathsf{Numpy}_{\\theta} \{\,  q(\\varepsilon,\\theta) \cdot G[\\theta] \,\} \,\} $ - %4.2f sec'
            )]
        return run_lst

    extra_compiler_args = Bool(True)
    le_sampling_lst = List(['LHS', 'PGrid'])
    le_n_int_lst = List([440, 5000])

    #===========================================================================
    # Output file names for language efficiency
    #===========================================================================
    fnames_language_efficiency = Property

    def _get_fnames_language_efficiency(self):
        return [
            '%s_codegen_efficiency_%s_extra_%s.png' %
            (self.qname, self.hostname, extra)
            for extra in [self.extra_compiler_args]
        ]

    language_efficiency_btn = Button(label='compare language efficiency')

    @on_trait_change('language_efficiency_btn')
    def codegen_language_efficiency(self):
        # define a tables with the run configurations to start in a batch

        home_dir = expanduser("~")

        #        pyxbld_dir = os.path.join(home_dir, '.pyxbld')
        #        if os.path.exists(pyxbld_dir):
        #            shutil.rmtree(pyxbld_dir)

        python_compiled_dir = os.path.join(home_dir, '.python27_compiled')
        if os.path.exists(python_compiled_dir):
            shutil.rmtree(python_compiled_dir)

        for extra, fname in zip([self.extra_compiler_args],
                                self.fnames_language_efficiency):
            print 'extra compilation args:', extra
            legend_lst = []
            error_lst = []
            n_sim_lst = []
            exec_times_sampling = []

            meth_lst = zip(self.le_sampling_lst, self.le_n_int_lst)
            for item, n_int in meth_lst:
                print 'sampling method:', item
                s = self.s
                s.exec_time  # eliminate first load time delay (first column)
                s.n_int = n_int
                s.sampling_type = item
                exec_times_lang = []

                for idx, run in enumerate(self.run_lst_language_config):
                    code, run_options, plot_options, legend_string = run

                    #os.system('rm -fr ~/.python27_compiled')

                    s.codegen_type = code
                    s.codegen.set(**run_options)
                    if s.codegen_type == 'c':
                        s.codegen.set(**dict(use_extra=extra))
                    print 'run', idx, run_options

                    exec_times_run = []
                    for i in range(self.n_recalc):
                        s.recalc = True  # automatically propagated
                        exec_times_run.append(s.exec_time)
                        print 'execution time', s.exec_time

                    legend_lst.append(legend_string[:-12])
                    if s.codegen_type == 'c':
                        # load weave.inline time from tmp file and fix values in time_arr
                        #@todo - does not work on windows
                        import tempfile
                        tdir = tempfile.gettempdir()
                        f = open(os.path.join(tdir, 'w_time'), 'r')
                        value_t = float(f.read())
                        f.close()
                        exec_times_run[0][1] = value_t
                        exec_times_run[0][2] -= value_t
                        exec_times_lang.append(exec_times_run)
                    else:
                        exec_times_lang.append(exec_times_run)

                print 'legend_lst', legend_lst
                n_sim_lst.append(s.sampling.n_sim)
                exec_times_sampling.append(exec_times_lang)
                #===========================================================================
                # Evaluate the error
                #===========================================================================
                if len(self.exact_arr) > 0:
                    er = ErrorEval(exact_arr=self.exact_arr)
                    error_lst.append((er.eval_error_rms(s.mu_q_arr),
                                      er.eval_error_max(s.mu_q_arr)))

            times_arr = np.array(exec_times_sampling, dtype='d')
            self._multi_bar_plot(meth_lst, legend_lst, times_arr, error_lst,
                                 n_sim_lst)
            if self.save_output:
                fname_path = os.path.join(self.fig_output_dir, fname)
                p.savefig(fname_path, dpi=self.dpi)

        if self.show_output:
            p.show()

    def combination_efficiency(self, tvars_det, tvars_rand):
        '''
        Run the code for all available random parameter combinations.
        Plot the results.
        '''
        qname = self.get_qname()

        s = self.s
        s.set(sampling_type='TGrid')

        # list of all combinations of response function parameters
        rv_comb_lst = list(powerset(s.tvars.keys()))

        p.figure()
        exec_time_lst = []

        for id, rv_comb in enumerate(rv_comb_lst[163:219]):  # [1:-1]
            s.tvars = tvars_det
            print 'Combination', rv_comb

            for rv in rv_comb:
                s.tvars[rv] = tvars_rand[rv]

            #legend = []
            #p.figure()
            time_lst = []
            for idx, run in enumerate(self.run_lst):
                code, run_options, plot_options, legend_string = run
                print 'run', idx, run_options
                s.codegen_type = code
                s.codegen.set(**run_options)

                #p.plot(s.evar_lst[0], s.mu_q_arr, plot_options)

                #print 'integral of the pdf theta', s.eval_i_dG_grid()
                print 'execution time', s.exec_time
                time_lst.append(s.exec_time)
                #legend.append(legend_string % s.exec_time)
            exec_time_lst.append(time_lst)
        p.plot(np.array((1, 2, 3, 4)), np.array(exec_time_lst).T)
        p.xlabel('method')
        p.ylabel('time')

        if self.save_output:
            print 'saving codegen_efficiency'
            fname = os.path.join(
                self.fig_output_dir,
                qname + '_' + 'combination_efficiency' + '.png')
            p.savefig(fname, dpi=self.dpi)

        if self.show_output:
            p.title(s.q.title)
            p.show()

    def _bar_plot(self, legend_lst, time_lst):
        rc('font', size=15)
        #rc('font', family = 'serif', style = 'normal', variant = 'normal', stretch = 'normal', size = 15)
        fig = p.figure(figsize=(10, 5))

        n_tests = len(time_lst)
        times = np.array(time_lst)
        x_norm = times[1]
        xmax = times.max()
        rel_xmax = xmax / x_norm
        rel_times = times / x_norm
        m = int(rel_xmax % 10)

        if m < 5:
            x_max_plt = int(rel_xmax) - m + 10
        else:
            x_max_plt = int(rel_xmax) - m + 15

        ax1 = fig.add_subplot(111)
        p.subplots_adjust(left=0.45, right=0.88)
        #fig.canvas.set_window_title('window title')
        pos = np.arange(n_tests) + 0.5
        rects = ax1.barh(pos,
                         rel_times,
                         align='center',
                         height=0.5,
                         color='w',
                         edgecolor='k')

        ax1.set_xlabel('normalized execution time [-]')
        ax1.axis([0, x_max_plt, 0, n_tests])
        ax1.set_yticks(pos)
        ax1.set_yticklabels(legend_lst)

        for rect, t in zip(rects, rel_times):
            width = rect.get_width()

            xloc = width + (0.03 * rel_xmax)
            clr = 'black'
            align = 'left'

            yloc = rect.get_y() + rect.get_height() / 2.0
            ax1.text(xloc,
                     yloc,
                     '%4.2f' % t,
                     horizontalalignment=align,
                     verticalalignment='center',
                     color=clr)  #, weight = 'bold')

        ax2 = ax1.twinx()
        ax1.plot([1, 1], [0, n_tests], 'k--')
        ax2.set_yticks([0] + list(pos) + [n_tests])
        ax2.set_yticklabels([''] + ['%4.2f s' % s for s in list(times)] + [''])
        ax2.set_xticks([0, 1] + range(5, x_max_plt + 1, 5))
        ax2.set_xticklabels(
            ['%i' % s for s in ([0, 1] + range(5, x_max_plt + 1, 5))])

    def _multi_bar_plot(self, title_lst, legend_lst, time_arr, error_lst,
                        n_sim_lst):
        '''Plot the results if the code efficiency. 
        '''
        p.rcdefaults()
        fsize = 14
        fig = p.figure(figsize=(15, 3))
        rc('font', size=fsize)
        rc('legend', fontsize=fsize - 2)
        legend_lst = ['weave', 'cython', 'numpy']

        # times are stored in 3d array - dimensions are:
        n_sampling, n_lang, n_run, n_times = time_arr.shape
        print 'arr', time_arr.shape
        times_sum = np.sum(time_arr, axis=n_times)

        p.subplots_adjust(left=0.1,
                          right=0.95,
                          wspace=0.1,
                          bottom=0.15,
                          top=0.8)

        for meth_i in range(n_sampling):

            ax1 = fig.add_subplot(1, n_sampling, meth_i + 1)
            ax1.set_xlabel('execution time [s]')
            ytick_pos = np.arange(n_lang) + 1

            #        ax1.axis([0, x_max_plt, 0, n_lang])
            # todo: **2 n_vars
            if len(self.exact_arr) > 0:
                ax1.set_title(
                    '%s: $ n_\mathrm{sim} = %s, \mathrm{e}_\mathrm{rms}=%s, \mathrm{e}_\mathrm{max}=%s$'
                    % (title_lst[meth_i][0],
                       self._formatSciNotation('%.2e' % n_sim_lst[meth_i]),
                       self._formatSciNotation('%.2e' % error_lst[meth_i][0]),
                       self._formatSciNotation('%.2e' % error_lst[meth_i][1])))
            else:
                ax1.set_title(
                    '%s: $ n_\mathrm{sim} = %s$' %
                    (title_lst[meth_i][0],
                     self._formatSciNotation('%.2e' % n_sim_lst[meth_i])))
            ax1.set_yticks(ytick_pos)
            if meth_i == 0:
                ax1.set_yticklabels(legend_lst, fontsize=fsize + 2)
            else:
                ax1.set_yticklabels([])

            ax1.set_xlim(0, 1.2 * np.max(times_sum[meth_i]))

            distance = 0.2
            height = 1.0 / n_run - distance
            offset = height / 2.0

            colors = ['w', 'w', 'w', 'r', 'y', 'b', 'g', 'm']
            hatches = ['/', '\\', 'x', '-', '+', '|', 'o', 'O', '.', '*']
            label_lst = ['sampling', 'compilation', 'integration']

            for i in range(n_run):
                pos = np.arange(n_lang) + 1 - offset + i * height
                end_bar_pos = np.zeros((n_lang, ), dtype='d')
                for j in range(n_times):
                    if i > 0:
                        label = label_lst[j]
                    else:
                        label = None
                    bar_lengths = time_arr[meth_i, :, i, j]
                    rects = ax1.barh(pos,
                                     bar_lengths,
                                     align='center',
                                     height=height,
                                     left=end_bar_pos,
                                     color=colors[j],
                                     edgecolor='k',
                                     hatch=hatches[j],
                                     label=label)
                    end_bar_pos += bar_lengths
                for k in range(n_lang):
                    x_val = times_sum[meth_i, k,
                                      i] + 0.01 * np.max(times_sum[meth_i])
                    ax1.text(x_val,
                             pos[k],
                             '$%4.2f\,$s' % x_val,
                             horizontalalignment='left',
                             verticalalignment='center',
                             color='black')  #, weight = 'bold')
                    if meth_i == 0:
                        ax1.text(0.02 * np.max(times_sum[0]),
                                 pos[k],
                                 '$%i.$' % (i + 1),
                                 horizontalalignment='left',
                                 verticalalignment='center',
                                 color='black',
                                 bbox=dict(pad=0., ec="w", fc="w"))
            p.legend(loc=0)

    def _formatSciNotation(self, s):
        # transform 1e+004 into 1e4, for example
        tup = s.split('e')
        try:
            significand = tup[0].rstrip('0').rstrip('.')
            sign = tup[1][0].replace('+', '')
            exponent = tup[1][1:].lstrip('0')
            if significand == '1':
                # reformat 1x10^y as 10^y
                significand = ''
            if exponent:
                exponent = '10^{%s%s}' % (sign, exponent)
            if significand and exponent:
                return r'%s{\cdot}%s' % (significand, exponent)
            else:
                return r'%s%s' % (significand, exponent)

        except IndexError, msg:
            return s
Exemple #16
0
class HPShell(HasTraits):
    '''Geometry definition of a hyperbolic parabolid shell.
    '''

    #-----------------------------------------------------------------
    # geometric parameters of the shell
    #-----------------------------------------------------------------

    # dimensions of the shell for one quarter of mush_roof
    #
    length_xy_quarter = Float(3.5, input=True)  # [m]
    length_z = Float(0.927, input=True)  # [m]

    # corresponds to the delta in the geometry .obj-file with name '4x4m' as a cut off
    #
    delta_h = Float(0.865, input=True)  # [m]

    # scale factors for geometric dimensions
    # NOTE: parameters can be scaled separately, i.e. scaling of 'delta_h' (inclination of the shell)
    # does not effect the scaling of the thickness
    #
    scalefactor_delta_h = Float(1.00, input=True)  # [-]
    scalefactor_length_xy = Float(1.00, input=True)  # [-]

    # thickness of the shell
    # NOTE: only used by the option 'const_reinf_layer'
    #
    t_shell = Float(0.06, input=True)  # [m]

    width_top_col = Float(0.45, input=True)  # [m]

    # factor shifting the z coordinates at the middle nodes of the edges upwards
    # in order to include the effect of imperfection in the formwork
    z_imperfection_factor = Float(0.0)

    #-----------------------------------------------------------------
    # specify the relation of the total structure (in the 'mushroof'-model)
    # with respect to a quarter of one shell defined in 'HPShell'
    #-----------------------------------------------------------------

    # @todo: "four" is not supported by "n_elems_xy_dict"in mushroff_model
    mushroof_part = Enum('one', 'quarter', 'four', input=True)

    # 'scale_size' parameter is used as scale factor for different mushroof parts
    # Defines the proportion between the length of the total model
    # with respect to the length of a quarter shell as the
    # basic substructure of which the model consists of.
    # @todo: add "depends_on" or remove "cached_property"
    # @todo: move to class definition of "mushroof_model" not in "HPShell"
    #        (also see there "n_elems_dict" with implicit "scale_factor")
    #
    scale_size = Property(Float, depends_on='mushroof_part')

    @cached_property
    def _get_scale_size(self):
        scale_dict = {'quarter': 1.0, 'one': 2.0, 'four': 4.0}
        return scale_dict[self.mushroof_part]

    # origin of the shell
    #
    X0 = Array(float, input=True)

    def _X0_default(self):
        return array([0., 0., 0.])

    #-----------------------------------------------------------------
    # discretisation
    #-----------------------------------------------------------------

    # number of element used for the discretisation ( dimensions of the entire model)
    #
    n_elems_xy_quarter = Int(5, input=True)
    n_elems_z = Int(3, input=True)

    n_elems_xy = Property(Int, depends_on='n_elems_xy_quarter, +input')

    @cached_property
    def _get_n_elems_xy(self):
        return self.n_elems_xy_quarter * self.scale_size

    #-----------------------------------------------------------------
    # option: 'shift_elems'
    #-----------------------------------------------------------------

    # shift of column elements
    # if set to "True" (default) the information defined in 'shift_array' is used.
    #
    shift_elems = Bool(True, input=True)

    # 'shift_array' is used to place element corners at a defined global
    # position in order to connect the shell with the corner nodes of the column.
    # [x_shift, y_shift, number of element s between the coordinate position]
    # NOTE: 'shift_array' needs to have shape (:,3)!
    #
    shift_array = Array(float, input=True)

    def _shift_array_default(self):
        return array(
            [[self.width_top_col / 2**0.5, self.width_top_col / 2**0.5, 1]])

    #-----------------------------------------------------------------
    # option: 'const_reinf_layer'
    #-----------------------------------------------------------------
    # 'const_reinf_layer' - parameter is used only for the non-linear analysis,
    # where an element layer with a constant thickness is needed to simulate the
    # reinforced concrete at the top and bottom of the TRC-shell.
    #
    const_reinf_layer_elem = Bool(False, input=True)
    t_reinf_layer = Float(0.03, input=True)  # [m]
    n_elems_reinf_layer = Int(
        1, input=True)  #number of dofs used for edge refinement

    #-----------------------------------------------------------------
    # read vertice points of the shell and derive a normalized
    # RBF-function for the shell approximation
    #-----------------------------------------------------------------

    # "lowerface_cut_off" - option replaces constant height for the coordinates
    # which connect to the column (this cuts of the shell geometry horizontally
    # at the bottom of the lower face of the shell geometry.
    #
    cut_off_lowerface = Bool(True, input=True)

    # choose geometric file (obj-data file)
    #
    geo_input_name = Enum('350x350cm', '4x4m', '02', input=True)

    # filter for '4x4m' file needs to be done to have regular grid
    # in order to rbf-function leading to stable solution without oscilation
    #
    geo_filter = Dict({'4x4m': delete_second_rows})

    #                        ,'350x350cm' : delete_second_rows} )

    def _read_arr(self, side='lowerface_'):
        '''read the robj-file saved in the subdirectory 
        'geometry_files'
        '''
        file_name = side + self.geo_input_name + '.robj'
        file_path = join('geometry_files', file_name)
        # get an array with the vertice coordinates
        #
        v_arr = read_rsurface(file_path)
        #        print 'v_arr before filtering \n', v_arr
        #        print 'v_arr.shape before filtering \n', v_arr.shape
        filter = self.geo_filter.get(self.geo_input_name, None)
        if filter != None:
            v_arr = filter(v_arr)


#        print 'v_arr after filtering \n', v_arr
#        print 'v_arr.shape after filtering \n', v_arr.shape
        return v_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the lower surface of the shell
    #
    vl_arr = Property(Array(float), depends_on='geo_input_name')

    @cached_property
    def _get_vl_arr(self):
        vl_arr = self._read_arr('lowerface_')
        if self.cut_off_lowerface == True:
            print '--- lower face z-coords cut off ---'

            # z-values of the coords from the lower face are cut off.
            # From the highest z-coordinate of the lower face the vertical
            # distance is 'delta h (for 4x4m: delta_h = 1.0m).
            # At this limit the lower face is cut off.
            # NOTE: the global z coordinate is assumed to point up
            # and must be given in the same unite as 'delta_h', i.e. in [m].
            #
            vl_z_max = max(vl_arr[:, 2])
            if self.geo_input_name == '4x4m':
                # NOTE: the global z-coordinates are given in the geo data file in [m]
                # no conversion of unites necessary (self.delta_h is given in [m])
                delta_h = self.delta_h
            elif self.geo_input_name == '350x350cm':
                # NOTE: the global z-coordinates are given in the geo data file in [cm]
                # convert delta_h from [m] to [cm]
                #
                delta_h = self.delta_h * 100.
            vl_z_min = vl_z_max - delta_h
            vl_arr_z = where(vl_arr[:, 2] < vl_z_min, vl_z_min, vl_arr[:, 2])
            vl_arr = c_[vl_arr[:, 0:2], vl_arr_z]

        return vl_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the upper surface of the shell
    #
    vu_arr = Property(Array(float), depends_on='geo_input_name')

    @cached_property
    def _get_vu_arr(self):
        return self._read_arr('upperface_')

    # normalized coordinates of the vertices for the lowerface
    # NOTE: the underline character indicates a normalized value
    # @todo: 'normalize_rsurfaces' is called twice for 'vl_arr_' and 'vu_arr_'
    #
    vl_arr_ = Property(Array(float), depends_on='geo_input_name')

    @cached_property
    def _get_vl_arr_(self):
        vl_arr_, vu_arr_ = normalize_rsurfaces(self.vl_arr, self.vu_arr)
        return vl_arr_

    # normalized coordinates of the vertices for the lowerface
    # NOTE: the underline character indicates a normalized value
    #
    vu_arr_ = Property(Array(float), depends_on='geo_input_name')

    @cached_property
    def _get_vu_arr_(self):
        vl_arr_, vu_arr_ = normalize_rsurfaces(self.vl_arr, self.vu_arr)
        return vu_arr_

    rbf_l_ = Property(Instance(Rbf), depends_on='geo_input_name')

    @cached_property
    def _get_rbf_l_(self):
        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the lower face
        #
        xl_ = self.vl_arr_[:, 0]
        yl_ = self.vl_arr_[:, 1]
        zl_ = self.vl_arr_[:, 2]

        # flip the orientation of the local coordinate axis
        # depending on the geometry file used
        #
        if self.geo_input_name == '350x350cm':
            xl_ = 1 - self.vl_arr_[:, 0]
        if self.geo_input_name == '4x4m':
            yl_ = 1 - self.vl_arr_[:, 1]

        rbf_l_ = Rbf(xl_, yl_, zl_, function='cubic')
        #        rbf_l_ = Rbf( xl_, yl_, zl_, function = 'linear' )
        return rbf_l_

    rbf_u_ = Property(Instance(Rbf), depends_on='geo_input_name')

    @cached_property
    def _get_rbf_u_(self):
        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the upper face
        #
        xu_ = self.vu_arr_[:, 0]
        yu_ = self.vu_arr_[:, 1]
        zu_ = self.vu_arr_[:, 2]

        # flip the orientation of the local coordinate axis
        # depending on the geometry file used
        #
        if self.geo_input_name == '350x350cm':
            xu_ = 1 - self.vu_arr_[:, 0]
        if self.geo_input_name == '4x4m':
            yu_ = 1 - self.vu_arr_[:, 1]

        rbf_u_ = Rbf(xu_, yu_, zu_, function='cubic')
        #        rbf_u_ = Rbf( xu_, yu_, zu_, function = 'linear' )
        return rbf_u_

    #------------------------------------------------------------------------------
    # hp_shell geometric transformation
    # NOTE: returns the global coordinates of the shell based on the supplied local
    #       grid points
    #------------------------------------------------------------------------------

    def __call__(self, points):
        '''Return the global coordinates of the supplied local points.
        '''

        # number of local grid points for each coordinate direction
        # NOTE: values must range between 0 and 1
        #
        xi_, yi_, zi_ = points[:, 0], points[:, 1], points[:, 2]

        # insert imperfection (shift the middle node of the shell upwards)
        imp = self.z_imperfection_factor
        zi_ += imp * xi_ + imp * yi_ - 2 * imp * xi_ * yi_

        # size of total structure
        #
        # @todo: move to class definition of "mushroof_model" and send to "__call__"
        scale_size = self.scale_size
        # @todo: add "_quarter" (see above)
        length_xy_tot = self.length_xy_quarter * scale_size
        n_elems_xy_quarter = self.n_elems_xy_quarter

        #        print 'HPShell n_elems_xy_quarter', n_elems_xy_quarter
        # distance from origin for each mushroof_part
        #
        def d_origin_fn(self, coords):
            if self.mushroof_part == 'quarter':
                return coords
            if self.mushroof_part == 'one':
                return abs(2.0 * coords - 1.0)
            # @todo: corresponding "scale_factor" needs to be added
            #        in order for this to work
            if self.mushroof_part == 'four':
                return where(coords < 0.5, abs(4 * coords - 1),
                             abs(-4 * coords + 3))

        # element at column shift
        #
        if self.shift_elems == True:

            # define the origin for each model part
            #
            def origin_fn(self, coords):
                if self.mushroof_part == 'quarter':
                    return zeros_like(coords)
                if self.mushroof_part == 'one':
                    return ones_like(xi_) * 0.5
                if self.mushroof_part == 'four':
                    return where(coords < 0.5, 0.25, 0.75)

            def piecewise_linear_fn(x, x_fix_arr_, y_fix_arr_):
                '''creates a piecewise linear_fn going through the fix_points
                values need to be normed running between 0..1
                and values have to be unique'''
                x_fix_arr_ = hstack((0, x_fix_arr_, 1))
                y_fix_arr_ = hstack((0, y_fix_arr_, 1))
                rbf_fn_ = Rbf(x_fix_arr_, y_fix_arr_,
                              function='linear')  #rbf has to be linear
                return rbf_fn_(x)

            # define origin for quarter
            #
            xi_origin_arr_ = origin_fn(self, xi_)
            yi_origin_arr_ = origin_fn(self, yi_)
            #            print 'xi_origin_arr_', xi_origin_arr_

            # delta towards origin
            #
            xi_delta_arr_ = (xi_ - xi_origin_arr_) * scale_size
            yi_delta_arr_ = (yi_ - yi_origin_arr_) * scale_size
            #            print 'xi_delta_arr_', xi_delta_arr

            # define sign
            #
            xi_sign_arr = where(xi_delta_arr_ == 0., 0.,
                                xi_delta_arr_ / abs(xi_delta_arr_))
            yi_sign_arr = where(yi_delta_arr_ == 0., 0.,
                                yi_delta_arr_ / abs(yi_delta_arr_))
            #            print 'xi_sign_arr', xi_sign_arr

            # fix points defined in shift array as normelized values
            #
            x_fix_ = self.shift_array[:, 0] / self.length_xy_quarter
            #            print 'x_fix_', x_fix_

            y_fix_ = self.shift_array[:, 1] / self.length_xy_quarter
            n_fix_ = add.accumulate(self.shift_array[:,
                                                     2]) / n_elems_xy_quarter

            #            print 'add.accumulate( self.shift_array[:, 2] )', add.accumulate( self.shift_array[:, 2] )
            #            print 'n_fix_', n_fix_
            #            print 'piecewise_linear_fn', piecewise_linear_fn( abs( xi_delta_arr_ ),
            #                                                                   n_fix_,
            #                                                                   x_fix_ ) / scale_size

            # new xi_
            #
            xi_ = xi_origin_arr_ + xi_sign_arr * piecewise_linear_fn(
                abs(xi_delta_arr_), n_fix_, x_fix_) / scale_size

            #            print 'xi_new', xi_

            # new yi
            #
            yi_ = yi_origin_arr_ + yi_sign_arr * piecewise_linear_fn(
                abs(yi_delta_arr_), n_fix_, y_fix_) / scale_size

            #-------------------------------------------------------------------------------------

        # values are used to calculate the z-coordinate using RBF-function of the quarter
        # (= values of the distance to the origin as absolute value)
        #
        xi_rbf_ = d_origin_fn(self, xi_)
        #        print 'xi_rbf_', xi_rbf_
        yi_rbf_ = d_origin_fn(self, yi_)

        # get the z-value at the supplied local grid points
        # of the lower face
        #
        zi_lower_ = self.rbf_l_(xi_rbf_, yi_rbf_)

        # get the z-value at the supplied local grid points
        # of the upper face
        #
        zi_upper_ = self.rbf_u_(xi_rbf_, yi_rbf_)

        # constant edge element transformation
        #
        if self.const_reinf_layer_elem == True:
            # arrange and check data
            #
            if self.t_reinf_layer > self.t_shell / 2. or self.n_elems_z < 3:
                print '--- constant edge element transformation canceled ---'
                print 'the following condition needs to be fullfilled: \n'
                print 'self.t_reinf_layer <= self.t_shell/2 and self.n_elems_z >= 3'
            else:
                n_elems_z = float(self.n_elems_z)
                # normed thickness will evaluate as t_reinf_layer at each element
                t_reinf_layer_ = self.t_reinf_layer / self.length_z / (
                    zi_upper_ - zi_lower_)

                # zi_old set off from top which needs to be shifted
                delta_ = self.n_elems_reinf_layer / n_elems_z

                # get upper, lower and internal coordinates, that need to be shifted
                zi_lower = where(zi_ <= delta_)
                zi_upper = where(abs(1 - zi_) <= delta_ + 1e-10)
                zi_inter = where(abs(zi_ - 0.5) < 0.5 - (delta_ + 1e-10))

                # narrowing of coordinates
                zi_[zi_lower] = zi_[zi_lower] * t_reinf_layer_[
                    zi_lower] / delta_
                zi_[zi_upper] = 1 - (
                    1 - zi_[zi_upper]) * t_reinf_layer_[zi_upper] / delta_
                zi_[zi_inter] = t_reinf_layer_[zi_inter] + \
                                (zi_[zi_inter] - delta_) / (1 - 2 * delta_)\
                                 * (1 - 2 * t_reinf_layer_[zi_inter])
                print '--- constant edge elements transformation done ---'

        # thickness is multiplied by the supplied zi coordinate
        #
        z_ = (zi_lower_ * self.scalefactor_delta_h +
              (zi_upper_ - zi_lower_) * zi_)

        # coordinates of origin
        #
        X_0, Y_0, Z_0 = self.X0

        print '--- geometric transformation done ---'

        # multiply the local grid points with the real dimensions in order to obtain the
        # global coordinates of the mushroof_part:
        #
        return c_[X_0 + (xi_ * length_xy_tot) * self.scalefactor_length_xy,
                  Y_0 + (yi_ * length_xy_tot) * self.scalefactor_length_xy,
                  Z_0 + z_ * self.length_z]
Exemple #17
0
class TSCrackLoc( TStepper ):
    '''Modified time stepper with adjusted predictor and corrector.
    
    The management of the shared variable omega_0 is done before
    calling the standard corrector predictor. The strain state
    at the x = 0 is evaluated and provided to the MATS1DCrackLoc
    material model in order to evaluate the next trial damage state.
    
    During the corrpred call, the material model then uses these
    variables during the stress and stiffness integration.
    '''
    mats_eval = Property( Instance( MATS1DCrackLoc ) )
    def _get_mats_eval( self ):
        return self.subdomains[0].fets_eval.mats_eval.mats_phase1

    on_update = Callable

    fe_grid = Property( Instance( FEGrid ) )
    @cached_property
    def _get_fe_grid( self ):
        # get the single subgrid in the first subdomain.
        return self.subdomains[0].fe_subgrids[0]

    concrete_dofs = Property( Array( Float ) )
    @cached_property
    def _get_concrete_dofs( self ):
        # get the dofs associated with the bottom layer - concrete
        return self.fe_grid[:, 0, :, 0].dofs[:, :, 0]

    # specialize the 
    #
    def eval( self, step_flag, U_k, d_U, t_n, t_n1 ):

        print 'concrete dofs'
        print self.concrete_dofs

        if step_flag == 'corrector':

            # when in the corrector - switch the trial to accepted
            #
            self.mats_eval.update_state()
            self.on_update()

            #print 'E', self.subdomains[0].dots.state_array

        #----------------------------------
        # calculate the epxilon_0 at x = 0 
        #----------------------------------
        fe_grid = self.subdomains[0]
        # pick the first element
        elem_0 = fe_grid.elements[0]
        fets_eval = fe_grid.fets_eval
        # get the displacement vector in the first element
        u = U_k[ elem_0.get_dof_map() ]
        # and the coordinates
        # set the spatial context
        self.sctx.X = elem_0.get_X_mtx()
        self.sctx.x = elem_0.get_x_mtx()
        self.sctx.loc = array( [0], dtype = 'float_' )
        # get epsilon
        eps = fets_eval.get_eps_eng( self.sctx, u )
        # set the trial state for the obtained strain
        self.mats_eval.set_trial_state( eps )

        print 'BEGIN TS'
        # run the standard calculation
        return super( TSCrackLoc, self ).eval( step_flag, U_k, d_U, t_n, t_n1 )
class ECBLCalibState(HasStrictTraits):

    # rupture moment and normal force measured in the calibration experiment
    # (three point bending test)
    #
    Mu = Float(3.5, enter_set = True, auto_set = False, input = True) # [kNm]
    Nu = Float(0.0, enter_set = True, auto_set = False, input = True) # [kN]

    #===========================================================================
    # Cross Section Specification (Geometry and Layout)
    #===========================================================================

    cs_geo = Instance(ECBCrossSectionGeo)
    def _cs_geo_default(self):
        return ECBCrossSectionGeo(notify_change = self.set_modified)

    cs_state = Property(Instance(ECBCrossSectionState), depends_on = 'cs_geo')
    @cached_property
    def _get_cs_state(self):
        return ECBCrossSectionState(cs_geo = self.cs_geo,
                                    notify_change = self.set_modified)

    notify_change = Callable(None)

    modified = Event
    @on_trait_change('+input')
    def set_modified(self):
        self.modified = True
        if self.notify_change != None:
            self.notify_change()

    u0 = Property(Array(float), depends_on = 'cs_geo.modified, cs_state.modified')
    @cached_property
    def _get_u0(self):
        u0 = self.cs_state.ecb_law.u0
        eps_up = -self.cs_geo.cc_law.eps_c_u
        self.cs_state.set(eps_up = eps_up)
        eps_lo = self.cs_state.convert_eps_tex_u_2_lo(u0[0])
        return np.array([eps_lo, u0[1] ], dtype = 'float')

    # iteration counter
    #
    n = Int(0)
    def get_lack_of_fit(self, u):
        '''Return the difference between 'N_external' and 'N_internal' as well as 'M_external' and 'M_internal'
        N_c (=compressive force of the compressive zone of the concrete)
        N_t (=total tensile force of the reinforcement layers)
        '''

        print '--------------------iteration', self.n, '------------------------'
        self.n += 1
        # set iteration counter
        #
        eps_up = -self.cs_geo.cc_law.eps_c_u
        eps_lo = u[0]
        self.cs_state.set(eps_lo = eps_lo, eps_up = eps_up)

        eps_tex_u = self.cs_state.convert_eps_lo_2_tex_u(u[0])

        self.cs_geo.ecb_law.set_cparams(eps_tex_u, u[1])

        N_internal = self.cs_state.N
        M_internal = self.cs_state.M

        d_N = N_internal - self.Nu
        d_M = M_internal - self.Mu

        return np.array([ d_M, d_N ], dtype = float)

    # solution vector returned by 'fit_response'
    #
    u_sol = Property(Array(Float), depends_on = 'modified')
    @cached_property
    def _get_u_sol(self):
        '''iterate 'eps_t' such that the lack of fit between the calculated
        normal forces in the tensile reinforcement and the compressive zone (concrete)
        is smaller then 'xtol' defined in function 'brentq'.
        NOTE: the method 'get_lack_of_fit' returns the relative error.
        '''

        # use scipy-functionality to get the iterated value of 'eps_t'
        # NOTE: get_lack_of_fit must have a sign change as a requirement
        # for the function call 'brentq' to work property. 

        # The method brentq has optional arguments such as
        #   'xtol'    - absolut error (default value = 1.0e-12)
        #   'rtol'    - relative error (not supported at the time)
        #   'maxiter' - maximum numbers of iterations used
        #
        return fsolve(self.get_lack_of_fit, self.u0, xtol = 1.0e-5)

    #===========================================================================
    # Calibrated ecb_law_mfn
    #===========================================================================

    calibrated_ecb_law = Property(depends_on = 'modified')
    @cached_property
    def _get_calibrated_ecb_law(self):
        print 'NEW CALIBRATION'
        self.cs_geo.ecb_law.set_cparams(*self.u_sol)
        return self.cs_geo.ecb_law

    view = View(Item('Mu'),
                Item('Nu'),
                buttons = ['OK', 'Cancel']
                )
Exemple #19
0
class ExpBT3PT(ExType):
    '''Experiment: Bending Test Three Point
    '''
    #    label = Str('three point bending test')

    implements(IExType)

    file_ext = 'raw'

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

    input_change = Event

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

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

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

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

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

    ccs = Instance(CompositeCrossSection)

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

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

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

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

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

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

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

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

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

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

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

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

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

    names_and_units = Property(depends_on='data_file')

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

    names_and_units_ASC = Property(depends_on='data_file')

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

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

    factor_list_ASC = Property(depends_on='data_file')

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

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

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

    elastomer_law = Property(depends_on='input_change')

    @cached_property
    def _get_elastomer_law(self):

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

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

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

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

    w_wo_elast = Property(depends_on='input_change')

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

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

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

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

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

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

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

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

        # coposite E-modulus
        #
        E_c = self.E_c

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

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

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

        return K_bending_elast

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

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

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

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

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

        return F_cr

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

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

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

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

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

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

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

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

            self.F_ASC = -1.0 * self.Kraft

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

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

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

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

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

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

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

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

    default_plot_template = 'force / deflection (displacement gauge)'

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

        # composite E-modulus
        #
        E_c = self.E_c

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        t = self.thickness
        w = self.width

        # coposite E-modulus
        #
        E_c = self.E_c

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

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

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

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

        w_lin_epsc = w_asc[idx_lin]

        w_lin_analytic = f_asc[idx_lin] / self.K_bending_elast

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def _plot_smoothed_force_gauge_displacement(self, axes):

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

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

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

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

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

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

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

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

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

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

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

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

    def _plot_smoothed_force_machine_displacement_wo_elast(self, axes):

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

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

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

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

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


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

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

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

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

        max_M = np.max(self.M_raw)

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

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

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

        max_M = np.max(self.M_raw)

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

    n_fit_window_fraction = Float(0.1)

    smoothed_M_eps_c_ASC = Property(depends_on='input_change')

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

    smoothed_eps_c_ASC = Property

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

    smoothed_M_ASC = Property

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

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

    smoothed_M_eps_c_raw = Property(depends_on='input_change')

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

    smoothed_eps_c_raw = Property

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

    smoothed_M_raw = Property

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

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

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

    traits_view = View(VGroup(
        Group(Item('length', format_str="%.3f"),
              Item('width', format_str="%.3f"),
              Item('thickness', format_str="%.3f"),
              label='geometry'),
        Group(Item('loading_rate'), Item('age'), label='loading rate and age'),
        Group(Item('E_c', show_label=True, style='readonly',
                   format_str="%.0f"),
              Item('ccs@', show_label=False),
              label='composite cross section')),
                       scrollable=True,
                       resizable=True,
                       height=0.8,
                       width=0.6)
Exemple #20
0
class MFnLineArray(HasTraits):

    # Public Traits
    xdata = Array(float, value = [0.0, 1.0])
    def _xdata_default(self):
        '''
        convenience default - when xdata not defined created automatically as
        an array of integers with the same shape as ydata
        '''
        return np.arange(self.ydata.shape[0])

    ydata = Array(float, value = [0.0, 1.0])

    extrapolate = Enum('constant', 'exception', 'diff', 'zero')

    # alternative vectorized interpolation using scipy.interpolate   
    def get_values(self, x, k = 1):
        '''
        vectorized interpolation, k is the spline order, default set to 1 (linear)
        '''
        tck = ip.splrep(self.xdata, self.ydata, s = 0, k = k)

        x = np.array([x]).flatten()

        if self.extrapolate == 'diff':
            values = ip.splev(x, tck, der = 0)
        elif self.extrapolate == 'exception':
            if x.all() < self.xdata[0] and x.all() > self.xdata[-1]:
                values = values = ip.splev(x, tck, der = 0)
            else:
                raise ValueError('value(s) outside interpolation range')

        elif self.extrapolate == 'constant':
            mask = x >= self.xdata[0]
            mask *= x <= self.xdata[-1]
            l_mask = x < self.xdata[0]
            r_mask = x > self.xdata[-1]
            extrapol_left = np.repeat(ip.splev(self.xdata[0], tck, der = 0), len(x)) * l_mask
            extrapol_right = np.repeat(ip.splev(self.xdata[-1], tck, der = 0), len(x)) * r_mask
            extrapol = extrapol_left + extrapol_right
            values = ip.splev(x, tck, der = 0) * mask + extrapol
        elif self.extrapolate == 'zero':
            mask = x >= self.xdata[0]
            mask *= x <= self.xdata[-1]
            mask_extrapol = mask == False
            extrapol = np.zeros(len(x)) * mask_extrapol
            values = ip.splev(x, tck, der = 0) * mask + extrapol
        return values

    def get_value(self, x):
        x2idx = self.xdata.searchsorted(x)
        if x2idx == len(self.xdata):
            x2idx -= 1
        x1idx = x2idx - 1
        x1 = self.xdata[ x1idx ]
        x2 = self.xdata[ x2idx ]
        dx = x2 - x1
        y1 = self.ydata[ x1idx ]
        y2 = self.ydata[ x2idx ]
        dy = y2 - y1
        y = y1 + dy / dx * (x - x1)
        return y

    data_changed = Event

    def get_diffs(self, x, k = 1, der = 1):
        '''
        vectorized interpolation, der is the nth derivative, default set to 1;
        k is the spline order of the data inetrpolation, default set to 1 (linear)
        '''
        xdata = np.sort(np.hstack((self.xdata, x)))
        idx = np.argwhere(np.diff(xdata) == 0).flatten()
        xdata = np.delete(xdata, idx)
        tck = ip.splrep(xdata, self.get_values(xdata, k = k), s = 0, k = k)
        return ip.splev(x, tck, der = der)

    def get_diff(self, x):
        x2idx = self.xdata.searchsorted(x)
        if x2idx == len(self.xdata):
            x2idx -= 1
        x1idx = x2idx - 1
        x1 = self.xdata[ x1idx ]
        x2 = self.xdata[ x2idx ]
        dx = x2 - x1
        y1 = self.ydata[ x1idx ]
        y2 = self.ydata[ x2idx ]
        dy = y2 - y1
        return dy / dx

    dump_button = ToolbarButton('Print data',
                                style = 'toolbar')
    @on_trait_change('dump_button')
    def print_data(self, event = None):
        print 'x = ', repr(self.xdata)
        print 'y = ', repr(self.ydata)

    integ_value = Property(Float(), depends_on = 'ydata')
    @cached_property
    def _get_integ_value(self):
        _xdata = self.xdata
        _ydata = self.ydata
        # integral under the stress strain curve
        E_t = np.trapz(_ydata, _xdata)
        # area of the stored elastic energy  
        U_t = 0.0
        if len(_xdata) != 0:
            U_t = 0.5 * _ydata[-1] * _xdata[-1]
        return E_t - U_t

    def clear(self):
        self.xdata = np.array([])
        self.ydata = np.array([])

    def plot(self, axes, *args, **kw):
        self.mpl_plot(axes, *args, **kw)

    def mpl_plot(self, axes, *args, **kw):
        '''plot within matplotlib window'''
        axes.plot(self.xdata, self.ydata, *args, **kw)
Exemple #21
0
class RandomVariable( HasTraits ):
    '''Class representing the definition and discretization of a random variable.
    '''
    trait_value = Float

    source_trait = CTrait

    # name of the parameter
    name = Str

    pd = Instance( IPDistrib )
    def _pd_changed( self ):
        self.pd.n_segments = self._n_int

    changed = Event
    @on_trait_change( 'pd.changed,+changed' )
    def _set_changed( self ):
        self.changed = True

    # Switch the parameter random 
    random = Bool( False, changed = True )

    def set_random( self, distribution = 'uniform', discr_type = 'T grid',
                    loc = 0., scale = 1., shape = 1., n_int = 30 ):

        possible_distr = self.source_trait.distr
        if distribution and distribution not in possible_distr:
            raise AssertionError, 'distribution type %s not allowed for parameter %s' \
                % ( distribution, self.name )

        self.pd = PDistrib( distr_choice = distribution, n_segments = n_int )
        self.pd.distr_type.set( scale = scale, shape = shape, loc = loc )

        self.n_int = n_int
        self.discr_type = discr_type
        self.random = True

    def unset_random( self ):
        self.random = False

    # Number of integration points (relevant only for grid based methods)
    _n_int = Int
    n_int = Property
    def _set_n_int( self, value ):
        if self.pd:
            self.pd.n_segments = value
        self._n_int = value
    def _get_n_int( self ):
        return self.pd.n_segments

    # type of the RandomVariable discretization 
    discr_type = Enum( 'T grid', 'P grid', 'MC',
                        changed = True )
    def _discr_type_default( self ):
        return 'T grid'

    theta_arr = Property( Array( 'float_' ), depends_on = 'changed' )
    @cached_property
    def _get_theta_arr( self ):
        '''Get the discr_type of the pdistrib
        '''
        if not self.random:
            return array( [ self.trait_value ], dtype = float )

        if self.discr_type == 'T grid':

            # Get the discr_type from pdistrib and shift it
            # such that the midpoints of the segments are used for the
            # integration.

            x_array = self.pd.x_array
            # Note assumption of T grid discr_type
            theta_array = x_array[:-1] + self.pd.dx / 2.0

        elif self.discr_type == 'P grid':

            # P grid disretization generated from the inverse cummulative
            # probability
            #
            distr = self.pd.distr_type.distr
            # Grid of constant probabilities
            pi_arr = linspace( 0.5 / self.n_int, 1. - 0.5 / self.n_int, self.n_int )
            theta_array = distr.ppf( pi_arr )

        return theta_array

    dG_arr = Property( Array( 'float_' ), depends_on = 'changed' )
    @cached_property
    def _get_dG_arr( self ):

        if not self.random:
            return array( [ 1.0 ], dtype = float )

        if self.discr_type == 'T grid':

            d_theta = self.theta_arr[1] - self.theta_arr[0]
            return self.pd.get_pdf_array( self.theta_arr ) * d_theta

        elif self.discr_type == 'P grid':

            # P grid disretization generated from the inverse cummulative
            # probability
            #
            return array( [ 1.0 / float( self.n_int ) ], dtype = 'float_' )

    def get_rvs_theta_arr( self, n_samples ):
        if self.random:
            return self.pd.get_rvs_array( n_samples )
        else:
            return array( [self.trait_value], float )
Exemple #22
0
class HPShell(HasTraits):
    '''Geometry definition.
    '''
    # dimensions of the shell structure [m]
    # (only one quart of the shell structure)
    #
    # NOTE: lenth_z = 1.0 m + 0.062 m = 1.062
    # NOTE: lenth_z = 0.865 m + 0.062 m = 0.927
    length_x = Float(3.50)
    length_y = Float(3.50)
    length_z = Float(0.927)

    # corresponds to the delta in the geometry obj file '4x4m'
    delta_h = Float(0.865)  # [m]

    # factor to scale height of lower surface
    # thickness remains unchanged as 0.06 m
    #
    delta_h_scalefactor = Float(1.00)  # [-]

    # cut of the z-coordinates of the lowerface if set to True
    #
    cut_off_lowerface = Bool(True)

    geo_input_name = Enum('350x350cm')
    geo_filter = Dict({'4x4m': delete_second_rows})

    def _read_arr(self, side='lowerface_'):
        file_name = side + self.geo_input_name + '.robj'
        file_path = join('geometry_files', file_name)
        v_arr = read_rsurface(file_path)

        filter = self.geo_filter.get(self.geo_input_name, None)
        if filter != None:
            v_arr = filter(v_arr)
        return v_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the lower surface of the shell
    vl_arr = Property(Array(float))

    @cached_property
    def _get_vl_arr(self):
        vl_arr = self._read_arr('lowerface_')
        if self.cut_off_lowerface == True:
            print '--- lower face z-coords cut off ---'

            # z-values of the coords from the lower face are cut off.
            # From the highest z-coordinate of the lower face the vertical
            # distance is 1 m (=delta h). At this limit the lower face is
            # cut off. Global z coordinate is assumed to point up.
            #
            vl_z_max = max(vl_arr[:, 2])
            if self.geo_input_name == '4x4m':
                # NOTE: the global z-coordinates are given in the geo data file in [m]
                # no conversion of unites necessary (self.delta_h is given in [m])
                delta_h = self.delta_h
            elif self.geo_input_name == '350x350cm':
                # NOTE: the global z-coordinates are given in the geo data file in [cm]
                # convert delta_h from [m] to [cm]
                #
                delta_h = self.delta_h * 100.
            vl_z_min = vl_z_max - self.delta_h
            vl_arr_z = where(vl_arr[:, 2] < vl_z_min, vl_z_min, vl_arr[:, 2])
            vl_arr = c_[vl_arr[:, 0:2], vl_arr_z]
        return vl_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the upper surface of the shell
    vu_arr = Property(Array(float))

    @cached_property
    def _get_vu_arr(self):
        return self._read_arr('upperface_')

    def get_mid_surface_and_thickness(self, points, perpendicular_t=True):
        '''Return the global coordinates of the supplied local points.
        '''
        print '*** get mid surface and thickness ***'

        #-----------------------------------------------
        # get the global coordinates as defined in the
        # input file and transform them to the coordinate
        # system of the master quarter
        #-----------------------------------------------

        #
        if self.geo_input_name == '350x350cm':
            X0 = [3.50, 3.50, 0.]
        else:
            X0 = [0., 0., 0.]

        # number of global grid points for each coordinate direction
        #
        xi, yi = points[:, 0] - X0[0], points[:, 1] - X0[1]

        # NOTE:
        # -- The available rbf-function is only defined for a quarter of one shell.
        # in order to get z and t values for an entire shell the abs-function
        # is used. The coordinate system of the quarter must be defined in the
        # lower left corner; the coordinate systemn of the entire one shell must
        # be defined in the center of the shell so that the coordinate system
        # for the master quarter remains unchanged.
        # -- The transformation is performed based on the defined class attributes
        # of hp_shell_stb: length_x, length_y, length_z, delta_h, delta_h_scalefactor
        # characterizing the properties of the master quarter

        # number of local grid points for each coordinate direction
        # values must range between 0 and 1
        #
        points_tilde_list = []
        for i_row in range(points.shape[0]):
            # get the x, y coordinate pair defined in the input
            # file in global coordinates
            #
            x = xi[i_row]
            y = yi[i_row]

            # transform values to local coordinate system,
            # i.e. move point to the 'master roof' containing the
            # global coordinate system:
            #
            if x <= self.length_x and y <= self.length_y:
                # point lays in first (master) roof
                #
                x_tilde = x
                y_tilde = y

            elif x >= self.length_x and y <= self.length_y:
                # point lays in second roof:
                #
                # roof length = 2* length of the master quarter
                # (e.g. 2*4,0m = 8,00m for obj-file "4x4m")
                x_tilde = x - 2 * self.length_x
                y_tilde = y

            elif x <= self.length_x and y >= self.length_y:
                # point lays in third roof:
                #
                x_tilde = x
                y_tilde = y - 2 * self.length_y

            elif x >= self.length_x and y >= self.length_y:
                # point lays in fourth roof:
                #
                x_tilde = x - 2 * self.length_x
                y_tilde = y - 2 * self.length_y

            points_tilde_list.append([x_tilde, y_tilde])

        points_tilde_arr = array(points_tilde_list, dtype='float_')
        xi_tilde = points_tilde_arr[:, 0]
        yi_tilde = points_tilde_arr[:, 1]
        #        print 'points_tilde_arr', points_tilde_arr

        xi_ = abs(xi_tilde) / self.length_x
        yi_ = abs(yi_tilde) / self.length_y

        #-----------------------------------------------
        # get the normalized rbf-function for the upper
        # and lower face of the master quarter
        #-----------------------------------------------
        # NOTE: the underline character indicates a normalized value

        # normalized coordinates of the vertices for lower- and upper-face
        #
        vl_arr_, vu_arr_ = normalize_rsurfaces(self.vl_arr, self.vu_arr)

        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the lower face
        #
        x_ = vl_arr_[:, 0]
        y_ = vl_arr_[:, 1]

        if self.geo_input_name == '350x350cm':
            x_ = 1 - vl_arr_[:, 0]

        z_l_ = vl_arr_[:, 2]
        rbf_l = Rbf(x_, y_, z_l_, function='cubic')

        # get the z-value at the supplied local grid points
        # of the lower face
        #
        zi_lower_ = rbf_l(xi_, yi_)

        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the upper face
        #
        x_ = vu_arr_[:, 0]
        y_ = vu_arr_[:, 1]

        if self.geo_input_name == '350x350cm':
            x_ = 1 - vu_arr_[:, 0]

        z_u_ = vu_arr_[:, 2]
        rbf_u = Rbf(x_, y_, z_u_, function='cubic')

        # get the z-value at the supplied local grid points
        # of the upper face
        #
        zi_upper_ = rbf_u(xi_, yi_)

        # approach of the slope to get thickness perpendicular to slope
        #
        # thickness is multiplied by the supplied zi coordinate
        # and z value of mid plane
        #
        t_ = zi_upper_ - zi_lower_

        z_middle_ = (zi_lower_ + (zi_upper_ - zi_lower_) * 0.5 /
                     self.delta_h_scalefactor) * self.delta_h_scalefactor

        if perpendicular_t == True:
            # delta shift of x and y for estimation of slope will be done in 4 direction
            # 0, 45, 90 and 135 degrees
            print "--- perpendicular ---"
            delta = 0.000001

            # shift in x

            dz_x_p_ = (rbf_u(xi_ + delta, yi_) + rbf_l(xi_ + delta, yi_)) / 2.0
            dz_x_m_ = (rbf_u(xi_ - delta, yi_) + rbf_l(xi_ - delta, yi_)) / 2.0

            slope_x_ = (dz_x_p_ - dz_x_m_) / (2.0 * delta)
            angle_x = arctan(slope_x_ * self.length_z / self.length_x)
            f_1 = cos(angle_x)

            # shift in y

            dz_y_p_ = (rbf_u(xi_, yi_ + delta) + rbf_l(xi_, yi_ + delta)) / 2.0
            dz_y_m_ = (rbf_u(xi_, yi_ - delta) + rbf_l(xi_, yi_ - delta)) / 2.0

            slope_y_ = (dz_y_p_ - dz_y_m_) / (2.0 * delta)
            angle_y = arctan(slope_y_ * self.length_z / self.length_x)
            f_2 = cos(angle_y)

            #shift +x +y; -x -y

            dz_x_p_y_p_ = (rbf_u(xi_ + delta, yi_ + delta) +
                           rbf_l(xi_ + delta, yi_ + delta)) / 2.0
            dz_x_m_y_m_ = (rbf_u(xi_ - delta, yi_ - delta) +
                           rbf_l(xi_ - delta, yi_ - delta)) / 2.0

            slope_x_p_y_p_ = (dz_x_p_y_p_ - dz_x_m_y_m_) / (2.0 * sqrt(2) *
                                                            delta)
            angle_x_p_y_p = arctan(slope_x_p_y_p_ * self.length_z /
                                   (self.length_x**2 + self.length_y**2)**0.5)
            f_3 = cos(angle_x_p_y_p)

            # shift in +x,-y ; -x and +y

            dz_x_p_y_m_ = (rbf_u(xi_ + delta, yi_ - delta) +
                           rbf_l(xi_ + delta, yi_ - delta)) / 2.0
            dz_x_m_y_p_ = (rbf_u(xi_ - delta, yi_ + delta) +
                           rbf_l(xi_ - delta, yi_ + delta)) / 2.0

            slope_x_p_y_m_ = (dz_x_p_y_m_ - dz_x_m_y_p_) / (sqrt(2) * 2.0 *
                                                            delta)
            angle_x_p_y_m = arctan(slope_x_p_y_m_ * self.length_z /
                                   (self.length_x**2 + self.length_y**2)**0.5)
            f_4 = cos(angle_x_p_y_m)

            # obtain minimum factor for good estimate of maximum slope

            factor = min([f_1, f_2, f_3, f_4], axis=0)
            t_ = t_ * factor

        return xi, yi, z_middle_ * self.length_z, t_ * self.length_z

    def _read_thickness_data(self, file_name):
        '''to read the stb - X and Y coordinates ( m ) save the xls - worksheet
        to a csv - file using ';' as filed delimiter and ' ' ( blank )
        as text delimiter.
        Stb Data needs to have same range of values in X and Y direction and same unit [m],
        as defined as length_x and length_y
        '''
        print '*** reading thickness data from file: ', file_name, ' ***'

        # get the column headings defined in the second row
        # of the csv thickness input file
        # "Nr.;X;Y;Z;[mm]"
        #
        file = open(file_name, 'r')
        lines = file.readlines()
        column_headings = array(lines[1].split(';'))
        elem_no_idx = where('Nr.' == column_headings)[0]
        X_idx = where('X' == column_headings)[0]
        Y_idx = where('Y' == column_headings)[0]
        Z_idx = where('Z' == column_headings)[0]
        thickness_idx = where('[mm]\n' == column_headings)[0]

        input_arr = loadtxt(file_name, delimiter=';', skiprows=2)

        # elem number:
        #
        elem_no = input_arr[:, elem_no_idx]

        # coordinates [m]:
        #
        X = input_arr[:, X_idx][:, 0]
        Y = input_arr[:, Y_idx][:, 0]

        #        print 'thickness_idx', thickness_idx
        if thickness_idx != []:
            thickness_stb = input_arr[:, thickness_idx][:, 0] / 1000.
            return elem_no, X, Y, thickness_stb
        else:
            thickness_stb = ones_like(elem_no)
            return elem_no, X, Y, thickness_stb

    def _read_elem_coords(self, file_name):
        '''x,y -coordinates must be read from old file
        '''
        input_arr = loadtxt(file_name, delimiter=';', skiprows=2)

        elem_no = input_arr[:, 0]
        X = input_arr[:, 2]
        Y = input_arr[:, 3]

        return elem_no, X, Y

    def _read_nodal_coords(self, file_name):
        '''read the nodal coordinates of the mid - surface
        defined in a csv - file. To export the excel sheet
        to csv use ";" as a field delimiter and "" ( none )
        as a text delimiter.
        Note that some lines do not contain values !
        '''
        print '*** reading nodal coordinates from file: ', file_name, ' ***'

        file = open(file_name, 'r')

        # read the column headings (first two lines)
        #
        first_line = file.readline()
        second_line = file.readline()
        column_headings = second_line.split(';')
        # remove '\n' from last string element in list
        column_headings[-1] = column_headings[-1][:-1]
        column_headings_arr = array(column_headings)

        # check in which column the node number and the
        # carthesian coordinates can be found
        #
        elem_no_idx = where('Nr.' == column_headings_arr)[0]
        X_idx = where('X [m]' == column_headings_arr)[0]
        Y_idx = where('Y [m]' == column_headings_arr)[0]
        Z_idx = where('Z [m]' == column_headings_arr)[0]

        lines = file.readlines()

        lines_list = [line.split(';') for line in lines]

        empty_lines_idx = []
        ll = []
        for i_line, line in enumerate(lines_list):

            # check if line contains values or only a node number!
            #
            if line[1] == 'Standard':
                ll.append(
                    [line[elem_no_idx], line[X_idx], line[Y_idx], line[Z_idx]])
            else:
                # NOTE: current number in file starts with 1, index in loop starts with 0
                # therefore add 1 in the index list
                #
                empty_lines_idx.append(i_line + 1)

        input_arr = array(ll, dtype='float_')

        node_no = input_arr[:, 0]
        X = input_arr[:, 1]
        Y = input_arr[:, 2]
        Z = input_arr[:, 2]

        return node_no, X, Y, Z, empty_lines_idx

    def compare_thickness_values(self, thickness, thickness_stb):
        '''get relative difference between the calucated thickness
        read in from the obj file, cut of and projected with respect to
        the approximated data given from stb.
        '''
        thickness = thickness.reshape(shape(thickness_stb))
        error = abs(1 - thickness / thickness_stb) * 100
        return error

    def export_midsurface_data(self, node_no, x, y, z_middle, file_name,
                               empty_lines_idx):
        '''exports data to csv - worksheet
        '''
        print '*** writing middle surface data to file,', file_name, ' ***'

        data = c_[node_no, x, y, z_middle]
        file = open(file_name, 'w')
        writer = csv.writer(file, delimiter=";", lineterminator="\n")
        writer.writerow(['node_number', 'x[m]', 'y[m]', 'z[m]'])
        writer.writerows(data)

        file = file.close()

        # if file contains empty lines add them at the positions
        # defined in 'empty_lines_idx'
        #
        if len(empty_lines_idx) != 0:

            print '--- file contains ', len(
                empty_lines_idx), ' empty_lines ---'

            # file without empty lines
            #
            file = open(file_name, 'r')
            lines = file.readlines()

            # overwrite file including empty lines
            #
            file = open(file_name, 'w')

            # index 'n' runs in the array without empty lines
            # index 'i' runs in the array with empty lines
            #
            n = 0
            for i in range(data.shape[0] + len(empty_lines_idx)):

                if i in empty_lines_idx:
                    file.writelines(str(i) + ";;;;\n")
                else:
                    file.writelines(lines[n])
                    n += 1

            # add last line:
            #
            file.writelines(lines[-1])

            file.close()
            print '--- empty lines added to file ---'

        return

    def export_thickness_data(self, elem_no, x, y, t, file_name):
        '''exports data to csv - worksheet
        '''
        print '*** writing thickness data to file,', file_name, ' ***'

        data = c_[elem_no, x, y, t * 1000]
        print shape(data)
        writer = csv.writer(open(file_name, 'w'),
                            delimiter=";",
                            lineterminator="\n")
        writer.writerow(['element_number', 'x[m]', 'y[m]', 't[mm]'])
        writer.writerows(data)
        return

    @show
    def show(self, x, y, z_middle, displayed_value):
        """Test contour_surf on regularly spaced co-ordinates like MayaVi.
        """
        print '*** plotting data***'
        s = points3d(X,
                     Y,
                     z_middle,
                     displayed_value,
                     colormap="gist_rainbow",
                     mode="cube",
                     scale_factor=0.3)

        sb = colorbar(s)
        # Recorded script from Mayavi2
        #try:
        #    engine = mayavi.engine
        #except NameError:
        #    from etsproxy.mayavi.api import Engine
        #    engine = Engine()
        #    engine.start()
        #if len(engine.scenes) == 0:
        #    engine.new_scene()
        # -------------------------------------------
        glyph = s  #.pipeline.scenes[0].children[0].children[0].children[0]
        glyph.glyph.glyph_source.glyph_source.center = array([0., 0., 0.])
        glyph.glyph.glyph_source.glyph_source.progress = 1.0
        glyph.glyph.glyph_source.glyph_source.x_length = 0.6
        glyph.glyph.glyph_source.glyph_source.y_length = 0.6
        sb.scalar_bar.title = 'thickness [m]'
        #print s.pipeline
        #s.scene.background = (1.0, 1.0, 1.0)

        return s
Exemple #23
0
class ExpST(ExType):
    '''Experiment: Slab Test
    '''
#    label = Str('slab test')
    implements(IExType)

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

                data_array_ironed[:, idx] = data_arr[:]

        return data_array_ironed


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

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

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

        # set attributes:
        #
        self._set_array_attribs()

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


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

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

                     }

    default_plot_template = 'force / deflection (center)'


    n_fit_window_fraction = Float(0.1)

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

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

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

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

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

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

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

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

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

        axes.legend()

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

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

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

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

        f.write(temp)
        f.close()



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    traits_view = View(VGroup(
                         Group(
                              Item('jump_rtol', format_str="%.4f"),
                              label='curve_ironing'
                              ),
                         Group(
                              Item('thickness', format_str="%.3f"),
                              Item('edge_length', format_str="%.3f"),
                              label='geometry'
                              ),
                         Group(
                              Item('loading_rate'),
                              Item('age'),
                              label='loading rate and age'
                              ),
                         Group(
                              Item('E_c', show_label=True, style='readonly', format_str="%.0f"),
                              Item('ccs@', show_label=False),
                              label='composite cross section'
                              )
                         ),
                        scrollable=True,
                        resizable=True,
                        height=0.8,
                        width=0.6
                        )
Exemple #24
0
class RandomField(HasTraits):
    '''
    This class implements a 3D random field on a regular grid
    and allows for interpolation using the EOLE method
    '''
    lacor_arr = Array(Float, modified=True) #(nD,1) array of autocorrelation lengths
    nDgrid = List(Array, modified=True) # list of nD entries: each entry is an array of points in the part. dimension
    reevaluate = Event
    seed = Bool(False)
    distr_type = Enum('Gauss', 'Weibull', modified=True)
    stdev = Float(1.0, modified=True)
    mean = Float(0.0, modified=True)
    shape = Float(5.0, modified=True)
    scale = Float(1.0, modified=True)
    loc = Float(0.0, modified=True)
    
    def acor(self, dx, lacor):
        '''autocorrelation function'''
        C = e ** (-(dx / lacor) ** 2)
        return C

    eigenvalues = Property(depends_on='+modified')
    @cached_property
    def _get_eigenvalues(self):
        '''evaluates the eigenvalues and eigenvectors of the covariance matrix'''
        # creating distances from the first coordinate
        for i, grid_i in enumerate(self.nDgrid):
            self.nDgrid[i] -= grid_i[0]
        # creating a symm. toeplitz matrix with (xgrid, xgrid) data points
        coords_lst = [toeplitz(grid_i) for grid_i in self.nDgrid]
        # apply the autocorrelation func. on the coord matrices to obtain the covariance matrices
        C_matrices = [self.acor(coords_i, self.lacor_arr[i]) for i, coords_i in enumerate(coords_lst)]
        # evaluate the eigenvalues and eigenvectors of the autocorrelation matrices
        eigen_lst = []
        for i, C_i in enumerate(C_matrices):
            print 'evaluating eigenvalues for dimension ' + str(i+1)
            lambda_i, Phi_i = eigh(C_i)
            # truncate the eigenvalues at 99% of tr(C)
            truncation_limit = 0.99 * np.trace(C_i)
            argsort = np.argsort(lambda_i)
            cum_sum_lambda = np.cumsum(np.sort(lambda_i)[::-1])
            idx_trunc = int(np.sum(cum_sum_lambda < truncation_limit))
            eigen_lst.append([lambda_i[argsort[::-1]][:idx_trunc], Phi_i[:, argsort[::-1]][:,:idx_trunc]])
        print 'complete'
        Lambda_C = 1.0
        Phi_C = 1.0
        for lambda_i, Phi_i in eigen_lst:
            Lambda_i = np.diag(lambda_i)
            Lambda_C = np.kron(Lambda_C, Lambda_i)
            Phi_C = np.kron(Phi_C, Phi_i)
        
        return Lambda_C, Phi_C
    
    generated_random_vector = Property(Array, depends_on='reevaluate')
    @cached_property
    def _get_generated_random_vector(self):
        if self.seed == True:
            np.random.seed(141)
        # points between 0 to 1 with an equidistant step for the LHS
        # No. of points = No. of truncated eigenvalues
        npts = self.eigenvalues[0].shape[0]
        randsim = np.linspace(0.5/npts, 1 - 0.5/npts, npts)
        # shuffling points for the simulation
        np.random.shuffle(randsim)
        # matrix containing standard Gauss distributed random numbers
        xi = norm().ppf(randsim)
        return xi
    
    random_field = Property(Array, depends_on='+modified')
    @cached_property
    def _get_random_field(self):
        '''simulates the Gaussian random field'''
        # evaluate the eigenvalues and eigenvectors of the autocorrelation matrix
        Lambda_C_sorted, Phi_C_sorted = self.eigenvalues
        # generate the RF with standardized Gaussian distribution
        ydata = np.dot(np.dot(Phi_C_sorted, (Lambda_C_sorted) ** 0.5), self.generated_random_vector)
        # transform the standardized Gaussian distribution
        if self.distr_type == 'Gauss':
            # scaling the std. distribution
            scaled_ydata = ydata * self.stdev + self.mean
        elif self.distr_type == 'Weibull':
            # setting Weibull params
            Pf = norm().cdf(ydata)
            scaled_ydata = weibull_min(self.shape, scale=self.scale, loc=self.loc).ppf(Pf)
        shape = tuple([len(grid_i) for grid_i in self.nDgrid])
        rf = np.reshape(scaled_ydata, shape)
        return rf
    
    def interpolate_rf(self, coords):
        '''interpolate RF values using the EOLE method
        coords = list of 1d arrays of coordinates'''
        # check consistency of dimensions
        if len(coords) != len(self.nDgrid):
            raise ValueError('point dimension differs from random field dimension')
        # create the covariance matrix
        C_matrices = [self.acor(coords_i.reshape(1, len(coords_i)) - self.nDgrid[i].reshape(len(self.nDgrid[i]),1), self.lacor_arr[i]) for i, coords_i in enumerate(coords)]
        
        C_u = 1.0
        for i, C_ui in enumerate(C_matrices):
            if i == 0:
                C_u *= C_ui
            else:
                C_u = C_u.reshape(C_u.shape[0], 1, C_u.shape[1]) * C_ui
            grid_size = 1.0
            for j in np.arange(i+1):
                grid_size *= len(self.nDgrid[j])
            C_u = C_u.reshape(grid_size,len(coords[0]))

        Lambda_Cx, Phi_Cx = self.eigenvalues
        # values interpolated in the standardized Gaussian rf 
        u = np.sum(self.generated_random_vector / np.diag(Lambda_Cx) ** 0.5 * np.dot(C_u.T, Phi_Cx), axis=1)
        if self.distr_type == 'Gauss':
            scaled_u = u * self.stdev + self.mean
        elif self.distr_type == 'Weibull':
            Pf = norm().cdf(u)
            scaled_u = weibull_min(self.shape, scale=self.scale, loc=self.loc).ppf(Pf)
        return scaled_u
Exemple #25
0
class Distribution(HasTraits):
    ''' takes a scipy.stats distribution '''
    def __init__(self, distribution, **kw):
        super(Distribution, self).__init__(**kw)
        self.distribution = distribution
        self.changes()

    distribution = Instance(rv_continuous)

    def add_listeners(self):
        self.on_trait_change(self.changes, '+params,+moments')

    def remove_listeners(self):
        self.on_trait_change(self.changes, '+params,+moments', remove=True)

    # precision for displayed numbers = 12 numbers corresponds with the numbers
    # displayed in the UI.
    decimal.getcontext().prec = 12

    # event that triggers the replot in pdistrib.py
    changed = Event

    # freezes the location to 0.0
    loc_zero = Bool(True)

    # old values are compared with new values to recognize which value changed
    old_values = Array(Float, value=zeros(7))
    new_values = Array(Float, value=zeros(7))

    # statistical parameters
    loc = Float(0.0, auto_set=False, enter_set=True, params=True)
    scale = Float(1.0, auto_set=False, enter_set=True, params=True)
    shape = Float(1.0, auto_set=False, enter_set=True, params=True)

    # statistical moments
    mean = Float(0.0, auto_set=False, enter_set=True, moments=True)
    variance = Float(0.0, auto_set=False, enter_set=True, moments=True)
    skewness = Float(0.0, auto_set=False, enter_set=True, moments=True)
    kurtosis = Float(0.0, auto_set=False, enter_set=True, moments=True)

    stdev = Property(depends_on='variance')

    def _get_stdev(self):
        return self.variance**(0.5)

    def get_mean(self):
        ''' Methods for evaluating the statistical moments. Decimal together with
        precision are needed in order to get the number which is actually displayed
        in the UI. Otherwise clicking in the interface or pressing enter on the
        displayed values would trigger new computation because these values are a
        representation of the computed values rounded to 12 numbers. '''
        self.mean = float(Decimal(str((self.distr.stats('m')))) / 1)

    def get_variance(self):
        self.variance = float(Decimal(str((self.distr.stats('v')))) / 1)

    def get_skewness(self):
        self.skewness = float(Decimal(str((self.distr.stats('s')))) / 1)

    def get_kurtosis(self):
        self.kurtosis = float(Decimal(str((self.distr.stats('k')))) / 1)

    def get_moments(self, specify):
        ''' specify is a string containing some of the letters 'mvsk' '''
        self.remove_listeners()

        moments = self.distr.stats(specify)

        moment_names = ['mean', 'variance', 'skewness', 'kurtosis']
        for idx, value in enumerate(moments):
            setattr(self, moment_names[idx][0], value)

        dict = {
            'm': self.get_mean,
            'v': self.get_variance,
            's': self.get_skewness,
            'k': self.get_kurtosis
        }

        # chooses the methods to calculate the three moments which didn't
        # trigger this method
        for idx in specify:
            dict[idx]()

        self.add_listeners()

    def changes(self):
        ''' coordinates the methods for computing
        parameters and moments when a change has occurred '''
        self.remove_listeners()
        self.new_values = array([
            self.shape, self.loc, self.scale, self.mean, self.variance,
            self.skewness, self.kurtosis
        ])
        # test which parameters or moments are significant
        indexing = arange(7)[abs(self.old_values - self.new_values) != 0]
        if len(indexing) > 0 and indexing[0] < 3:
            self.get_moments('mvsk')
        elif len(indexing) > 0 and indexing[0] > 2:
            self.param_methods[indexing[0] - 3]()
        else:
            pass
        self.old_values = array([
            self.shape, self.loc, self.scale, self.mean, self.variance,
            self.skewness, self.kurtosis
        ])
        self.add_listeners()
        self.changed = True

    param_methods = Property(Array, depends_on='distribution')

    @cached_property
    def _get_param_methods(self):
        methods = array([
            self.mean_change, self.variance_change_scale,
            self.variance_change_shape, self.skewness_change,
            self.kurtosis_change
        ])
        if self.distribution.shapes == None:
            return methods[0:2]
        else:
            if len(self.distribution.shapes) == 1:
                return hstack((methods[0], methods[2:5]))
            else:
                print 'more than 1 shape parameters'

    def shape_scale_mean_var_residuum(self, params):
        shape = params[0]
        scale = params[1]
        res_mean = self.mean - self.distribution(shape, \
            loc=self.loc, scale=scale).stats('m')
        res_var = self.variance - self.distribution(shape, \
            loc=self.loc, scale=scale).stats('v')
        return [res_mean, res_var]

    def mean_change(self):
        if self.loc_zero == True and self.distribution.__dict__[
                'shapes'] != None:
            self.loc = 0.0
            result = fsolve(self.shape_scale_mean_var_residuum, [1., 1.])
            self.shape = float(Decimal(str(result[0].sum())) / 1)
            self.scale = float(Decimal(str(result[1].sum())) / 1)
        else:
            self.loc += float(
                Decimal(str(self.mean - self.distr.stats('m'))) / 1)

    def scale_variance_residuum(self, scale):
        return self.variance - self.distribution(\
            loc=self.loc, scale=scale).stats('v')

    def variance_change_scale(self):
        self.scale = float(
            Decimal(str(fsolve(self.scale_variance_residuum, 1).sum())) / 1)

    def shape_variance_residuum(self, shape):
        return self.variance - self.distribution(shape, \
                loc=self.loc, scale=self.scale).stats('v')

    def variance_change_shape(self):
        self.shape = float(
            Decimal(str(fsolve(self.shape_variance_residuum, 1).sum())) / 1)
        self.get_moments('msk')

    def shape_skewness_residuum(self, shape):
        return self.skewness - self.distribution(shape, \
                loc=self.loc, scale=self.scale).stats('s')

    def skewness_change(self):
        self.shape = float(
            Decimal(str(fsolve(self.shape_skewness_residuum, 1).sum())) / 1)
        self.get_moments('mvk')

    def shape_kurtosis_residuum(self, shape):
        return self.kurtosis - self.distribution(shape, \
                loc=self.loc, scale=self.scale).stats('k')

    def kurtosis_change(self):
        self.shape = float(
            Decimal(str(fsolve(self.shape_kurtosis_residuum, 1).sum())) / 1)
        self.get_moments('mvs')

    distr = Property(depends_on='+params')

    @cached_property
    def _get_distr(self):
        if self.distribution.__dict__['numargs'] == 0:
            return self.distribution(self.loc, self.scale)
        elif self.distribution.__dict__['numargs'] == 1:
            return self.distribution(self.shape, self.loc, self.scale)

    def default_traits_view(self):
        '''checks the number of shape parameters of the distribution and adds them to
        the view instance'''
        label = str(self.distribution.name)
        if self.distribution.shapes == None:
            params = Item()
            if self.mean == infty:
                moments = Item(label='No finite moments defined')
            else:
                moments = Item('mean', label='mean'), \
                            Item('variance', label='variance'), \
                            Item('stdev', label='st. deviation', style='readonly')

        elif len(self.distribution.shapes) == 1:
            params = Item('shape', label='shape')
            if self.mean == infty:
                moments = Item(label='No finite moments defined')
            else:
                moments = Item('mean', label='mean'), \
                            Item('variance', label='variance'), \
                            Item('stdev', label='st. deviation', style='readonly'), \
                            Item('skewness', label='skewness'), \
                            Item('kurtosis', label='kurtosis'),
        else:
            params = Item()
            moments = Item()

        view = View(VGroup(Label(label, emphasized=True),
                           Group(params,
                                 Item('loc', label='location'),
                                 Item('scale', label='scale'),
                                 Item('loc_zero', label='loc = 0.0'),
                                 show_border=True,
                                 label='parameters',
                                 id='pdistrib.distribution.params'),
                           Group(
                               moments,
                               id='pdistrib.distribution.moments',
                               show_border=True,
                               label='moments',
                           ),
                           id='pdistrib.distribution.vgroup'),
                    kind='live',
                    resizable=True,
                    id='pdistrib.distribution.view')
        return view
Exemple #26
0
class ExpSH(ExType):
    '''Experiment: Shell Test
    '''
#    label = Str('slab test')
    implements(IExType)

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

                data_array_ironed[:, idx] = data_arr[:]

        return data_array_ironed


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

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

        # set attributes:
        #
        self._set_array_attribs()

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

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

    def _plot_force_w_elastomer(self, axes):

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

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


    def _plot_force_time(self, axes):

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

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

    def _plot_force_deflection_center(self, axes):

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

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

    n_fit_window_fraction = Float(0.1)

    def _plot_smoothed_force_deflection_center(self, axes):

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

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

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

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

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

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

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


    def _plot_force_deflections(self, axes):

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

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

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

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

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


    def _plot_time_deflections(self, axes):

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

        time = self.Bezugskanal

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

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

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


    def _plot_force_eps_c(self, axes):

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

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

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

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

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


    def _plot_force_eps_t(self, axes):

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

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

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

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

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


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

    traits_view = View(VGroup(
                         Group(
                              Item('jump_rtol', format_str = "%.4f"),
                              label = 'curve_ironing'
                              ),
                         Group(
                              Item('thickness', format_str = "%.3f"),
                              Item('edge_length', format_str = "%.3f"),
                              label = 'geometry'
                              ),
                         Group(
                              Item('loading_rate'),
                              Item('age'),
                              label = 'loading rate and age'
                              ),
                         Group(
                              Item('E_c', show_label = True, style = 'readonly', format_str = "%.0f"),
                              Item('ccs@', show_label = False),
                              label = 'composite cross section'
                              )
                         ),
                        scrollable = True,
                        resizable = True,
                        height = 0.8,
                        width = 0.6
                        )
Exemple #27
0
class SingleRun(HasTraits):
    '''Pairing of algorithm configuration and randomization pattern.
    '''
    rf = Property

    def _get_rf(self):
        return self.run_table.rf

    config = Tuple

    conf_idx = Property

    def _get_conf_idx(self):
        return self.config[0]

    conf_options = Property

    def _get_conf_options(self):
        return self.config[1][0]

    conf_latex_label = Property

    def _get_conf_latex_label(self):
        return self.config[1][1]

    rand_idx_arr = Array(int, rand=True)

    run_table = WeakRef

    # derived stuff
    s = Property

    def _get_s(self):
        return self.run_table.s

    n_rv = Property

    def _get_n_rv(self):
        return len(self.rand_idx_arr)

    memsize = Property

    def _get_memsize(self):
        return self.run_table.memsize

    n_int = Property

    def _get_n_int(self):
        return int(pow(self.memsize, 1 / float(self.n_rv)))

    real_memsize = Property

    def _get_real_memsize(self):
        return pow(self.n_int, self.n_rv)

    exec_time = Property

    def _get_exec_time(self):
        '''Run spirrid with the given dictionary of configurations.
        '''
        s = self.s

        # apply the randomization pattern
        s.clear_rv()
        for rv in self.rand_idx_arr:
            param_key = self.rf.param_keys[rv]
            s.add_rv(param_key, n_int=self.n_int)

        # setup the spirrid exec configuration
        s.set(**self.conf_options)

        return s.exec_time

    def __str__(self):
        return 'conf: %s, rand_idx_arr %s' % (self.conf_options,
                                              self.rand_idx_arr)
Exemple #28
0
class PDistrib(HasTraits):

    implements = IPDistrib

    def __init__(self, **kw):
        super(PDistrib, self).__init__(**kw)
        self.on_trait_change(self.refresh,
                             'distr_type.changed,quantile,n_segments')
        self.refresh()

    # puts all chosen continuous distributions distributions defined
    # in the scipy.stats.distributions module as a list of strings
    # into the Enum trait
    # distr_choice = Enum(distr_enum)

    distr_choice = Enum('sin2x', 'weibull_min', 'sin_distr', 'uniform', 'norm',
                        'piecewise_uniform', 'gamma')
    distr_dict = {
        'sin2x': sin2x,
        'uniform': uniform,
        'norm': norm,
        'weibull_min': weibull_min,
        'sin_distr': sin_distr,
        'piecewise_uniform': piecewise_uniform,
        'gamma': gamma
    }

    # instantiating the continuous distributions
    distr_type = Property(Instance(Distribution), depends_on='distr_choice')

    @cached_property
    def _get_distr_type(self):
        return Distribution(self.distr_dict[self.distr_choice])

    # change monitor - accumulate the changes in a single event trait
    changed = Event

    @on_trait_change('distr_choice, distr_type.changed, quantile, n_segments')
    def _set_changed(self):
        self.changed = True

    #------------------------------------------------------------------------
    # Methods setting the statistical modments
    #------------------------------------------------------------------------
    mean = Property

    def _get_mean(self):
        return self.distr_type.mean

    def _set_mean(self, value):
        self.distr_type.mean = value

    variance = Property

    def _get_variance(self):
        return self.distr_type.mean

    def _set_variance(self, value):
        self.distr_type.mean = value

    #------------------------------------------------------------------------
    # Methods preparing visualization
    #------------------------------------------------------------------------

    quantile = Float(1e-14, auto_set=False, enter_set=True)
    range = Property(Tuple(Float), depends_on=\
                      'distr_type.changed, quantile')

    @cached_property
    def _get_range(self):
        return (self.distr_type.distr.ppf(self.quantile),
                self.distr_type.distr.ppf(1 - self.quantile))

    n_segments = Int(500, auto_set=False, enter_set=True)

    dx = Property(Float, depends_on=\
                      'distr_type.changed, quantile, n_segments')

    @cached_property
    def _get_dx(self):
        range_length = self.range[1] - self.range[0]
        return range_length / self.n_segments

    #-------------------------------------------------------------------------
    # Discretization of the distribution domain
    #-------------------------------------------------------------------------
    x_array = Property(Array('float_'), depends_on=\
                        'distr_type.changed,'\
                        'quantile, n_segments')

    @cached_property
    def _get_x_array(self):
        '''Get the intrinsic discretization of the distribution
        respecting its  bounds.
        '''
        return linspace(self.range[0], self.range[1], self.n_segments + 1)

    #===========================================================================
    # Access function to the scipy distribution
    #===========================================================================
    def pdf(self, x):
        return self.distr_type.distr.pdf(x)

    def cdf(self, x):
        return self.distr_type.distr.cdf(x)

    def rvs(self, n):
        return self.distr_type.distr.rvs(n)

    def ppf(self, e):
        return self.distr_type.distr.ppf(e)

    #===========================================================================
    # PDF - permanent array
    #===========================================================================

    pdf_array = Property(Array('float_'), depends_on=\
                                    'distr_type.changed,'\
                                     'quantile, n_segments')

    @cached_property
    def _get_pdf_array(self):
        '''Get pdf values in intrinsic positions'''
        return self.distr_type.distr.pdf(self.x_array)

    def get_pdf_array(self, x_array):
        '''Get pdf values in externally specified positions'''
        return self.distr_type.distr.pdf(x_array)

    #===========================================================================
    # CDF permanent array
    #===========================================================================
    cdf_array = Property(Array('float_'), depends_on=\
                                    'distr_type.changed,'\
                                     'quantile, n_segments')

    @cached_property
    def _get_cdf_array(self):
        '''Get cdf values in intrinsic positions'''
        return self.distr_type.distr.cdf(self.x_array)

    def get_cdf_array(self, x_array):
        '''Get cdf values in externally specified positions'''
        return self.distr_type.distr.cdf(x_array)

    #-------------------------------------------------------------------------
    # Randomization
    #-------------------------------------------------------------------------
    def get_rvs_array(self, n_samples):
        return self.distr_type.distr.rvs(n_samples)

    figure = Instance(Figure)

    def _figure_default(self):
        figure = Figure(facecolor='white')
        return figure

    data_changed = Event

    def plot(self, fig):
        figure = fig
        figure.clear()
        axes = figure.gca()
        # plot PDF
        axes.plot(self.x_array, self.pdf_array, lw=1.0, color='blue', \
                  label='PDF')
        axes2 = axes.twinx()
        # plot CDF on a separate axis (tick labels left)
        axes2.plot(self.x_array, self.cdf_array, lw=2, color='red', \
                  label='CDF')
        # fill the unity area given by integrating PDF along the X-axis
        axes.fill_between(self.x_array,
                          0,
                          self.pdf_array,
                          color='lightblue',
                          alpha=0.8,
                          linewidth=2)
        # plot mean
        mean = self.distr_type.distr.stats('m')
        axes.plot([mean, mean], [0.0, self.distr_type.distr.pdf(mean)],
                  lw=1.5,
                  color='black',
                  linestyle='-')
        # plot stdev
        stdev = sqrt(self.distr_type.distr.stats('v'))
        axes.plot([mean - stdev, mean - stdev],
                  [0.0, self.distr_type.distr.pdf(mean - stdev)],
                  lw=1.5,
                  color='black',
                  linestyle='--')
        axes.plot([mean + stdev, mean + stdev],
                  [0.0, self.distr_type.distr.pdf(mean + stdev)],
                  lw=1.5,
                  color='black',
                  linestyle='--')

        axes.legend(loc='center left')
        axes2.legend(loc='center right')
        axes.ticklabel_format(scilimits=(-3., 4.))
        axes2.ticklabel_format(scilimits=(-3., 4.))

        # plot limits on X and Y axes
        axes.set_ylim(0.0, max(self.pdf_array) * 1.15)
        axes2.set_ylim(0.0, 1.15)
        range = self.range[1] - self.range[0]
        axes.set_xlim(self.x_array[0] - 0.05 * range,
                      self.x_array[-1] + 0.05 * range)
        axes2.set_xlim(self.x_array[0] - 0.05 * range,
                       self.x_array[-1] + 0.05 * range)

    def refresh(self):
        self.plot(self.figure)
        self.data_changed = True

    icon = Property(Instance(ImageResource),
                    depends_on='distr_type.changed,quantile,n_segments')

    @cached_property
    def _get_icon(self):
        fig = plt.figure(figsize=(4, 4), facecolor='white')
        self.plot(fig)
        tf_handle, tf_name = tempfile.mkstemp('.png')
        fig.savefig(tf_name, dpi=35)
        return ImageResource(name=tf_name)

    traits_view = View(HSplit(VGroup(
        Group(
            Item('distr_choice', show_label=False),
            Item('@distr_type', show_label=False),
        ),
        id='pdistrib.distr_type.pltctrls',
        label='Distribution parameters',
        scrollable=True,
    ),
                              Tabbed(
                                  Group(
                                      Item('figure',
                                           editor=MPLFigureEditor(),
                                           show_label=False,
                                           resizable=True),
                                      scrollable=True,
                                      label='Plot',
                                  ),
                                  Group(Item('quantile', label='quantile'),
                                        Item('n_segments',
                                             label='plot points'),
                                        label='Plot parameters'),
                                  label='Plot',
                                  id='pdistrib.figure.params',
                                  dock='tab',
                              ),
                              dock='tab',
                              id='pdistrib.figure.view'),
                       id='pdistrib.view',
                       dock='tab',
                       title='Statistical distribution',
                       buttons=['Ok', 'Cancel'],
                       scrollable=True,
                       resizable=True,
                       width=600,
                       height=400)
Exemple #29
0
class RV( HasTraits ):
    '''Class representing the definition and discretization of a random variable.
    '''
    name = Str

    pd = Instance( IPDistrib )
    def _pd_changed( self ):
        self.pd.n_segments = self._n_int

    changed = Event
    @on_trait_change( 'pd.changed,+changed' )
    def _set_changed( self ):
        self.changed = True

    _n_int = Int
    n_int = Property
    def _set_n_int( self, value ):
        if self.pd:
            self.pd.n_segments = value
        self._n_int = value
    def _get_n_int( self ):
        return self.pd.n_segments

    # index within the randomization
    idx = Int( 0 )

    # type of the RV discretization 
    discr_type = Enum( 'T grid', 'P grid', 'MC',
                        changed = True )
    def _discr_type_default( self ):
        return 'T grid'

    theta_arr = Property( Array( 'float_' ), depends_on = 'changed' )
    @cached_property
    def _get_theta_arr( self ):
        '''Get the discr_type of the pdistrib
        '''
        if self.discr_type == 'T grid':

            # Get the discr_type from pdistrib and shift it
            # such that the midpoints of the segments are used for the
            # integration.

            x_array = self.pd.x_array
            # Note assumption of T grid discr_type
            theta_array = x_array[:-1] + self.pd.dx / 2.0

        elif self.discr_type == 'P grid':

            # P grid disretization generated from the inverse cummulative
            # probability
            #
            distr = self.pd.distr_type.distr
            # Grid of constant probabilities
            pi_arr = linspace( 0.5 / self.n_int, 1. - 0.5 / self.n_int, self.n_int )
            theta_array = distr.ppf( pi_arr )

        return theta_array

    dG_arr = Property( Array( 'float_' ), depends_on = 'changed' )
    @cached_property
    def _get_dG_arr( self ):

        if self.discr_type == 'T grid':

            d_theta = self.theta_arr[1] - self.theta_arr[0]
            return self.pd.get_pdf_array( self.theta_arr ) * d_theta

        elif self.discr_type == 'P grid':

            # P grid disretization generated from the inverse cummulative
            # probability
            #
            return array( [ 1.0 / float( self.n_int ) ], dtype = 'float_' )

    def get_rvs_theta_arr( self, n_samples ):
        return self.pd.get_rvs_array( n_samples )
class HPShell(HasTraits):
    '''Geometry definition.
    '''

    #===========================================================================
    # geometric variables and values
    #===========================================================================

    # part of mushroof
    #
    # @todo: "four" is not supported by "n_elems_xy_dict"in mushroff_model
    mushroof_part = Enum('detail', 'quarter', 'one', 'four')

    # origin
    # @todo: define as "_default"
    #
    X0 = Array(float, value=[0., 0., 0.])

    # element properties of grid
    #
    n_elems_xy = Int(6)
    n_elems_z = Int(3)

    n_elems_xy_quarter = Property(Int)

    @cached_property
    def _get_n_elems_xy_quarter(self):
        return self.n_elems_xy / self.scale_size

    # standard array for column shift
    # shift array shifts the elements towards the defined coordinates
    # [x_shift,y_shift,element_between]
    # array needs to have the right shape (:,3)!!
    #
    # @todo: define as "_default"
    #
    shift_array = Array(float,
                        shape=(None, 3),
                        value=[[0.45 / 2**0.5, 0.45 / 2**0.5, 1]])

    # dimensions of the shell for one quarter of mush_roof
    # @todo: add "_quarter"
    #
    length_x = Float(4.0)  # [m]
    length_y = Float(4.0)  # [m]
    length_z = Float(1.062)  # [m]
    t_shell = Float(0.06)  # [m]
    width_column = Float(0.45)  # [m]

    length_x_detail = Float(1.5)  # [m]
    length_y_detail = Float(1.5)  # [m]

    scale_size_detail_x = Property(Float)

    def _get_scale_size_detail_x(self):
        return self.length_x_detail / self.length_x * 2.

    scale_size_detail_y = Property(Float)

    def _get_scale_size_detail_y(self):
        return self.length_y_detail / self.length_y * 2.

    # scale factor for different mushroof parts
    # Defines the proportion between the lenght of the model
    # with respect to the length of a quarter shell as the
    # basic substructure of which the model consists of.
    # @todo: add "depend_on" or remove "cached_property"
    # @todo: move to class definition of "mushroof_model" not in "HPShell"
    #        (also see there "n_elems_dict" with implicit "scale_factor")
    #
    scale_size = Property(Float)

    #    @cached_property
    def _get_scale_size(self):
        #        scale_size_detail = self.lenght_x_detail / self.length_x
        scale_dict = {
            'detail': self.scale_size_detail_x,
            'quarter': 1.0,
            'one': 2.0,
            'four': 4.0
        }
        return scale_dict[self.mushroof_part]

    # factor to scale delta_h (inclination of the shell)
    # The thickness remains unchanged by this scaling, e.g. self.thickness = 0.06 [m]
    #
    delta_h_scalefactor = Float(1.00)  # [-]

    # shift of column elements
    #
    shift_elems = Bool(True)

    # const_edge element operator
    # (for non-linear analysis only, where an element layer of constant
    # thickness is needed to simulate the reinforced behaviour of the
    # concrete.
    #
    const_edge_elem = Bool(False)
    t_edge = Float(0.03)  # [m]
    n_elems_edge = Int(1)  #number of dofs used for edge refinement

    #===========================================================================
    # reading options
    #===========================================================================

    # "lowerface_cut_off" - option replaces constant height for the coordinates
    # which connect to the column (this cuts of the shell geometry horizontally
    # at the bottom of the lower face of the shell geometry.
    # Option should be used for the robj-file with 4x4m geometry
    #
    cut_off_lowerface = Bool(True)

    # corresponds to the delta in the geometry .obj-file with name '4x4m' as a cut off
    #
    delta_h = Float(1.00)  # [m]

    # choose geometric file (obj-data file)
    #
    geo_input_name = Enum('4x4m', '02')

    # filter for '4x4m' file needs to be done to have regular grid
    # in order to rbf-function leading to stable solution without oscilation
    #
    geo_filter = Dict({'4x4m': delete_second_rows})

    def _read_arr(self, side='lowerface_'):
        file_name = side + self.geo_input_name + '.robj'
        file_path = join('geometry_files', file_name)
        v_arr = read_rsurface(file_path)
        filter = self.geo_filter.get(self.geo_input_name, None)
        if filter != None:
            v_arr = filter(v_arr)
        return v_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the lower surface of the shell
    vl_arr = Property(Array(float))

    @cached_property
    def _get_vl_arr(self):
        vl_arr = self._read_arr('lowerface_')
        if self.cut_off_lowerface == True:
            print '--- lower face z-coords cut off ---'

            # z-values of the coords from the lower face are cut off.
            # From the highest z-coordinate of the lower face the vertical
            # distance is 1 m (=delta h). At this limit the lower face is
            # cut off. Global z coordinate is assumed to point up.
            #
            vl_z_max = max(vl_arr[:, 2])
            vl_z_min = vl_z_max - self.delta_h
            vl_arr_z = where(vl_arr[:, 2] < vl_z_min, vl_z_min, vl_arr[:, 2])
            vl_arr = c_[vl_arr[:, 0:2], vl_arr_z]
        return vl_arr

    # array of the vertex positions in global
    # x,y,z-coordinates defining the upper surface of the shell
    vu_arr = Property(Array(float))

    @cached_property
    def _get_vu_arr(self):
        return self._read_arr('upperface_')

    #------------------------------------------------------------------------------
    # hp_shell geometric transformation
    #------------------------------------------------------------------------------

    def __call__(self, points):
        '''Return the global coordinates of the supplied local points.
        '''

        # number of local grid points for each coordinate direction
        # values must range between 0 and 1
        #
        xi, yi, zi = points[:, 0], points[:, 1], points[:, 2]
        print "xi", xi
        print "xi.shape", xi.shape

        # size of total structure
        #
        # @todo: move to class definition of "mushroof_model" and send to "__call__"
        scale_size = self.scale_size
        print "scale_size", scale_size

        # @todo: add "_quarter" (see above)
        length_x_tot = self.length_x * scale_size
        length_y_tot = self.length_y * scale_size
        n_elems_xy_quarter = self.n_elems_xy_quarter

        # distance from origin for each mushroof_part
        #
        def d_origin_fn(self, coords):
            #            if self.mushroof_part == 'quarter':
            #                return coords
            #            if self.mushroof_part == 'one':
            #                return abs( 2.0 * coords - 1.0 )

            if self.mushroof_part == 'detail':
                print 'in d_origin_fn'
                return abs(1.0 * coords - 0.5) * scale_size


#            # @todo: corresponding "scale_factor" needs to be added
#            #        in order for this to work
#            if self.mushroof_part == 'four':
#                return  where( coords < 0.5, abs( 4 * coords - 1 ), abs( -4 * coords + 3 ) )

# values are used to calculate the z-coordinate using RBF-function of the quarter
# (= values of the distance to the origin as absolute value)
#

        xi_rbf = d_origin_fn(self, xi)
        print 'xi_rbf', xi_rbf
        yi_rbf = d_origin_fn(self, yi)

        # normalized coordinates of the vertices for lower- and upperface
        # NOTE: the underline character indicates a normalized value
        #
        vl_arr_, vu_arr_ = normalize_rsurfaces(self.vl_arr, self.vu_arr)

        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the lower face
        #
        x_ = vl_arr_[:, 0]

        # flip the orientation of the local coordinate system in the
        # corresponding y-direction depending on the data file
        #
        geo_input_name = self.geo_input_name
        if geo_input_name == '4x4m':
            y_ = vl_arr_[:, 1]
        else:
            y_ = 1 - vl_arr_[:, 1]

        z_ = vl_arr_[:, 2]
        rbf = Rbf(x_, y_, z_, function='cubic')

        # get the z-value at the supplied local grid points
        # of the lower face
        #
        zi_lower_ = rbf(xi_rbf, yi_rbf)

        # use a radial basis function approximation (rbf) (i.e. interpolation of
        # scattered data) based on the normalized vertex points of the upper face
        #
        x_ = vu_arr_[:, 0]

        # flip the orientation of the local coordinate system in the
        # corresponding y-direction depending on the data file
        #
        geo_input_name = self.geo_input_name
        if geo_input_name == '4x4m':
            y_ = vu_arr_[:, 1]
        else:
            y_ = 1 - vu_arr_[:, 1]

        z_ = vu_arr_[:, 2]
        rbf = Rbf(x_, y_, z_, function='cubic')

        # get the z-value at the supplied local grid points
        # of the upper face
        #
        # note that zi_upper_ is a normalized coordinate!
        #
        zi_upper_ = rbf(xi_rbf, yi_rbf)

        # thickness is multiplied by the supplied zi coordinate
        #
        z_ = (zi_lower_ + (zi_upper_ - zi_lower_) * zi /
              self.delta_h_scalefactor) * self.delta_h_scalefactor

        # coordinates of origin
        #
        X, Y, Z = self.X0

        print '--- geometric transformation done ---'

        # multiply the local grid points with the real dimensions in order to obtain the
        # global coordinates of the mushroof_part:
        #
        return c_[X + xi * length_x_tot, Y + yi * length_y_tot,
                  Z + z_ * self.length_z]