Example #1
0
    def from_desc(constructor, desc, region, integrals=None):
        from sfepy.discrete import Integrals

        if integrals is None:
            integrals = Integrals()

        integral = integrals.get(desc.integral)
        obj = constructor(desc.name, desc.args, integral, region)
        obj.sign = desc.sign

        return obj
Example #2
0
    def from_desc(constructor, desc, region, integrals=None):
        from sfepy.discrete import Integrals

        if integrals is None:
            integrals = Integrals()

        integral = integrals.get(desc.integral)
        obj = constructor(desc.name, desc.args, integral, region)
        obj.sign = desc.sign

        return obj
Example #3
0
    def from_desc(constructor, desc, region, integrals=None):
        from sfepy.discrete import Integrals

        if integrals is None:
            integrals = Integrals()

        if desc.name == 'intFE':
            obj = constructor(desc.name, desc.args, None, region, desc=desc)
        else:
            obj = constructor(desc.name, desc.args, None, region)
        obj.set_integral(integrals.get(desc.integral))
        obj.sign = desc.sign

        return obj
Example #4
0
def compute_erros(analytic_fun, pb):
    """
    Compute errors from analytical solution in conf.sol_fun and numerical
    solution saved in pb
    :param analytic_fun: analytic solution
    :param pb: problem with numerical solution
    :return: analytic_fun L2 norm,
             vaules of analytic_fun in qps
             L2 norm of difference between analytic and numerical solution
             relative difference
             values of numerical solution in qps
    """
    idiff = Integral('idiff', 20)
    num_qp = pb.evaluate('ev_volume_integrate.idiff.Omega(p)',
                         integrals=Integrals([idiff]),
                         mode='qp',
                         copy_materials=False,
                         verbose=False)
    aux = Material('aux', function=analytic_fun)
    ana_qp = pb.evaluate('ev_volume_integrate_mat.idiff.Omega(aux.p, p)',
                         aux=aux,
                         integrals=Integrals([idiff]),
                         mode='qp',
                         copy_materials=False,
                         verbose=False)
    field = pb.fields['f']
    det = get_jacobian(field, idiff)
    diff_l2 = nm.sqrt((((num_qp - ana_qp)**2) * det).sum())
    ana_l2 = nm.sqrt(((ana_qp**2) * det).sum())
    rel_l2 = diff_l2 / ana_l2

    diff_loo = nm.max(num_qp - ana_qp)
    ana_loo = nm.max(ana_qp)
    rel_loo = diff_loo / ana_loo

    diff_l1 = nm.sqrt((nm.abs(num_qp - ana_qp) * det).sum())
    ana_l1 = nm.sqrt((nm.abs(ana_qp) * det).sum())
    rel_l1 = diff_l2 / ana_l2
    return ana_l2, ana_qp, diff_l2, rel_l2, num_qp
def main():
    parser = ArgumentParser(description=__doc__,
                            formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('--version', action='version', version='%(prog)s')
    parser.add_argument('-d',
                        '--dims',
                        metavar='dims',
                        action='store',
                        dest='dims',
                        default='[1.0, 1.0]',
                        help=helps['dims'])
    parser.add_argument('-c',
                        '--centre',
                        metavar='centre',
                        action='store',
                        dest='centre',
                        default='[0.0, 0.0]',
                        help=helps['centre'])
    parser.add_argument('-s',
                        '--shape',
                        metavar='shape',
                        action='store',
                        dest='shape',
                        default='[11, 11]',
                        help=helps['shape'])
    parser.add_argument('-b',
                        '--bc-kind',
                        metavar='kind',
                        action='store',
                        dest='bc_kind',
                        choices=['free', 'cantilever', 'fixed'],
                        default='free',
                        help=helps['bc_kind'])
    parser.add_argument('-a',
                        '--axis',
                        metavar='0, ..., dim, or -1',
                        type=int,
                        action='store',
                        dest='axis',
                        default=-1,
                        help=helps['axis'])
    parser.add_argument('--young',
                        metavar='float',
                        type=float,
                        action='store',
                        dest='young',
                        default=200e+9,
                        help=helps['young'])
    parser.add_argument('--poisson',
                        metavar='float',
                        type=float,
                        action='store',
                        dest='poisson',
                        default=0.3,
                        help=helps['poisson'])
    parser.add_argument('--density',
                        metavar='float',
                        type=float,
                        action='store',
                        dest='density',
                        default=7800.0,
                        help=helps['density'])
    parser.add_argument('--order',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='order',
                        default=1,
                        help=helps['order'])
    parser.add_argument('-n',
                        '--n-eigs',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='n_eigs',
                        default=6,
                        help=helps['n_eigs'])
    parser.add_argument('-i',
                        '--ignore',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='ignore',
                        default=None,
                        help=helps['ignore'])
    parser.add_argument('--solver', metavar='solver', action='store',
                        dest='solver',
                        default= \
                        "eig.scipy,method:'eigh',tol:1e-5,maxiter:1000",
                        help=helps['solver'])
    parser.add_argument('--show',
                        action="store_true",
                        dest='show',
                        default=False,
                        help=helps['show'])
    #parser.add_argument('filename', nargs='?', default=None)
    #read block.mesh
    #parser.add_argument('filename', nargs='?', default="platehexat200mm.mesh")
    parser.add_argument('filename', nargs='?', default="block_1m.mesh")
    options = parser.parse_args()

    aux = options.solver.split(',')
    kwargs = {}
    for option in aux[1:]:
        key, val = option.split(':')
        kwargs[key.strip()] = eval(val)
    eig_conf = Struct(name='evp', kind=aux[0], **kwargs)

    output('using values:')
    output("  Young's modulus:", options.young)
    output("  Poisson's ratio:", options.poisson)
    output('  density:', options.density)
    output('displacement field approximation order:', options.order)
    output('requested %d eigenvalues' % options.n_eigs)
    output('using eigenvalue problem solver:', eig_conf.kind)
    output.level += 1
    for key, val in six.iteritems(kwargs):
        output('%s: %r' % (key, val))
    output.level -= 1

    assert_((0.0 < options.poisson < 0.5),
            "Poisson's ratio must be in ]0, 0.5[!")
    assert_((0 < options.order),
            'displacement approximation order must be at least 1!')

    filename = options.filename
    if filename is not None:
        mesh = Mesh.from_file(filename)
        dim = mesh.dim
        dims = nm.diff(mesh.get_bounding_box(), axis=0)

    else:
        dims = nm.array(eval(options.dims), dtype=nm.float64)
        dim = len(dims)

        centre = nm.array(eval(options.centre), dtype=nm.float64)[:dim]
        shape = nm.array(eval(options.shape), dtype=nm.int32)[:dim]

        output('dimensions:', dims)
        output('centre:    ', centre)
        output('shape:     ', shape)

        mesh = gen_block_mesh(dims, shape, centre, name='mesh')

    output('axis:      ', options.axis)
    assert_((-dim <= options.axis < dim), 'invalid axis value!')

    eig_solver = Solver.any_from_conf(eig_conf)

    # Build the problem definition.
    domain = FEDomain('domain', mesh)

    bbox = domain.get_mesh_bounding_box()
    min_coor, max_coor = bbox[:, options.axis]
    eps = 1e-8 * (max_coor - min_coor)
    ax = 'xyz'[:dim][options.axis]

    omega = domain.create_region('Omega', 'all')
    """
    bottom = domain.create_region('Bottom',
                                  'vertices in (%s < %.10f)'
                                  % (ax, min_coor + eps),
                                  'facet')

    bottom_top = domain.create_region('BottomTop',
                                      'r.Bottom +v vertices in (%s > %.10f)'
                                      % (ax, max_coor - eps),
                                      'facet')
    """
    #import pdb; pdb.set_trace()
    left = domain.create_region('left', 'vertices in (x < -0.49)', 'facet')

    field = Field.from_args('fu',
                            nm.float64,
                            'vector',
                            omega,
                            approx_order=options.order)

    u = FieldVariable('u', 'unknown', field)
    v = FieldVariable('v', 'test', field, primary_var_name='u')

    mtx_d = stiffness_from_youngpoisson(dim, options.young, options.poisson)

    m = Material('m', D=mtx_d, rho=options.density)

    integral = Integral('i', order=2 * options.order)

    t1 = Term.new('dw_lin_elastic(m.D, v, u)', integral, omega, m=m, v=v, u=u)
    t2 = Term.new('dw_volume_dot(m.rho, v, u)', integral, omega, m=m, v=v, u=u)
    eq1 = Equation('stiffness', t1)
    eq2 = Equation('mass', t2)
    lhs_eqs = Equations([eq1, eq2])

    pb = Problem('modal', equations=lhs_eqs)
    """
    if options.bc_kind == 'free':
        pb.time_update()
        n_rbm = dim * (dim + 1) // 2

    elif options.bc_kind == 'cantilever':
        fixed = EssentialBC('Fixed', bottom, {'u.all' : 0.0})
        pb.time_update(ebcs=Conditions([fixed]))
        n_rbm = 0

    elif options.bc_kind == 'fixed':
        fixed = EssentialBC('Fixed', bottom_top, {'u.all' : 0.0})
        pb.time_update(ebcs=Conditions([fixed]))
        n_rbm = 0

    else:
        raise ValueError('unsupported BC kind! (%s)' % options.bc_kind)

    if options.ignore is not None:
        n_rbm = options.ignore
    """
    fixed = EssentialBC('Fixed', left, {'u.all': 0.0})
    pb.time_update(ebcs=Conditions([fixed]))
    n_rbm = 0

    pb.update_materials()

    # Assemble stiffness and mass matrices.
    mtx_k = eq1.evaluate(mode='weak', dw_mode='matrix', asm_obj=pb.mtx_a)
    mtx_m = mtx_k.copy()
    mtx_m.data[:] = 0.0
    mtx_m = eq2.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_m)

    try:
        eigs, svecs = eig_solver(mtx_k,
                                 mtx_m,
                                 options.n_eigs + n_rbm,
                                 eigenvectors=True)

    except sla.ArpackNoConvergence as ee:
        eigs = ee.eigenvalues
        svecs = ee.eigenvectors
        output('only %d eigenvalues converged!' % len(eigs))

    output('%d eigenvalues converged (%d ignored as rigid body modes)' %
           (len(eigs), n_rbm))

    eigs = eigs[n_rbm:]
    svecs = svecs[:, n_rbm:]

    omegas = nm.sqrt(eigs)
    freqs = omegas / (2 * nm.pi)

    output('number |         eigenvalue |  angular frequency '
           '|          frequency')
    for ii, eig in enumerate(eigs):
        output('%6d | %17.12e | %17.12e | %17.12e' %
               (ii + 1, eig, omegas[ii], freqs[ii]))

    # Make full eigenvectors (add DOFs fixed by boundary conditions).
    variables = pb.get_variables()

    vecs = nm.empty((variables.di.ptr[-1], svecs.shape[1]), dtype=nm.float64)
    for ii in range(svecs.shape[1]):
        vecs[:, ii] = variables.make_full_vec(svecs[:, ii])

    # Save the eigenvectors.
    out = {}
    state = pb.create_state()
    for ii in range(eigs.shape[0]):
        state.set_full(vecs[:, ii])
        aux = state.create_output_dict()
        strain = pb.evaluate('ev_cauchy_strain.i.Omega(u)',
                             integrals=Integrals([integral]),
                             mode='el_avg',
                             verbose=False)
        out['u%03d' % ii] = aux.popitem()[1]
        out['strain%03d' % ii] = Struct(mode='cell', data=strain)

    pb.save_state('eigenshapes.vtk', out=out)
    pb.save_regions_as_groups('regions')

    if len(eigs) and options.show:
        # Show the solution. If the approximation order is greater than 1, the
        # extra DOFs are simply thrown away.
        from sfepy.postprocess.viewer import Viewer
        from sfepy.postprocess.domain_specific import DomainSpecificPlot

        scaling = 0.05 * dims.max() / nm.abs(vecs).max()

        ds = {}
        for ii in range(eigs.shape[0]):
            pd = DomainSpecificPlot('plot_displacements', [
                'rel_scaling=%s' % scaling, 'color_kind="tensors"',
                'color_name="strain%03d"' % ii
            ])
            ds['u%03d' % ii] = pd

        view = Viewer('eigenshapes.vtk')
        view(domain_specific=ds,
             only_names=sorted(ds.keys()),
             is_scalar_bar=False,
             is_wireframe=True)
Example #6
0
def main():
    from sfepy import data_dir

    parser = OptionParser(usage=usage, version='%prog')
    parser.add_option('--young',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='young',
                      default=2000.0,
                      help=helps['young'])
    parser.add_option('--poisson',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='poisson',
                      default=0.4,
                      help=helps['poisson'])
    parser.add_option('--load',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='load',
                      default=-1000.0,
                      help=helps['load'])
    parser.add_option('--order',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='order',
                      default=1,
                      help=helps['order'])
    parser.add_option('-r',
                      '--refine',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='refine',
                      default=0,
                      help=helps['refine'])
    parser.add_option('-s',
                      '--show',
                      action="store_true",
                      dest='show',
                      default=False,
                      help=helps['show'])
    parser.add_option('-p',
                      '--probe',
                      action="store_true",
                      dest='probe',
                      default=False,
                      help=helps['probe'])
    options, args = parser.parse_args()

    assert_((0.0 < options.poisson < 0.5),
            "Poisson's ratio must be in ]0, 0.5[!")
    assert_((0 < options.order),
            'displacement approximation order must be at least 1!')

    output('using values:')
    output("  Young's modulus:", options.young)
    output("  Poisson's ratio:", options.poisson)
    output('  vertical load:', options.load)
    output('uniform mesh refinement level:', options.refine)

    # Build the problem definition.
    mesh = Mesh.from_file(data_dir + '/meshes/2d/its2D.mesh')
    domain = FEDomain('domain', mesh)

    if options.refine > 0:
        for ii in xrange(options.refine):
            output('refine %d...' % ii)
            domain = domain.refine()
            output('... %d nodes %d elements' %
                   (domain.shape.n_nod, domain.shape.n_el))

    omega = domain.create_region('Omega', 'all')
    left = domain.create_region('Left', 'vertices in x < 0.001', 'facet')
    bottom = domain.create_region('Bottom', 'vertices in y < 0.001', 'facet')
    top = domain.create_region('Top', 'vertex 2', 'vertex')

    field = Field.from_args('fu',
                            nm.float64,
                            'vector',
                            omega,
                            approx_order=options.order)

    u = FieldVariable('u', 'unknown', field)
    v = FieldVariable('v', 'test', field, primary_var_name='u')

    D = stiffness_from_youngpoisson(2, options.young, options.poisson)

    asphalt = Material('Asphalt', D=D)
    load = Material('Load', values={'.val': [0.0, options.load]})

    integral = Integral('i', order=2 * options.order)
    integral0 = Integral('i', order=0)

    t1 = Term.new('dw_lin_elastic(Asphalt.D, v, u)',
                  integral,
                  omega,
                  Asphalt=asphalt,
                  v=v,
                  u=u)
    t2 = Term.new('dw_point_load(Load.val, v)', integral0, top, Load=load, v=v)
    eq = Equation('balance', t1 - t2)
    eqs = Equations([eq])

    xsym = EssentialBC('XSym', bottom, {'u.1': 0.0})
    ysym = EssentialBC('YSym', left, {'u.0': 0.0})

    ls = ScipyDirect({})

    nls_status = IndexedStruct()
    nls = Newton({}, lin_solver=ls, status=nls_status)

    pb = Problem('elasticity', equations=eqs, nls=nls, ls=ls)

    pb.time_update(ebcs=Conditions([xsym, ysym]))

    # Solve the problem.
    state = pb.solve()
    output(nls_status)

    # Postprocess the solution.
    out = state.create_output_dict()
    out = stress_strain(out, pb, state, extend=True)
    pb.save_state('its2D_interactive.vtk', out=out)

    gdata = geometry_data['2_3']
    nc = len(gdata.coors)

    integral_vn = Integral('ivn',
                           coors=gdata.coors,
                           weights=[gdata.volume / nc] * nc)

    nodal_stress(out, pb, state, integrals=Integrals([integral_vn]))

    if options.probe:
        # Probe the solution.
        probes, labels = gen_lines(pb)

        sfield = Field.from_args('sym_tensor',
                                 nm.float64,
                                 3,
                                 omega,
                                 approx_order=options.order - 1)
        stress = FieldVariable('stress',
                               'parameter',
                               sfield,
                               primary_var_name='(set-to-None)')
        strain = FieldVariable('strain',
                               'parameter',
                               sfield,
                               primary_var_name='(set-to-None)')

        cfield = Field.from_args('component',
                                 nm.float64,
                                 1,
                                 omega,
                                 approx_order=options.order - 1)
        component = FieldVariable('component',
                                  'parameter',
                                  cfield,
                                  primary_var_name='(set-to-None)')

        ev = pb.evaluate
        order = 2 * (options.order - 1)
        strain_qp = ev('ev_cauchy_strain.%d.Omega(u)' % order, mode='qp')
        stress_qp = ev('ev_cauchy_stress.%d.Omega(Asphalt.D, u)' % order,
                       mode='qp',
                       copy_materials=False)

        project_by_component(strain, strain_qp, component, order)
        project_by_component(stress, stress_qp, component, order)

        all_results = []
        for ii, probe in enumerate(probes):
            fig, results = probe_results(u, strain, stress, probe, labels[ii])

            fig.savefig('its2D_interactive_probe_%d.png' % ii)
            all_results.append(results)

        for ii, results in enumerate(all_results):
            output('probe %d:' % ii)
            output.level += 2
            for key, res in ordered_iteritems(results):
                output(key + ':')
                val = res[1]
                output('  min: %+.2e, mean: %+.2e, max: %+.2e' %
                       (val.min(), val.mean(), val.max()))
            output.level -= 2

    if options.show:
        # Show the solution. If the approximation order is greater than 1, the
        # extra DOFs are simply thrown away.
        from sfepy.postprocess.viewer import Viewer

        view = Viewer('its2D_interactive.vtk')
        view(vector_mode='warp_norm',
             rel_scaling=1,
             is_scalar_bar=True,
             is_wireframe=True)
Example #7
0
def eval_in_els_and_qp(expression, iels, coors,
                       fields, materials, variables,
                       functions=None, mode='eval', term_mode=None,
                       extra_args=None, verbose=True, kwargs=None):
    """
    Evaluate an expression in given elements and points.

    Parameters
    ----------
    expression : str
        The expression to evaluate.
    fields : dict
        The dictionary of fields used in `variables`.
    materials : Materials instance
        The materials used in the expression.
    variables : Variables instance
        The variables used in the expression.
    functions : Functions instance, optional
        The user functions for materials etc.
    mode : one of 'eval', 'el_avg', 'qp'
        The evaluation mode - 'qp' requests the values in quadrature points,
        'el_avg' element averages and 'eval' means integration over
        each term region.
    term_mode : str
        The term call mode - some terms support different call modes
        and depending on the call mode different values are
        returned.
    extra_args : dict, optional
        Extra arguments to be passed to terms in the expression.
    verbose : bool
        If False, reduce verbosity.
    kwargs : dict, optional
        The variables (dictionary of (variable name) : (Variable
        instance)) to be used in the expression.

    Returns
    -------
    out : array
        The result of the evaluation.
    """
    weights = nm.ones_like(coors[:, 0])
    integral = Integral('ie', coors=coors, weights=weights)

    domain = fields.values()[0].domain

    region = Region('Elements', 'given elements', domain, '')
    region.cells = iels
    region.update_shape()
    domain.regions.append(region)

    for field in fields.itervalues():
        field.clear_mappings(clear_all=True)
        field.clear_qp_base()

    aux = create_evaluable(expression, fields, materials,
                           variables.itervalues(), Integrals([integral]),
                           functions=functions,
                           mode=mode, extra_args=extra_args, verbose=verbose,
                           kwargs=kwargs)
    equations, variables = aux

    out = eval_equations(equations, variables,
                         preserve_caches=False,
                         mode=mode, term_mode=term_mode)
    domain.regions.pop()

    return out
Example #8
0
def main():
    parser = OptionParser(usage=usage, version='%prog')
    parser.add_option('-d',
                      '--dims',
                      metavar='dims',
                      action='store',
                      dest='dims',
                      default='[1.0, 1.0]',
                      help=helps['dims'])
    parser.add_option('-c',
                      '--centre',
                      metavar='centre',
                      action='store',
                      dest='centre',
                      default='[0.0, 0.0]',
                      help=helps['centre'])
    parser.add_option('-s',
                      '--shape',
                      metavar='shape',
                      action='store',
                      dest='shape',
                      default='[11, 11]',
                      help=helps['shape'])
    parser.add_option('-b',
                      '--bc-kind',
                      metavar='kind',
                      action='store',
                      dest='bc_kind',
                      choices=['free', 'clamped'],
                      default='free',
                      help=helps['bc_kind'])
    parser.add_option('--young',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='young',
                      default=6.80e+10,
                      help=helps['young'])
    parser.add_option('--poisson',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='poisson',
                      default=0.36,
                      help=helps['poisson'])
    parser.add_option('--density',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='density',
                      default=2700.0,
                      help=helps['density'])
    parser.add_option('--order',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='order',
                      default=1,
                      help=helps['order'])
    parser.add_option('-n',
                      '--n-eigs',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='n_eigs',
                      default=6,
                      help=helps['order'])
    parser.add_option('',
                      '--show',
                      action="store_true",
                      dest='show',
                      default=False,
                      help=helps['show'])
    options, args = parser.parse_args()

    assert_((0.0 < options.poisson < 0.5),
            "Poisson's ratio must be in ]0, 0.5[!")
    assert_((0 < options.order),
            'displacement approximation order must be at least 1!')

    dims = nm.array(eval(options.dims), dtype=nm.float64)
    dim = len(dims)
    centre = nm.array(eval(options.centre), dtype=nm.float64)[:dim]
    shape = nm.array(eval(options.shape), dtype=nm.int32)[:dim]

    output('dimensions:', dims)
    output('centre:    ', centre)
    output('shape:     ', shape)
    output('using values:')
    output("  Young's modulus:", options.young)
    output("  Poisson's ratio:", options.poisson)
    output('  density:', options.density)

    # Build the problem definition.
    mesh = gen_block_mesh(dims, shape, centre, name='mesh')
    domain = FEDomain('domain', mesh)

    bbox = domain.get_mesh_bounding_box()
    min_y, max_y = bbox[:, 1]
    eps = 1e-8 * (max_y - min_y)
    omega = domain.create_region('Omega', 'all')
    bottom = domain.create_region('Bottom',
                                  'vertices in (y < %.10f)' % (min_y + eps),
                                  'facet')

    field = Field.from_args('fu',
                            nm.float64,
                            'vector',
                            omega,
                            approx_order=options.order)

    u = FieldVariable('u', 'unknown', field)
    v = FieldVariable('v', 'test', field, primary_var_name='u')

    mtx_d = stiffness_from_youngpoisson(dim, options.young, options.poisson)

    m = Material('m', D=mtx_d, rho=options.density)

    integral = Integral('i', order=2 * options.order)

    t1 = Term.new('dw_lin_elastic(m.D, v, u)', integral, omega, m=m, v=v, u=u)
    t2 = Term.new('dw_volume_dot(m.rho, v, u)', integral, omega, m=m, v=v, u=u)
    eq1 = Equation('stiffness', t1)
    eq2 = Equation('mass', t2)
    lhs_eqs = Equations([eq1, eq2])

    pb = Problem('modal', equations=lhs_eqs)

    if options.bc_kind == 'free':
        pb.time_update()
        n_rbm = dim * (dim + 1) / 2

    else:
        fixed_b = EssentialBC('FixedB', bottom, {'u.all': 0.0})
        pb.time_update(ebcs=Conditions([fixed_b]))
        n_rbm = 0

    pb.update_materials()

    # Assemble stiffness and mass matrices.
    mtx_k = eq1.evaluate(mode='weak', dw_mode='matrix', asm_obj=pb.mtx_a)
    mtx_m = mtx_k.copy()
    mtx_m.data[:] = 0.0
    mtx_m = eq2.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_m)

    try:
        eigs, svecs = sla.eigsh(mtx_k,
                                k=options.n_eigs + n_rbm,
                                M=mtx_m,
                                which='SM',
                                tol=1e-5,
                                maxiter=10000)
    except sla.ArpackNoConvergence as ee:
        eigs = ee.eigenvalues
        svecs = ee.eigenvectors
        output('only %d eigenvalues converged!' % len(eigs))

    eigs = eigs[n_rbm:]
    svecs = svecs[:, n_rbm:]

    output('eigenvalues:', eigs)
    output('eigen-frequencies:', nm.sqrt(eigs))

    # Make full eigenvectors (add DOFs fixed by boundary conditions).
    variables = pb.get_variables()

    vecs = nm.empty((variables.di.ptr[-1], svecs.shape[1]), dtype=nm.float64)
    for ii in xrange(svecs.shape[1]):
        vecs[:, ii] = variables.make_full_vec(svecs[:, ii])

    # Save the eigenvectors.
    out = {}
    state = pb.create_state()
    for ii in xrange(eigs.shape[0]):
        state.set_full(vecs[:, ii])
        aux = state.create_output_dict()
        strain = pb.evaluate('ev_cauchy_strain.i.Omega(u)',
                             integrals=Integrals([integral]),
                             mode='el_avg',
                             verbose=False)
        out['u%03d' % ii] = aux.popitem()[1]
        out['strain%03d' % ii] = Struct(mode='cell', data=strain)

    pb.save_state('eigenshapes.vtk', out=out)
    pb.save_regions_as_groups('regions')

    if options.show:
        # Show the solution. If the approximation order is greater than 1, the
        # extra DOFs are simply thrown away.
        from sfepy.postprocess.viewer import Viewer
        from sfepy.postprocess.domain_specific import DomainSpecificPlot

        scaling = 0.05 * dims.max() / nm.abs(vecs).max()

        ds = {}
        for ii in xrange(eigs.shape[0]):
            pd = DomainSpecificPlot('plot_displacements', [
                'rel_scaling=%s' % scaling, 'color_kind="tensors"',
                'color_name="strain%03d"' % ii
            ])
            ds['u%03d' % ii] = pd

        view = Viewer('eigenshapes.vtk')
        view(domain_specific=ds,
             only_names=sorted(ds.keys()),
             is_scalar_bar=False,
             is_wireframe=True)