예제 #1
0
파일: ls.py 프로젝트: lokik/sfepy
    def _standard_call(self, rhs, x0=None, conf=None, eps_a=None, eps_r=None,
                       i_max=None, mtx=None, status=None, context=None,
                       **kwargs):
        tt = time.clock()

        conf = get_default(conf, self.conf)
        mtx = get_default(mtx, self.mtx)
        status = get_default(status, self.status)
        context = get_default(context, self.context)

        assert_(mtx.shape[0] == mtx.shape[1] == rhs.shape[0])
        if x0 is not None:
            assert_(x0.shape[0] == rhs.shape[0])

        result = call(self, rhs, x0, conf, eps_a, eps_r, i_max, mtx, status,
                      context=context, **kwargs)
        if isinstance(result, tuple):
            result, n_iter = result

        else:
            n_iter = -1 # Number of iterations is undefined/unavailable.

        ttt = time.clock() - tt
        if status is not None:
            status['time'] = ttt
            status['n_iter'] = n_iter

        return result
예제 #2
0
        def get_constants(ts=None, coors=None, mode=None,
                          term=None, problem=None, **kwargs):
            out = {}
            if mode == 'qp':
                qps = term.get_physical_qps()
                assert_(qps.num == coors.shape[0])

                for key, val in six.iteritems(values):
                    if '.' in key: continue
                    rval = nm.array(val[list(val.keys())[0]], dtype=nm.float64,
                                    ndmin=3)
                    s0 = rval.shape[1:]
                    matdata = nm.zeros(qps.shape[:2] + s0, dtype=nm.float64)

                    for rkey, rval in six.iteritems(val):
                        region = problem.domain.regions[rkey]
                        rval = nm.array(rval, dtype=nm.float64, ndmin=3)

                        cells = region.get_cells(true_cells_only=False)
                        ii = term.region.get_cell_indices(cells,
                                                          true_cells_only=False)
                        matdata[ii] = rval

                    out[key] = matdata.reshape((-1,) + s0)

            return out
예제 #3
0
def create_petsc_system(mtx, sizes, pdofs, drange, is_overlap=True,
                        comm=None, verbose=False):
    """
    Create and pre-allocate (if `is_overlap` is True) a PETSc matrix and
    related solution and right-hand side vectors.
    """
    if comm is None:
        comm = PETSc.COMM_WORLD

    if is_overlap:
        mtx.data[:] = 1
        mtx_prealloc = create_prealloc_data(mtx, pdofs, drange,
                                            verbose=True)
        pmtx = create_petsc_matrix(sizes, mtx_prealloc, comm=comm)

    else:
        pmtx = create_petsc_matrix(sizes, comm=comm)

    own_range = pmtx.getOwnershipRange()
    output('pmtx ownership:', own_range, verbose=verbose)
    assert_(own_range == drange)

    psol, prhs = pmtx.getVecs()

    own_range = prhs.getOwnershipRange()
    output('prhs ownership:', own_range, verbose=verbose)
    assert_(own_range == drange)

    return pmtx, psol, prhs
예제 #4
0
파일: ls.py 프로젝트: lokik/sfepy
    def _petsc_call(self, rhs, x0=None, conf=None, eps_a=None, eps_r=None,
                    i_max=None, mtx=None, status=None, comm=None,
                    context=None, **kwargs):
        tt = time.clock()

        conf = get_default(conf, self.conf)
        mtx = get_default(mtx, self.mtx)
        status = get_default(status, self.status)
        context = get_default(context, self.context)
        comm = get_default(comm, self.comm)

        mshape = mtx.size if isinstance(mtx, self.petsc.Mat) else mtx.shape
        rshape = [rhs.size] if isinstance(rhs, self.petsc.Vec) else rhs.shape

        assert_(mshape[0] == mshape[1] == rshape[0])
        if x0 is not None:
            xshape = [x0.size] if isinstance(x0, self.petsc.Vec) else x0.shape
            assert_(xshape[0] == rshape[0])

        result = call(self, rhs, x0, conf, eps_a, eps_r, i_max, mtx, status,
                      comm, context=context, **kwargs)

        ttt = time.clock() - tt
        if status is not None:
            status['time'] = ttt
            status['n_iter'] = self.ksp.getIterationNumber()

        return result
예제 #5
0
파일: fields.py 프로젝트: LeiDai/sfepy
    def set_dofs(self, fun=0.0, region=None, dpn=None, warn=None):
        """
        Set the values of given DOFs using a function of space coordinates or
        value `fun`.

        Notes
        -----
        Works for a constant value over an entire patch side only.
        """
        if region is None:
            region = self.region

        if dpn is None:
            dpn = self.n_components

        nods = []
        vals = []

        aux = self.get_dofs_in_region(region, clean=True, warn=warn)
        nods = nm.unique(nm.hstack(aux))

        if nm.isscalar(fun):
            vals = nm.repeat([fun], nods.shape[0] * dpn)

        elif isinstance(fun, nm.ndarray):
            assert_(len(fun) == dpn)
            vals = nm.repeat(fun, nods.shape[0])

        else:
            raise ValueError('unknown function/value type! (%s)' % type(fun))

        return nods, vals
예제 #6
0
파일: sparse.py 프로젝트: Gkdnz/sfepy
def insert_sparse_to_csr(mtx1, mtx2, irs, ics):
    """
    Insert a sparse matrix `mtx2` into a CSR sparse matrix `mtx1` at
    rows `irs` and columns `ics`. The submatrix `mtx1[irs,ics]` must
    already be preallocated and have the same structure as `mtx2`.
    """
    import sfepy.discrete.common.extmods.assemble as asm

    if isinstance(irs, slice):
        irs = nm.arange(irs.start, irs.stop, irs.step, dtype=nm.int32)

    if isinstance(ics, slice):
        ics = nm.arange(ics.start, ics.stop, ics.step, dtype=nm.int32)

    n_row, n_col = mtx1.shape

    assert_((irs.min() >= 0) and (irs.max() < n_row))
    assert_((ics.min() >= 0) and (ics.max() < n_col))

    aux = mtx2.tocoo()
    data = nm.ascontiguousarray(aux.data[:,None,None,None])
    rows = irs[aux.row[:,None]]
    cols = ics[aux.col[:,None]]

    iels = nm.arange(rows.shape[0], dtype=nm.int32)
    asm.assemble_matrix(mtx1.data, mtx1.indptr, mtx1.indices, data,
                        iels, 1.0, rows, cols)
예제 #7
0
파일: iga.py 프로젝트: andy-c-huang/sfepy
def compute_bezier_extraction(knots, degrees):
    """
    Compute local (element) Bezier extraction operators for a nD B-spline
    parametric domain.

    Parameters
    ----------
    knots : sequence of array or array
        The knot vectors.
    degrees : sequence of ints or int
        Polynomial degrees in each parametric dimension.

    Returns
    -------
    cs : list of lists of 2D arrays
        The element extraction operators in each parametric dimension.
    """
    if isinstance(degrees, int): degrees = [degrees]

    knots = _get_knots_tuple(knots)
    dim = len(knots)
    assert_(dim == len(degrees))

    cs = []
    for ii, knots1d in enumerate(knots):
        cs1d = compute_bezier_extraction_1d(knots1d, degrees[ii])
        cs.append(cs1d)

    return cs
예제 #8
0
def get_poly(order, dim, is_simplex=False):
    """
    Construct a polynomial of given `order` in space dimension `dim`,
    and integrate it symbolically over a rectangular or simplex domain
    for coordinates in [0, 1].
    """
    xs = symarray("x", dim)

    opd = max(1, int((order + 1) / dim))

    poly = 1.0
    oo = 0
    for ii, x in enumerate(xs):
        if ((oo + opd) > order) or (ii == (len(xs) - 1)):
            opd = max(order - oo, 0)

        poly *= x ** opd + 1
        oo += opd

    assert_(oo == order)

    limits = [[xs[ii], 0, 1] for ii in range(dim)]
    if is_simplex:
        for ii in range(1, dim):
            for ip in range(0, ii):
                limits[ii][2] -= xs[ip]

    integral = sm.integrate(poly, *reversed(limits))

    return xs, poly, limits, integral
예제 #9
0
파일: postproc.py 프로젝트: clazaro/sfepy
 def __call__(self, parser, namespace, value, option_string=None):
     vals = value.split(',')
     assert_(len(vals) in [2, 3, 6])
     val = tuple(float(ii) for ii in vals)
     if len(vals) == 6:
         val = val[:3] + (list(val[3:]),)
     setattr(namespace, self.dest, val)
예제 #10
0
파일: probe.py 프로젝트: AshitaPrasad/sfepy
def postprocess(filename_input, filename_results, options):
    """
    Postprocess probe data files - replot, integrate data.
    """
    from matplotlib import pyplot as plt

    header, results = read_results(filename_input,
                                   only_names=options.only_names)
    output(header)

    fig = plt.figure()
    for name, result in results.iteritems():
        pars, vals = result[:, 0], result[:, 1]

        ii = nm.where(nm.isfinite(vals))[0]
        # Nans only at the edges.
        assert_(nm.diff(ii).sum() == (len(ii)-1))

        val = integrate_along_line(pars[ii], vals[ii], options.radial)

        label = r'%s: $\int\ %s' % (name, name)
        if options.radial:
            label += ' (r)'
        label += '$ = %.5e'% val

        plt.plot(pars, vals, label=label, lw=0.2, marker='+', ms=1)
        plt.ylabel('probed data')
        plt.xlabel('probe coordinate')

        output(label)

    plt.legend()

    fig.savefig(filename_results)
예제 #11
0
    def test_material_functions(self):
        from sfepy.discrete import Material

        problem = self.problem
        conf = problem.conf

        ts = problem.get_default_ts(step=0)

        conf_mat1 = conf.get_item_by_name('materials', 'mf1')
        mat1 = Material.from_conf(conf_mat1, problem.functions)
        mat1.time_update(ts, None, mode='normal', problem=problem)

        coors = problem.domain.get_mesh_coors()
        assert_(nm.all(coors[:,0] == mat1.get_data(None, 'x_0')))

        conf_mat2 = conf.get_item_by_name('materials', 'mf2')
        mat2 = Material.from_conf(conf_mat2, problem.functions)
        mat2.time_update(ts, None, mode='normal', problem=problem)

        assert_(nm.all(coors[:,1] == mat2.get_data(None, 'x_1')))

        materials = problem.get_materials()
        materials.time_update(ts, problem.equations, mode='normal',
                              problem=problem)
        mat3 = materials['mf3']
        key = mat3.get_keys(region_name='Omega')[0]

        assert_(nm.all(mat3.get_data(key, 'a') == 10.0))
        assert_(nm.all(mat3.get_data(key, 'b') == 2.0))
        assert_(mat3.get_data(None, 'c') == 'ahoj')

        return True
예제 #12
0
파일: eigen.py 프로젝트: taldcroft/sfepy
    def compute_cat( self, ret_iw_dir=False ):
        """Compute the Christoffel acoustic tensor, given the incident wave
        direction."""
        opts = self.app_options
        iw_dir = nm.array( opts.incident_wave_dir, dtype = nm.float64 )

        dim = self.problem.get_dim()
        assert_( dim == iw_dir.shape[0] )

        iw_dir = iw_dir / nla.norm( iw_dir )

        if self.cached_christoffel is not None:
            christoffel = self.cached_christoffel

        else:
            coefs = self.eval_homogenized_coefs()
            christoffel = compute_cat( coefs, iw_dir,
                                       self.app_options.dispersion )
            report_iw_cat( iw_dir, christoffel )

            self.cached_christoffel = christoffel

        if ret_iw_dir:
            return christoffel, iw_dir

        else:
            return christoffel
예제 #13
0
def prepare_cylindrical_transform(coors, origin, mode='axes'):
    """
    Prepare matrices for transforming tensors into cylindrical coordinates with
    the axis 'z' in a given origin.

    Parameters
    ----------
    coors : array
        The Cartesian coordinates.
    origin : array of length 3
        The origin.
    mode : 'axes' or 'data'
        In 'axes' (default) mode the matrix transforms data to different
        coordinate system, while in 'data' mode the matrix transforms
        the data in the same coordinate system and is transpose of the
        matrix in the 'axes' mode.

    Returns
    -------
    mtx : array
        The array of transformation matrices for each coordinate in `coors`.
    """
    assert_(mode in ['axes', 'data'])

    x, y = coors[:,0] - origin[0], coors[:,1] - origin[1]
    theta = nm.arctan2(y, x)
    if mode == 'data':
        theta = -theta

    mtx = nm.zeros((coors.shape[0], 3, 3), dtype=nm.float64)
    for ii, th in enumerate(theta):
        mtx[ii] = make_axis_rotation_matrix([0.0, 0.0, 1.0], th)

    return mtx
예제 #14
0
파일: postproc.py 프로젝트: qilicun/sfepy
def parse_view(option, opt, value, parser):
    vals = value.split(',')
    assert_(len(vals) in [2, 3, 6])
    val = tuple(float(ii) for ii in vals)
    if len(vals) == 6:
        val = val[:3] + (list(val[3:]),)
    setattr(parser.values, option.dest, val)
예제 #15
0
파일: utils.py 프로젝트: Nasrollah/sfepy
def norm_l2_along_axis(ar, axis=1, n_item=None, squared=False):
    """Compute l2 norm of rows (axis=1) or columns (axis=0) of a 2D array.

    n_item ... use only the first n_item columns/rows
    squared ... if True, return the norm squared
    """
    assert_(axis in [0, 1])
    assert_(ar.ndim == 2)

    other = 1 - axis
    vec = nm.zeros((ar.shape[other],), dtype=nm.float64)

    if n_item is None:
        n_item = ar.shape[axis]
    else:
        n_item = min( n_item, ar.shape[axis] )

    if axis == 1:
        for ii in range( n_item ):
            vec += ar[:,ii]**2
    else:
        for ii in range( n_item ):
            vec += ar[ii,:]**2

    if not squared:
        vec = nm.sqrt( vec )

    return vec
예제 #16
0
def plot_displacements(
    source, ctp, bbox, position, family, kind, name, rel_scaling=1.0, color_kind=None, color_name=None, opacity=1.0
):
    """
    Show displacements by displaying a colormap given by quantity
    `color_name` on the deformed mesh.

    Parameters
    ----------
    rel_scaling : float
        The relative scaling of displacements.
    color_kind : str, optional
        The kind of data determining the colormap.
    color_name : str, optional
        The name of data determining the colormap.
    opacity : float
        The surface plot opacity.
    """
    assert_(kind == "vectors")

    if color_name is None:
        active = mlab.pipeline.set_active_attribute(source)

    else:
        active = mlab.pipeline.set_active_attribute(ctp)

    active.point_vectors_name = name
    active = mlab.pipeline.warp_vector(active)
    active.filter.scale_factor = rel_scaling

    if color_name is None:
        new_kind = kind
        new_name = name

        active = mlab.pipeline.extract_vector_norm(active)

    else:
        new_kind = "scalars"

        if color_kind == "tensors":
            new_name = "|%s|" % color_name
            active = mlab.pipeline.set_active_attribute(active)
            active.point_tensors_name = color_name
            active = mlab.pipeline.extract_tensor_components(active)

        elif color_kind == "vectors":
            new_name = "|%s|" % color_name
            active = mlab.pipeline.set_active_attribute(active)
            active.point_vectors_name = color_name
            active = mlab.pipeline.extract_tensor_components(active)

        elif color_kind == "scalars":
            new_name = "%s" % color_name
            active = mlab.pipeline.set_active_attribute(active)
            active.point_scalars_name = color_name

    surf = mlab.pipeline.surface(active, opacity=opacity)
    surf.actor.actor.position = position

    return new_kind, new_name, active
예제 #17
0
파일: region.py 프로젝트: mfkiwl/sfepy
    def get_edge_graph(self):
        """
        Return the graph of region edges as a sparse matrix having uid(k) + 1
        at (i, j) if vertex[i] is connected with vertex[j] by the edge k.

        Degenerate edges are ignored.
        """
        from scipy.sparse import csr_matrix

        cmesh = self.domain.cmesh

        e_verts = cmesh.get_incident(0, self.edges, 1)
        e_verts.shape = (e_verts.shape[0] / 2, 2)

        ii = nm.where(e_verts[:, 0] != e_verts[:, 1])[0]
        edges = self.edges[ii]
        e_verts = e_verts[ii]

        vals = edges + 1
        rows = e_verts[:, 0]
        cols = e_verts[:, 1]

        num = self.vertices.max() + 1
        graph = csr_matrix((vals, (rows, cols)), shape=(num, num))

        nnz = graph.nnz
        # Symmetrize.
        graph = graph + graph.T
        assert_(graph.nnz == 2 * nnz)

        return graph
예제 #18
0
    def solve_pressure_eigenproblem(self, mtx, eig_problem=None,
                                    n_eigs=0, check=False):
        """G = B*AI*BT or B*AI*BT+D"""

        def get_slice(n_eigs, nn):
            if n_eigs > 0:
                ii = slice(0, n_eigs)
            elif n_eigs < 0:
                ii = slice(nn + n_eigs, nn)
            else:
                ii = slice(0, 0)
            return ii

        eig_problem = get_default(eig_problem, self.eig_problem)
        n_eigs = get_default(n_eigs, self.n_eigs)
        check = get_default(check, self.check)

        mtx_c, mtx_b, action_aibt = mtx['C'], mtx['B'], mtx['action_aibt']
        mtx_g = mtx_b * action_aibt.to_array() # mtx_b must be sparse!
        if eig_problem == 'B*AI*BT+D':
            mtx_g += mtx['D'].toarray()

        mtx['G'] = mtx_g
        output(mtx_c.shape, mtx_g.shape)

        eigs, mtx_q = eig(mtx_c.toarray(), mtx_g, method='eig.sgscipy')

        if check:
            ee = nm.diag(sc.dot(mtx_q.T * mtx_c, mtx_q)).squeeze()
            oo = nm.diag(sc.dot(sc.dot(mtx_q.T,  mtx_g), mtx_q)).squeeze()
            try:
                assert_(nm.allclose(ee, eigs))
                assert_(nm.allclose(oo, nm.ones_like(eigs)))
            except ValueError:
                debug()

        nn = mtx_c.shape[0]
        if isinstance(n_eigs, tuple):
            output('required number of eigenvalues: (%d, %d)' % n_eigs)
            if sum(n_eigs) < nn:
                ii0 = get_slice(n_eigs[0], nn)
                ii1 = get_slice(-n_eigs[1], nn)
                eigs = nm.concatenate((eigs[ii0], eigs[ii1]))
                mtx_q = nm.concatenate((mtx_q[:,ii0], mtx_q[:,ii1]), 1) 
        else:
            output('required number of eigenvalues: %d' % n_eigs)
            if (n_eigs != 0) and (abs(n_eigs) < nn):
                ii = get_slice(n_eigs, nn)
                eigs = eigs[ii]
                mtx_q = mtx_q[:,ii]

##         from sfepy.base.plotutils import pylab, iplot
##         pylab.semilogy(eigs)
##         pylab.figure(2)
##         iplot(eigs)
##         pylab.show()
##         debug()

        out = Struct(eigs=eigs, mtx_q=mtx_q)
        return out
예제 #19
0
def barycentric_coors(coors, s_coors):
    """
    Get barycentric (area in 2D, volume in 3D) coordinates of points
    with coordinates `coors` w.r.t. the simplex given by `s_coors`.

    Returns
    -------
    bc : array
        The barycentric coordinates. Then reference element coordinates
        `xi = dot(bc.T, ref_coors)`.
    """
    n_v, dim = s_coors.shape
    n_c, dim2 = coors.shape
    assert_(dim == dim2)
    assert_(n_v == (dim + 1))

    mtx = nm.ones((n_v, n_v), nm.float64)
    mtx[0:n_v-1,:] = s_coors.T

    rhs = nm.empty((n_v,n_c), nm.float64)
    rhs[0:n_v-1,:] = coors.T
    rhs[n_v-1,:] = 1.0

    bc = nla.solve(mtx, rhs)

    return bc
예제 #20
0
    def __call__(self, problem=None, data=None):
        problem = get_default(problem, self.problem)

        problem.set_equations(self.equations)

        problem.select_bcs(ebc_names=self.ebcs, epbc_names=self.epbcs,
                           lcbc_names=self.get_default_attr('lcbcs', []))

        problem.update_materials(problem.ts)

        self.init_solvers(problem)

        variables = problem.get_variables()

        states = nm.zeros((self.dim,), dtype=nm.object)
        clist = []
        for ir in range(self.dim):
            if isinstance(self.set_variables, list):
                self.set_variables_default(variables, ir,
                                           self.set_variables, data)
            else:
                self.set_variables(variables, ir, **data)
            state = problem.solve()
            assert_(state.has_ebc())
            states[ir] = state.get_parts()

            clist.append((ir,))

        corr_sol = CorrSolution(name=self.name,
                                states=states,
                                components=clist)

        self.save(corr_sol, problem)

        return corr_sol
예제 #21
0
    def get_cell_indices(self, cells, true_cells_only=True):
        """
        Return indices of `cells` in the region cells.

        Raises ValueError if `true_cells_only` is True and the region kind does
        not allow cells. For `true_cells_only` equal to False, cells incident
        to facets are returned if the region itself contains no cells.

        Notes
        -----
        If the number of unique values in `cells` is smaller or equal to the
        number of cells in the region, all `cells` has to be also the region
        cells (`self` is a superset of `cells`). The region cells are
        considered depending on `true_cells_only`.

        Otherwise, indices of all cells in `self` that are in `cells` are
        returned.
        """
        fcells = self.get_cells(true_cells_only=true_cells_only)

        if len(nm.unique(cells)) <= len(nm.unique(fcells)):
            # self is a superset of cells.
            ii = nm.searchsorted(fcells, cells)
            assert_((fcells[ii] == cells).all())

        else:
            aux = nm.searchsorted(cells, fcells)
            ii = nm.where(nm.take(cells, aux, mode='clip') == fcells)[0]

        return ii
예제 #22
0
    def _setup_vertex_dofs(self):
        """
        Setup vertex DOF connectivity.
        """
        if self.node_desc.vertex is None:
            return 0, None

        region = self.region

        cmesh = self.domain.cmesh
        conn, offsets = cmesh.get_incident(0, region.cells, region.tdim,
                                           ret_offsets=True)

        vertices = nm.unique(conn)
        remap = prepare_remap(vertices, region.n_v_max)
        n_dof = vertices.shape[0]

        aux = nm.unique(nm.diff(offsets))
        assert_(len(aux) == 1, 'region with multiple reference geometries!')
        offset = aux[0]


        # Remap vertex node connectivity to field-local numbering.
        aux = conn.reshape((-1, offset)).astype(nm.int32)
        self.econn[:, :offset] = nm.take(remap, aux)

        return n_dof, remap
예제 #23
0
    def set_dofs(self, fun=0.0, region=None, dpn=None, warn=None):
        """
        Set the values of DOFs in a given region using a function of space
        coordinates or value `fun`.
        """
        if region is None:
            region = self.region

        if dpn is None:
            dpn = self.shape[0]

        aux = self.get_dofs_in_region(region, clean=True, warn=warn)
        nods = nm.unique(nm.hstack(aux))

        if callable(fun):
            vals = fun(self.get_coor(nods))

        elif nm.isscalar(fun):
            vals = nm.repeat([fun], nods.shape[0] * dpn)

        elif isinstance(fun, nm.ndarray):
            assert_(len(fun) == dpn)
            vals = nm.repeat(fun, nods.shape[0])

        else:
            raise ValueError('unknown function/value type! (%s)' % type(fun))

        return nods, vals
예제 #24
0
    def __init__(self, name, regions, dof_names, dof_map_fun,
                 filename, variables, ts=None, functions=None):
        MRLCBCOperator.__init__(self, name, regions, dof_names, dof_map_fun,
                                variables, functions=functions)
        self.filename = filename

        dim = self.region.dim
        assert_(len(self.dof_names) == dim)

        can_save = ((self.filename is not None)
                    and ((ts is None) or ((ts is not None) and ts.step == 0)))
        filename = self.filename if can_save else None

        vectors = self.get_vectors(self.mdofs, self.region, self.field,
                                   filename=filename)
        n_nod, dim = vectors.shape

        data = vectors.ravel()
        rows = nm.arange(data.shape[0])
        cols = nm.repeat(nm.arange(n_nod), dim)

        mtx = sp.coo_matrix((data, (rows, cols)), shape=(n_nod * dim, n_nod))

        self.n_mdof = n_nod * dim
        self.n_new_dof = n_nod
        self.mtx = mtx.tocsr()
예제 #25
0
    def __call__( self, problem = None, data = None, save_hook = None ):
        """data: corrs_pressure, evp, optionally vec_g"""
        problem = get_default( problem, self.problem )
        ts = problem.get_time_solver().ts

        corrs, evp = [data[ii] for ii in self.requires[:2]]
        if len(self.requires) == 3:
            vec_g = data[self.requires[2]]
        else:
            vec_g = None

        assert_( evp.ebcs == self.ebcs )
        assert_( evp.epbcs == self.epbcs )

        filename = self.get_dump_name()
        savename = self.get_save_name()

        self.setup_equations(self.equations)

        solve = self.compute_correctors
        solve(evp, 1.0, corrs.state, ts, filename, savename, vec_g=vec_g)

        if self.check:
            self.setup_equations(self.verify_equations)
            self.init_solvers(problem)

            output( 'verifying correctors %s...' % self.name )
            verify = self.verify_correctors
            ok = verify(1.0, corrs.state, filename)
            output( '...done, ok: %s' % ok )

        return Struct( name = self.name,
                       filename = filename )
예제 #26
0
    def __call__(self, problem=None, data=None):
        problem = get_default(problem, self.problem)

        problem.set_equations(self.equations)

        problem.select_bcs(ebc_names=self.ebcs, epbc_names=self.epbcs,
                           lcbc_names=self.get_default_attr('lcbcs', []))

        problem.update_materials(problem.ts)

        self.init_solvers(problem)

        variables = problem.get_variables()

        if hasattr(self, 'set_variables'):
            if isinstance(self.set_variables, list):
                self.set_variables_default(variables, self.set_variables,
                                           data)
            else:
                self.set_variables(variables, **data)

        state = problem.solve()
        assert_(state.has_ebc())

        corr_sol = CorrSolution(name=self.name,
                                state=state.get_parts())

        self.save(corr_sol, problem)

        return corr_sol
예제 #27
0
    def __call__(self, volume=None, problem=None, data=None):
        problem = get_default(problem, self.problem)
        opts = self.app_options

        iw_dir = nm.array(opts.incident_wave_dir, dtype=nm.float64)
        dim = problem.get_dim()
        assert_(dim == iw_dir.shape[0])

        iw_dir = iw_dir / nla.norm(iw_dir)

        dispersion = data[self.requires[0]]

        wave_vectors = dispersion.logs.eig_vectors

        pas = []

        iw_dir = iw_dir / nla.norm(iw_dir)
        idims = range(iw_dir.shape[0])
        pi2 = 0.5 * nm.pi
        for vecs in wave_vectors:
            pa = nm.empty(vecs.shape[:-1], dtype=nm.float64)
            for ir, vec in enumerate(vecs):
                for ic in idims:
                    vv = vec[:,ic]
                    # Ensure the angle is in [0, pi/2].
                    val = nm.arccos(nm.dot(iw_dir, vv) / nla.norm(vv))
                    if val > pi2:
                        val = nm.pi - val
                    pa[ir,ic] = val

            pas.append(pa)

        return pas
예제 #28
0
파일: membranes.py 프로젝트: iostanin/sfepy
def create_mapping(coors, gel, order):
    """
    Create mapping from transformed (in `x-y` plane) element faces to
    reference element faces.

    Parameters
    ----------
    coors : array
        The transformed coordinates of element nodes, shape `(n_el,
        n_ep, dim)`. The function verifies that the all `z` components
        are zero.
    gel : GeometryElement instance
        The geometry element corresponding to the faces.
    order : int
        The polynomial order of the mapping.

    Returns
    -------
    mapping : VolumeMapping instance
        The reference element face mapping.
    """
    # Strip 'z' component (should be 0 now...).
    assert_(nm.allclose(coors[:, :, -1], 0.0, rtol=1e-12, atol=1e-12))
    coors = coors[:, :, :-1].copy()

    # Mapping from transformed element to reference element.
    sh = coors.shape
    seq_coors = coors.reshape((sh[0] * sh[1], sh[2]))
    seq_conn = nm.arange(seq_coors.shape[0], dtype=nm.int32)
    seq_conn.shape = sh[:2]

    mapping = VolumeMapping(seq_coors, seq_conn, gel=gel, order=1)

    return mapping
예제 #29
0
    def get_edge_graph(self):
        """
        Return the graph of region edges as a sparse matrix having uid(k) + 1
        at (i, j) if vertex[i] is connected with vertex[j] by the edge k.

        Degenerate edges are ignored.
        """
        from scipy.sparse import csr_matrix

        ed = self.domain.ed

        rows, cols, vals = [], [], []
        for ig, edges in self.edges.iteritems():
            e_verts = ed.facets[edges]
            ii = nm.where(e_verts[:, 0] != e_verts[:, 1])[0]
            edges = edges[ii]
            e_verts = e_verts[ii]

            vals.append(ed.uid_i[edges] + 1)
            rows.append(e_verts[:, 0])
            cols.append(e_verts[:, 1])

        vals, indx = nm.unique(nm.concatenate(vals), return_index=True)
        rows = nm.concatenate(rows)[indx]
        cols = nm.concatenate(cols)[indx]

        num = self.all_vertices.max() + 1
        graph = csr_matrix((vals, (rows, cols)), shape=(num, num))

        nnz = graph.nnz
        # Symmetrize.
        graph = graph + graph.T
        assert_(graph.nnz == 2 * nnz)

        return graph
예제 #30
0
    def __init__(self, anchor, normal, bounds):
        Struct.__init__(self, anchor=nm.array(anchor, dtype=nm.float64),
                        bounds=nm.asarray(bounds, dtype=nm.float64))
        self.normal = nm.asarray(normal, dtype=nm.float64)

        norm = nm.linalg.norm
        self.normal /= norm(self.normal)

        e3 = [0.0, 0.0, 1.0]
        dd = nm.dot(e3, self.normal)
        rot_angle = nm.arccos(dd)

        if nm.abs(rot_angle) < 1e-14:
            mtx = nm.eye(3, dtype=nm.float64)
            bounds2d = self.bounds[:, :2]

        else:
            rot_axis = nm.cross([0.0, 0.0, 1.0], self.normal)
            mtx = la.make_axis_rotation_matrix(rot_axis, rot_angle)

            mm = la.insert_strided_axis(mtx, 0, self.bounds.shape[0])
            rbounds = la.dot_sequences(mm, self.bounds)
            bounds2d = rbounds[:, :2]

        assert_(nm.allclose(nm.dot(mtx, self.normal), e3,
                            rtol=0.0, atol=1e-12))

        self.adotn = nm.dot(self.anchor, self.normal)

        self.rot_angle = rot_angle
        self.mtx = mtx
        self.bounds2d = bounds2d
예제 #31
0
    def assemble_to(self, asm_obj, val, iels, mode='vector', diff_var=None):
        """
        Assemble the results of term evaluation.

        For standard terms, assemble the values in `val` corresponding to
        elements/cells `iels` into a vector or a CSR sparse matrix `asm_obj`,
        depending on `mode`.

        For terms with a dynamic connectivity (e.g. contact terms), in
        `'matrix'` mode, return the extra COO sparse matrix instead. The extra
        matrix has to be added to the global matrix by the caller. By default,
        this is done in :func:`Equations.evaluate()
        <sfepy.discrete.equations.Equations.evaluate()>`.
        """
        import sfepy.discrete.common.extmods.assemble as asm

        vvar = self.get_virtual_variable()
        dc_type = self.get_dof_conn_type()

        extra = None

        if mode == 'vector':
            if asm_obj.dtype == nm.float64:
                assemble = asm.assemble_vector

            else:
                assert_(asm_obj.dtype == nm.complex128)
                assemble = asm.assemble_vector_complex
                for ii in range(len(val)):
                    if not (val[ii].dtype == nm.complex128):
                        val[ii] = nm.complex128(val[ii])

            if not isinstance(val, tuple):
                dc = vvar.get_dof_conn(dc_type)
                assert_(val.shape[2] == dc.shape[1])

                assemble(asm_obj, val, iels, 1.0, dc)

            else:
                vals, rows, var = val
                if var.eq_map is not None:
                    eq = var.eq_map.eq

                    rows = eq[rows]
                    active = (rows >= 0)
                    vals, rows = vals[active], rows[active]

                # Assumes no repeated indices in rows!
                asm_obj[rows] += vals

        elif mode == 'matrix':
            if asm_obj.dtype == nm.float64:
                assemble = asm.assemble_matrix

            else:
                assert_(asm_obj.dtype == nm.complex128)
                assemble = asm.assemble_matrix_complex

            svar = diff_var
            tmd = (asm_obj.data, asm_obj.indptr, asm_obj.indices)

            if ((asm_obj.dtype == nm.complex128)
                    and (val.dtype == nm.float64)):
                val = val.astype(nm.complex128)

            sign = 1.0
            if self.arg_derivatives[svar.name]:
                if not self.is_quasistatic or (self.step > 0):
                    sign *= 1.0 / self.dt

                else:
                    sign = 0.0

            if not isinstance(val, tuple):
                rdc = vvar.get_dof_conn(dc_type)

                is_trace = self.arg_traces[svar.name]
                trace_region = self.arg_trace_regions[svar.name]
                cdc = svar.get_dof_conn(dc_type, is_trace, trace_region)
                assert_(val.shape[2:] == (rdc.shape[1], cdc.shape[1]))

                assemble(tmd[0], tmd[1], tmd[2], val, iels, sign, rdc, cdc)

            else:
                from scipy.sparse import coo_matrix

                vals, rows, cols, rvar, cvar = val
                if rvar.eq_map is not None:
                    req, ceq = rvar.eq_map.eq, cvar.eq_map.eq

                    rows, cols = req[rows], ceq[cols]
                    active = (rows >= 0) & (cols >= 0)
                    vals, rows, cols = vals[active], rows[active], cols[active]

                extra = coo_matrix((sign * vals, (rows, cols)),
                                   shape=asm_obj.shape)

        else:
            raise ValueError('unknown assembling mode! (%s)' % mode)

        return extra
예제 #32
0
    def evaluate(self,
                 mode='eval',
                 diff_var=None,
                 standalone=True,
                 ret_status=False,
                 **kwargs):
        """
        Evaluate the term.

        Parameters
        ----------
        mode : 'eval' (default), or 'weak'
            The term evaluation mode.

        Returns
        -------
        val : float or array
            In 'eval' mode, the term returns a single value (the
            integral, it does not need to be a scalar), while in 'weak'
            mode it returns an array for each element.
        status : int, optional
            The flag indicating evaluation success (0) or failure
            (nonzero). Only provided if `ret_status` is True.
        iels : array of ints, optional
            The local elements indices in 'weak' mode. Only provided in
            non-'eval' modes.
        """
        if standalone:
            self.standalone_setup()

        kwargs = kwargs.copy()
        term_mode = kwargs.pop('term_mode', None)

        if mode in ('eval', 'el_eval', 'el_avg', 'qp'):
            args = self.get_args(**kwargs)
            self.check_shapes(*args)

            emode = 'eval' if mode == 'el_eval' else mode
            _args = tuple(args) + (emode, term_mode, diff_var)

            shape, dtype = self.get_eval_shape(*_args, **kwargs)

            if shape[0] == 0:
                val = nm.zeros(shape, dtype=dtype)
                status = 0

            else:
                fargs = self.call_get_fargs(_args, kwargs)

                if dtype == nm.float64:
                    val, status = self.eval_real(shape, fargs, mode, term_mode,
                                                 **kwargs)

                elif dtype == nm.complex128:
                    val, status = self.eval_complex(shape, fargs, mode,
                                                    term_mode, **kwargs)

                else:
                    raise ValueError('unsupported term dtype! (%s)' % dtype)

            val *= self.sign
            out = (val, )

        elif mode == 'weak':
            varr = self.get_virtual_variable()
            if varr is None:
                raise ValueError(
                    'no virtual variable in weak mode! (in "%s")' %
                    self.get_str())

            if diff_var is not None:
                varc = self.get_variables(as_list=False)[diff_var]

            args = self.get_args(**kwargs)
            self.check_shapes(*args)

            n_elr, n_qpr, dim, n_enr, n_cr = self.get_data_shape(varr)
            n_row = n_cr * n_enr

            if diff_var is None:
                shape = (n_elr, 1, n_row, 1)

            else:
                n_elc, n_qpc, dim, n_enc, n_cc = self.get_data_shape(varc)
                n_col = n_cc * n_enc

                shape = (n_elr, 1, n_row, n_col)

            if shape[0] == 0:
                vals = nm.zeros(shape, dtype=varr.dtype)
                status = 0

            else:
                _args = tuple(args) + (mode, term_mode, diff_var)
                fargs = self.call_get_fargs(_args, kwargs)

                if varr.dtype == nm.float64:
                    vals, status = self.eval_real(shape, fargs, mode,
                                                  term_mode, diff_var,
                                                  **kwargs)

                elif varr.dtype == nm.complex128:
                    vals, status = self.eval_complex(shape, fargs, mode,
                                                     term_mode, diff_var,
                                                     **kwargs)

                else:
                    raise ValueError('unsupported term dtype! (%s)' %
                                     varr.dtype)

            if not isinstance(vals, tuple):
                vals *= self.sign
                iels = self.get_assembling_cells(vals.shape)

            else:
                vals = (self.sign * vals[0], ) + vals[1:]
                iels = None

            out = (vals, iels)

        if goptions['check_term_finiteness']:
            assert_(nm.isfinite(out[0]).all(),
                    msg='"%s" term values not finite!' % self.get_str())

        if ret_status:
            out = out + (status, )

        if len(out) == 1:
            out = out[0]

        return out
예제 #33
0
파일: poly_spaces.py 프로젝트: zitkat/sfepy
    def _define_nodes(self):
        geometry = self.geometry
        order = self.order

        n_v, dim = geometry.n_vertex, geometry.dim

        n_nod, n_per_edge, n_per_face, n_bubble = self._get_counts()

        nodes = nm.zeros((n_nod, dim), nm.int32)
        nts = nm.zeros((n_nod, 2), nm.int32)

        # Vertex nodes.
        nts[0:n_v, 0] = 0
        nts[0:n_v, 1] = nm.arange(n_v, dtype=nm.int32)
        nodes[0:n_v] = nm.array(vertex_maps[dim], dtype=nm.int32)
        ii = n_v

        # Edge nodes.
        if (dim > 1) and (n_per_edge > 0):
            ik = nm.arange(2, order + 1, dtype=nm.int32)
            zo = nm.zeros((n_per_edge, 2), dtype=nm.int32)
            zo[:, 1] = 1
            for ie, edge in enumerate(geometry.edges):
                n1, n2 = nodes[edge]
                ifix = nm.where(n1 == n2)[0]
                irun = nm.where(n1 != n2)[0][0]
                ic = n1[ifix]

                nodes[ii:ii + n_per_edge, ifix] = zo[:, ic]
                nodes[ii:ii + n_per_edge, irun] = ik
                nts[ii:ii + n_per_edge] = [[1, ie]]
                ii += n_per_edge

        # 3D face nodes.
        face_axes = []
        sfnodes = None
        if (dim == 3) and (n_per_face > 0):
            n_face = len(geometry.faces)
            sfnodes = nm.zeros((n_per_face * n_face, dim), nm.int32)
            ii0 = ii

            ik = nm.arange(2, order + 1, dtype=nm.int32)
            zo = nm.zeros((n_per_face, 2), dtype=nm.int32)
            zo[:, 1] = 1

            for ifa, face in enumerate(geometry.faces):
                ns = nodes[face]

                diff = nm.diff(ns, axis=0)
                asum = nm.abs(diff).sum(axis=0)
                ifix = nm.where(asum == 0)[0][0]
                ic = ns[0, ifix]
                irun1 = nm.where(asum == 2)[0][0]
                irun2 = nm.where(asum == 1)[0][0]

                iy, ix = nm.meshgrid(ik, ik)

                nodes[ii:ii + n_per_face, ifix] = zo[:, ic]
                nodes[ii:ii + n_per_face, irun1] = ix.ravel()
                nodes[ii:ii + n_per_face, irun2] = iy.ravel()
                nts[ii:ii + n_per_face] = [[2, ifa]]

                ij = ii - ii0
                sfnodes[ij:ij + n_per_face, ifix] = zo[:, ic]
                sfnodes[ij:ij + n_per_face, irun1] = iy.ravel()
                sfnodes[ij:ij + n_per_face, irun2] = ix.ravel()

                face_axes.append([irun1, irun2])

                ii += n_per_face

        face_axes = nm.array(face_axes)

        # Bubble nodes.
        if n_bubble > 0:
            ik = nm.arange(2, order + 1, dtype=nm.int32)
            nodes[ii:] = nm.array([aux for aux in combine([ik] * dim)])
            nts[ii:ii + n_bubble] = [[3, 0]]
            ii += n_bubble

        assert_(ii == n_nod)

        # Coordinates of the "nodes". All nodes on a facet have the same
        # coordinates - the centre of the facet.
        c_min, c_max = self.bbox[:, 0]

        node_coors = nm.zeros(nodes.shape, dtype=nm.float64)
        node_coors[:n_v] = nodes[:n_v]

        if (dim > 1) and (n_per_edge > 0):
            ie = nm.where(nts[:, 0] == 1)[0]
            node_coors[ie] = node_coors[geometry.edges[nts[ie, 1]]].mean(1)

        if (dim == 3) and (n_per_face > 0):
            ifa = nm.where(nts[:, 0] == 2)[0]
            node_coors[ifa] = node_coors[geometry.faces[nts[ifa, 1]]].mean(1)

        if n_bubble > 0:
            ib = nm.where(nts[:, 0] == 3)[0]
            node_coors[ib] = node_coors[geometry.conn].mean(0)

        return nodes, nts, node_coors, face_axes, sfnodes
예제 #34
0
파일: fea.py 프로젝트: sdurve/sfepy
    def describe_geometry(self,
                          field,
                          gtype,
                          region,
                          integral=None,
                          return_mapping=False):
        """
        Compute jacobians, element volumes and base function derivatives
        for Volume-type geometries (volume mappings), and jacobians,
        normals and base function derivatives for Surface-type
        geometries (surface mappings).

        Notes
        -----
        - volume mappings can be defined on a part of an element group,
          although the field has to be defined always on the whole group.
        - surface mappings are defined on the surface region
        - surface mappings require field order to be > 0
        """
        domain = field.domain
        group = domain.groups[self.ig]
        coors = domain.get_mesh_coors(actual=True)

        if gtype == 'volume':
            if integral is None:
                from sfepy.fem import Integral
                integral = Integral('i_tmp', 'v', 1)

            qp = self.get_qp('v', integral)

            iels = region.cells[self.ig]

            geo_ps = self.interp.get_geom_poly_space('v')
            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(group.conn, iels, axis=0)
            mapping = VolumeMapping(coors, conn, poly_space=geo_ps)
            vg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     ori=self.ori)

            out = vg

        elif (gtype == 'surface') or (gtype == 'surface_extra'):
            assert_(field.approx_order > 0)

            if self.ori is not None:
                msg = 'surface integrals do not work yet with the' \
                      ' hierarchical basis!'
                raise ValueError(msg)

            sd = domain.surface_groups[self.ig][region.name]
            esd = self.surface_data[region.name]

            qp = self.get_qp(sd.face_type, integral)

            geo_ps = self.interp.get_geom_poly_space(sd.face_type)
            ps = self.interp.poly_spaces[esd.face_type]
            bf = self.get_base(esd.face_type, 0, integral)

            conn = sd.get_connectivity()

            mapping = SurfaceMapping(coors, conn, poly_space=geo_ps)
            sg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps)

            if gtype == 'surface_extra':
                sg.alloc_extra_data(self.get_v_data_shape()[2])

                self.create_bqp(region.name, integral)
                qp = self.qp_coors[(integral.name, esd.bkey)]

                v_geo_ps = self.interp.get_geom_poly_space('v')
                bf_bg = v_geo_ps.eval_base(qp.vals, diff=True)
                ebf_bg = self.get_base(esd.bkey, 1, integral)

                sg.evaluate_bfbgm(bf_bg, ebf_bg, coors, sd.fis, group.conn)

            out = sg

        elif gtype == 'point':
            out = mapping = None

        else:
            raise ValueError('unknown geometry type: %s' % gtype)

        if out is not None:
            # Store the integral used.
            out.integral = integral
            out.qp = qp
            out.ps = ps
            # Update base.
            out.bf[:] = bf

        if return_mapping:
            out = (out, mapping)

        return out
예제 #35
0
파일: fea.py 프로젝트: sdurve/sfepy
    def get_geom_poly_space(self, key):
        assert_(key[0] == 's')

        ps = self.gel.interp.poly_spaces['v']

        return ps
예제 #36
0
def create_task_dof_maps(field,
                         cell_tasks,
                         inter_facets,
                         is_overlap=True,
                         use_expand_dofs=False,
                         save_inter_regions=False,
                         output_dir=None):
    """
    For each task list its inner and interface DOFs of the given field and
    create PETSc numbering that is consecutive in each subdomain.

    For each task, the DOF map has the following structure::

      [inner,
       [own_inter1, own_inter2, ...],
       [overlap_cells1, overlap_cells2, ...],
       n_task_total, task_offset]

    The overlapping cells are defined so that the system matrix corresponding
    to each task can be assembled independently, see [1]. TODO: Some "corner"
    cells may be added even if not needed - filter them out by using the PETSc
    DOFs range.

    When debugging domain partitioning problems, it is advisable to set
    `save_inter_regions` to True to save the task interfaces as meshes as well
    as vertex-based markers - to be used only with moderate problems and small
    numbers of tasks.

    [1] J. Sistek and F. Cirak. Parallel iterative solution of the
    incompressible Navier-Stokes equations with application to rotating
    wings. Submitted for publication, 2015
    """
    domain = field.domain
    cmesh = domain.cmesh

    if use_expand_dofs:
        id_map = nm.zeros(field.n_nod * field.n_components, dtype=nm.uint32)

    else:
        id_map = nm.zeros(field.n_nod, dtype=nm.uint32)

    def _get_dofs_region(field, region):
        dofs = field.get_dofs_in_region(region)
        if use_expand_dofs:
            dofs = expand_dofs(dofs, field.n_components)
        return dofs

    def _get_dofs_conn(field, conn):
        dofs = nm.unique(conn)
        if use_expand_dofs:
            dofs = expand_dofs(dofs, field.n_components)
        return dofs

    dof_maps = {}
    count = 0
    inter_count = 0
    ocs = nm.zeros(0, dtype=nm.int32)
    cell_parts = []
    for ir, ntasks in ordered_iteritems(inter_facets):
        cells = nm.where(cell_tasks == ir)[0].astype(nm.int32)
        cell_parts.append(cells)

        cregion = Region.from_cells(cells, domain, name='task_%d' % ir)
        domain.regions.append(cregion)
        dofs = _get_dofs_region(field, cregion)

        rdof_map = dof_maps.setdefault(ir, [None, [], [], 0, 0])
        inter_dofs = []
        for ic, facets in ordered_iteritems(ntasks):
            cdof_map = dof_maps.setdefault(ic, [None, [], [], 0, 0])

            name = 'inter_%d_%d' % (ir, ic)
            ii = ir

            region = Region.from_facets(facets,
                                        domain,
                                        name,
                                        parent=cregion.name)
            region.update_shape()

            if save_inter_regions:
                output_dir = output_dir if output_dir is not None else '.'
                filename = os.path.join(output_dir, '%s.mesh' % name)

                aux = domain.mesh.from_region(region,
                                              domain.mesh,
                                              is_surface=True)
                aux.write(filename, io='auto')

                mask = nm.zeros((domain.mesh.n_nod, 1), dtype=nm.float64)
                mask[region.vertices] = 1
                out = {name: Struct(name=name, mode='vertex', data=mask)}
                filename = os.path.join(output_dir, '%s.h5' % name)
                domain.mesh.write(filename, out=out, io='auto')

            inter_dofs.append(_get_dofs_region(field, region))

            sd = FESurface('surface_data_%s' % region.name, region,
                           field.efaces, field.econn, field.region)
            econn = sd.get_connectivity()
            n_facet = econn.shape[0]

            ii2 = max(int(n_facet / 2), 1)

            dr = _get_dofs_conn(field, econn[:ii2])
            ii = nm.where((id_map[dr] == 0))[0]
            n_new = len(ii)
            if n_new:
                rdof_map[1].append(dr[ii])
                rdof_map[3] += n_new
                id_map[dr[ii]] = 1
                inter_count += n_new
                count += n_new

                if is_overlap:
                    ovs = cmesh.get_incident(0, region.facets[:ii2],
                                             cmesh.tdim - 1)
                    ocs = cmesh.get_incident(cmesh.tdim, ovs, 0)
                    rdof_map[2].append(ocs.astype(nm.int32))

            dc = _get_dofs_conn(field, econn[ii2:])
            ii = nm.where((id_map[dc] == 0))[0]
            n_new = len(ii)
            if n_new:
                cdof_map[1].append(dc[ii])
                cdof_map[3] += n_new
                id_map[dc[ii]] = 1
                inter_count += n_new
                count += n_new

                if is_overlap:
                    ovs = cmesh.get_incident(0, region.facets[ii2:],
                                             cmesh.tdim - 1)
                    ocs = cmesh.get_incident(cmesh.tdim, ovs, 0)
                    cdof_map[2].append(ocs.astype(nm.int32))

        domain.regions.pop()  # Remove the cell region.

        inner_dofs = nm.setdiff1d(dofs, nm.concatenate(inter_dofs))
        n_inner = len(inner_dofs)
        rdof_map[3] += n_inner
        assert_(nm.all(id_map[inner_dofs] == 0))
        id_map[inner_dofs] = 1
        count += n_inner

        rdof_map[0] = inner_dofs

    offset = 0
    overlap_cells = []
    for ir, dof_map in ordered_iteritems(dof_maps):
        n_owned = dof_map[3]

        i0 = len(dof_map[0])
        id_map[dof_map[0]] = nm.arange(offset, offset + i0, dtype=nm.uint32)
        for aux in dof_map[1]:
            i1 = len(aux)
            id_map[aux] = nm.arange(offset + i0,
                                    offset + i0 + i1,
                                    dtype=nm.uint32)
            i0 += i1

        if len(dof_map[2]):
            ocs = nm.unique(nm.concatenate(dof_map[2]))

        else:
            ocs = nm.zeros(0, dtype=nm.int32)

        overlap_cells.append(ocs)

        assert_(i0 == n_owned)

        dof_map[4] = offset
        offset += n_owned

    if not len(dof_maps):
        dofs = _get_dofs_region(field, field.region)
        dof_maps[0] = [dofs, [], [], len(dofs), 0]
        id_map[:] = nm.arange(len(dofs), dtype=nm.uint32)

    if not len(cell_parts):
        cell_parts.append(nm.arange(len(cell_tasks), dtype=nm.int32))

    if not len(overlap_cells):
        overlap_cells.append(nm.zeros(0, dtype=nm.int32))

    return dof_maps, id_map, cell_parts, overlap_cells
예제 #37
0
파일: test_io.py 프로젝트: zitkat/sfepy
    def test_sparse_matrix_hdf5( self ):
        from sfepy.base.ioutils import write_sparse_matrix_hdf5, read_sparse_matrix_hdf5
        from sfepy.base.ioutils import pt
        if pt is None:
            self.report( 'skipped (no pytables)' )
            return True
        filename = op.join( self.options.out_dir, 'mtx.h5' )

        aux = nm.random.rand( 5, 5 )
        aux[1,:] = aux[:,2] = aux[3,:] = 0.0

        mtx = sp.csr_matrix( aux, dtype = nm.float64 )
#        self.report( 'sparse matrix:\n%s' % mtx )
        self.report( 'saving matrix into %s...' % filename )
        write_sparse_matrix_hdf5( filename, mtx )
        self.report( 'reading...' )
        mtx2 = read_sparse_matrix_hdf5( filename )
#        self.report( 'read matrix:\n%s' % mtx2 )
        self.report( 'difference:\n%s' % (mtx2 - mtx).__repr__() )

        assert_( mtx.shape == mtx2.shape )
        assert_( mtx.dtype == mtx2.dtype )
        assert_( mtx.format == mtx2.format )
        assert_( nm.allclose( mtx.data, mtx2.data ) )
        assert_( nm.allclose( mtx.indices, mtx2.indices ) )
        assert_( nm.allclose( mtx.indptr, mtx2.indptr ) )

        return True
예제 #38
0
    def linearize(self, dofs, min_level=0, max_level=1, eps=1e-4):
        """
        Linearize the solution for post-processing.

        Parameters
        ----------
        dofs : array, shape (n_nod, n_component)
            The array of DOFs reshaped so that each column corresponds
            to one component.
        min_level : int
            The minimum required level of mesh refinement.
        max_level : int
            The maximum level of mesh refinement.
        eps : float
            The relative tolerance parameter of mesh adaptivity.

        Returns
        -------
        mesh : Mesh instance
            The adapted, nonconforming, mesh.
        vdofs : array
            The DOFs defined in vertices of `mesh`.
        levels : array of ints
            The refinement level used for each element group.
        """
        assert_(dofs.ndim == 2)

        n_nod, dpn = dofs.shape

        assert_(n_nod == self.n_nod)
        assert_(dpn == self.shape[0])

        vertex_coors = self.coors[:self.n_vertex_dof, :]

        coors = []
        vdofs = []
        conns = []
        mat_ids = []
        levels = []
        offset = 0
        for ig, ap in self.aps.iteritems():
            ps = ap.interp.poly_spaces['v']
            gps = ap.interp.gel.interp.poly_spaces['v']
            group = self.domain.groups[ig]
            vertex_conn = ap.econn[:, :group.shape.n_ep]

            eval_dofs = get_eval_dofs(dofs, ap.econn, ps, ori=ap.ori)
            eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps)

            (level, _coors, conn,
             _vdofs, _mat_ids) = create_output(eval_dofs, eval_coors,
                                               group.shape.n_el, ps,
                                               min_level=min_level,
                                               max_level=max_level, eps=eps)

            _mat_ids[:] = self.domain.mesh.mat_ids[ig][0]

            coors.append(_coors)
            vdofs.append(_vdofs)
            conns.append(conn + offset)
            mat_ids.append(_mat_ids)
            levels.append(level)

            offset += _coors.shape[0]

        coors = nm.concatenate(coors, axis=0)
        vdofs = nm.concatenate(vdofs, axis=0)
        mesh = Mesh.from_data('linearized_mesh', coors, None, conns, mat_ids,
                              self.domain.mesh.descs)

        return mesh, vdofs, levels
예제 #39
0
def _gen_common_data(orders, gels, report):
    import sfepy
    from sfepy.base.base import Struct
    from sfepy.linalg import combine
    from sfepy.fem import Mesh, Domain, Field, FieldVariable, Integral
    from sfepy.fem.global_interp import get_ref_coors

    bases = ([ii for ii in combine([['2_4', '3_8'],
                                    ['lagrange', 'lobatto']])]
             + [ii for ii in combine([['2_3', '3_4'],
                                      ['lagrange']])])
    for geom, poly_space_base in bases:
        report('geometry: %s, base: %s' % (geom, poly_space_base))

        order = orders[geom]
        integral = Integral('i', order=order)

        aux = '' if geom in ['2_4', '3_8'] else 'z'
        mesh0 = Mesh.from_file('meshes/elements/%s_2%s.mesh' % (geom, aux),
                               prefix_dir=sfepy.data_dir)
        gel = gels[geom]

        perms = gel.get_conn_permutations()

        qps, qp_weights = integral.get_qp(gel.surface_facet.name)
        zz = nm.zeros_like(qps[:, :1])
        qps = nm.hstack(([qps] + [zz]))

        shift = shifts[geom]
        rcoors = nm.ascontiguousarray(qps
                                      + shift[:1, :] - shift[1:, :])
        ccoors = nm.ascontiguousarray(qps
                                      + shift[:1, :] + shift[1:, :])

        for ir, pr in enumerate(perms):
            for ic, pc in enumerate(perms):
                report('ir: %d, ic: %d' % (ir, ic))
                report('pr: %s, pc: %s' % (pr, pc))

                mesh = mesh0.copy()
                conn = mesh.conns[0]
                conn[0, :] = conn[0, pr]
                conn[1, :] = conn[1, pc]

                cache = Struct(mesh=mesh)

                domain = Domain('domain', mesh)
                omega = domain.create_region('Omega', 'all')
                region = domain.create_region('Facet', rsels[geom], 'facet')
                field = Field.from_args('f', nm.float64, shape=1,
                                        region=omega, approx_order=order,
                                        poly_space_base=poly_space_base)
                var = FieldVariable('u', 'unknown', field, 1)
                report('# dofs: %d' % var.n_dof)

                vec = nm.empty(var.n_dof, dtype=var.dtype)

                ap = field.aps[0]
                ps = ap.interp.poly_spaces['v']

                dofs = field.get_dofs_in_region_group(region, 0,
                                                      merge=False)
                edofs, fdofs = nm.unique(dofs[1]), nm.unique(dofs[2])

                rrc, rcells, rstatus = get_ref_coors(field, rcoors,
                                                     cache=cache)
                crc, ccells, cstatus = get_ref_coors(field, ccoors,
                                                     cache=cache)
                assert_((rstatus == 0).all() and (cstatus == 0).all())

                yield (geom, poly_space_base, qp_weights, mesh, ir, ic,
                       ap, ps, rrc, rcells[0, 1], crc, ccells[0, 1],
                       vec, edofs, fdofs)
예제 #40
0
def distribute_fields_dofs(fields,
                           cell_tasks,
                           is_overlap=True,
                           use_expand_dofs=False,
                           save_inter_regions=False,
                           output_dir=None,
                           comm=None,
                           verbose=False):
    """
    Distribute the owned cells and DOFs of the given field to all tasks.

    Uses interleaved PETSc numbering in each task, i.e., the PETSc DOFs of each
    tasks are consecutive and correspond to the first field DOFs block followed
    by the second etc.

    Expand DOFs to equations if `use_expand_dofs` is True.
    """
    if comm is None:
        comm = PETSc.COMM_WORLD

    size = comm.size

    if comm.rank == 0:
        gfds = []
        inter_facets = get_inter_facets(fields[0].domain, cell_tasks)
        for field in fields:
            aux = create_task_dof_maps(field,
                                       cell_tasks,
                                       inter_facets,
                                       is_overlap=is_overlap,
                                       use_expand_dofs=use_expand_dofs,
                                       save_inter_regions=save_inter_regions,
                                       output_dir=output_dir)
            cell_parts = aux[2]
            n_cell_parts = [len(ii) for ii in cell_parts]
            output('numbers of cells in tasks (without overlaps):',
                   n_cell_parts,
                   verbose=verbose)
            assert_(sum(n_cell_parts) == field.domain.mesh.n_el)
            assert_(nm.all(nm.array(n_cell_parts) > 0))

            gfd = Struct(name='global field %s distribution' % field.name,
                         dof_maps=aux[0],
                         id_map=aux[1],
                         cell_parts=aux[2],
                         overlap_cells=aux[3],
                         coffsets=nm.empty(size, dtype=nm.int32))
            gfds.append(gfd)

        # Initialize composite offsets of DOFs.
        if len(fields) > 1:
            # Renumber id_maps for field inter-leaving.
            offset = 0
            for ir in range(size):
                for ii, gfd in enumerate(gfds):
                    dof_map = gfd.dof_maps[ir]
                    n_owned = dof_map[3]
                    off = dof_map[4]

                    iown = nm.concatenate([dof_map[0]] + dof_map[1])
                    gfd.id_map[iown] += offset - off
                    gfd.coffsets[ir] = offset

                    offset += n_owned

        else:
            gfd = gfds[0]
            gfd.coffsets[:] = [gfd.dof_maps[ir][4] for ir in range(size)]

    else:
        gfds = [None] * len(fields)

    lfds = []
    for ii, field in enumerate(fields):
        aux = distribute_field_dofs(field,
                                    gfds[ii],
                                    use_expand_dofs=use_expand_dofs,
                                    comm=comm,
                                    verbose=verbose)
        lfd = Struct(name='local field %s distribution' % field.name,
                     cells=aux[0],
                     petsc_dofs_range=aux[1],
                     petsc_dofs_conn=aux[2])
        lfds.append(lfd)

    return lfds, gfds
예제 #41
0
def verify_task_dof_maps(dof_maps,
                         id_map,
                         field,
                         use_expand_dofs=False,
                         verbose=False):
    """
    Verify the counts and values of DOFs in `dof_maps` and `id_map`
    corresponding to `field`.

    Returns the vector with a task number for each DOF.
    """
    timer = Timer(start=True)
    if verbose:
        output('verifying...')
        output('total number of DOFs:', field.n_nod)
        output('number of tasks:', len(dof_maps))

    count = count2 = 0
    dofs = []
    if use_expand_dofs:
        vec = nm.empty(field.n_nod * field.n_components, dtype=nm.float64)

    else:
        vec = nm.empty(field.n_nod, dtype=nm.float64)
    for ir, dof_map in ordered_iteritems(dof_maps):
        n_owned = dof_map[3]
        offset = dof_map[4]
        o2 = offset + n_owned

        if verbose:
            output('task %d: %d owned on offset %d' % (ir, n_owned, offset))

        if not use_expand_dofs:
            aux = dof_map[0]
            assert_(nm.all((id_map[aux] >= offset) & (id_map[aux] < o2)))

        count2 += dof_map[3]

        count += len(dof_map[0])

        dofs.append(dof_map[0])
        vec[dof_map[0]] = ir
        for aux in dof_map[1]:
            if not use_expand_dofs:
                assert_(nm.all((id_map[aux] >= offset) & (id_map[aux] < o2)))

            count += len(aux)
            dofs.append(aux)
            vec[aux] = ir

    dofs = nm.concatenate(dofs)

    n_dof = vec.shape[0]

    assert_(n_dof == len(dofs))
    if not expand_dofs:
        assert_(nm.all(nm.sort(dofs) == nm.sort(id_map)))

    dofs = nm.unique(dofs)
    assert_(n_dof == len(dofs))

    assert_(n_dof == dofs[-1] + 1)
    assert_(n_dof == count)
    assert_(n_dof == count2)
    assert_(n_dof == len(id_map))
    assert_(n_dof == len(nm.unique(id_map)))

    output('...done in', timer.stop(), verbose=verbose)

    return vec
예제 #42
0
    def classify_args(self):
        """
        Classify types of the term arguments and find matching call
        signature.

        A state variable can be in place of a parameter variable and
        vice versa.
        """
        self.names = Struct(name='arg_names',
                            material=[],
                            variable=[],
                            user=[],
                            state=[],
                            virtual=[],
                            parameter=[])

        # Prepare for 'opt_material' - just prepend a None argument if needed.
        if isinstance(self.arg_types[0], tuple):
            arg_types = self.arg_types[0]

        else:
            arg_types = self.arg_types

        if len(arg_types) == (len(self.args) + 1):
            self.args.insert(0, (None, None))
            self.arg_names.insert(0, (None, None))

        if isinstance(self.arg_types[0], tuple):
            assert_(len(self.modes) == len(self.arg_types))
            # Find matching call signature using variable arguments - material
            # and user arguments are ignored!
            matched = []
            for it, arg_types in enumerate(self.arg_types):
                arg_kinds = get_arg_kinds(arg_types)
                if self._check_variables(arg_kinds):
                    matched.append((it, arg_kinds))

            if len(matched) == 1:
                i_match, arg_kinds = matched[0]
                arg_types = self.arg_types[i_match]
                self.mode = self.modes[i_match]

            elif len(matched) == 0:
                msg = 'cannot match arguments! (%s)' % self.arg_names
                raise ValueError(msg)

            else:
                msg = 'ambiguous arguments! (%s)' % self.arg_names
                raise ValueError(msg)

        else:
            arg_types = self.arg_types
            arg_kinds = get_arg_kinds(self.arg_types)
            self.mode = Struct.get(self, 'mode', None)

            if not self._check_variables(arg_kinds):
                raise ValueError('cannot match variables! (%s)' %
                                 self.arg_names)

        # Set actual argument types.
        self.ats = list(arg_types)

        for ii, arg_kind in enumerate(arg_kinds):
            name = self.arg_names[ii]
            if arg_kind.endswith('variable'):
                names = self.names.variable

                if arg_kind == 'virtual_variable':
                    self.names.virtual.append(name)

                elif arg_kind == 'state_variable':
                    self.names.state.append(name)

                elif arg_kind == 'parameter_variable':
                    self.names.parameter.append(name)

            elif arg_kind.endswith('material'):
                # This should be better checked already in create_arg_parser().
                if not isinstance(name, tuple):
                    raise ValueError('wrong material argument %s of term %s!' %
                                     (name, self.get_str()))
                names = self.names.material

            else:
                names = self.names.user

            names.append(name)

        self.n_virtual = len(self.names.virtual)
        if self.n_virtual > 1:
            raise ValueError('at most one virtual variable is allowed! (%d)' %
                             self.n_virtual)

        self.set_arg_types()

        self.setup_integration()
예제 #43
0
def plot_velocity(source,
                  ctp,
                  bbox,
                  position,
                  family,
                  kind,
                  name,
                  seed='sphere',
                  type='ribbon',
                  integration_direction='both',
                  seed_scale=1.0,
                  seed_resolution=20,
                  widget_enabled=True,
                  color_kind=None,
                  color_name=None,
                  opacity=1.0,
                  **kwargs):
    """
    Show velocity field by displaying streamlines and optionally a
    surface plot given by quantity `color_name`.

    Parameters
    ----------
    seed : one of ('sphere', 'point', 'line', 'plane')
        The streamline seed name.
    type : one of ('line', 'ribbon', 'tube')
        The streamline seed line type.
    integration_direction : one of ('forward', 'backward', 'both')
        The stream tracer integration direction.
    seed_scale : float
        The seed size scale.
    seed_resolution : int
        The number of seed points in a direction (depends on `seed`).
    widget_enabled : bool
        It True, the seed widget is visible and can be interacted with.
    color_kind : str, optional
        The kind of data determining the colormap.
    color_name : str, optional
        The name of data determining the colormap.
    opacity : float
        The surface plot opacity.
    **kwargs : dict
        Additional keyword arguments for attributes of
        `streamline.seed.widget`.
    """
    assert_(kind == 'vectors')

    active_v = mlab.pipeline.set_active_attribute(source)
    active_v.point_vectors_name = name

    active_n = mlab.pipeline.extract_vector_norm(active_v)

    s = mlab.pipeline.streamline
    streamline = s(active_n,
                   seedtype=seed,
                   linetype=type,
                   seed_visible=True,
                   seed_scale=seed_scale,
                   integration_direction=integration_direction,
                   seed_resolution=seed_resolution)
    streamline.update_streamlines = True
    streamline.seed.widget.enabled = widget_enabled
    streamline.actor.actor.position = position

    for key, val in six.iteritems(kwargs):
        setattr(streamline.seed.widget, key, val)

    if color_name is None:
        active = active_n

    else:
        new_name, active = _get_scalars(color_name, color_kind, source)

    surf = mlab.pipeline.surface(active, opacity=opacity)
    surf.actor.actor.position = position

    if color_name is not None:
        mm = active.children[0]
        lm = mm.scalar_lut_manager
        scalar_bars = [['point', new_name, lm]]

        active_v.point_vectors_name = name  # This is needed to have
        # colors by velocity!
        return kind, name, active_n, scalar_bars

    else:
        return kind, name, active_n
예제 #44
0
    def __init__(self, name, regions, dof_names, dof_map_fun,
                 constraints, variables, ts=None, functions=None):
        MRLCBCOperator.__init__(self, name, regions, dof_names, dof_map_fun,
                                variables, functions=functions)
        import sympy as sm

        n_c = self.field.n_components
        dpn = len(self.dof_names)
        n_nod = self.mdofs.shape[0]

        assert_(dpn <= n_c)

        if (isinstance(constraints, basestr)
            or isinstance(constraints, Function)):
            fun = get_condition_value(constraints, functions,
                                      'nodal', 'constraints')
            coors = self.field.get_coor(self.mdofs)
            mtx, rhs = fun(ts, coors, self.region)

        else:
            mtx, rhs = constraints
            mtx = nm.tile(mtx, (n_nod, 1, 1))
            rhs = nm.tile(rhs, (n_nod, 1))

        n_ceq = mtx.shape[1]

        assert_(n_ceq == rhs.shape[1])
        assert_(dpn == mtx.shape[2])
        assert_(n_ceq <= dpn)

        data = []
        rows = []
        cols = []
        rhss = nm.zeros(n_nod * dpn, dtype=nm.float64)
        n_new = 0
        us = [sm.Symbol('u%d' % ii) for ii in range(dpn)]
        for im, nmtx in enumerate(mtx):
            eqs = sm.Matrix(nmtx) * sm.Matrix(us) - rhs[im][:, None]
            sol = sm.solve(eqs)

            assert_(len(sol) == n_ceq)

            imasters = []
            ifixed = []
            islaves = set()
            ccs = []
            for key, _poly in six.iteritems(sol):
                imaster = int(key.name[1:])
                imasters.append(imaster)

                if not isinstance(_poly, sm.Float):
                    poly = _poly.as_poly()

                    # Workaround for poly.all_coeffs() not applicable to
                    # multivariate polynomials.
                    coefs = []
                    for ii, uu in enumerate(us):
                        if poly.has(uu):
                            coefs.append(poly.coeff_monomial(uu))
                            islaves.add(ii)
                    coefs.append(poly.TC())
                    ccs.append(coefs)

                else: # Degenerated constraint - fixed master.
                    ifixed.append(imaster)
                    ccs.append([float(_poly)])

            islaves = sorted(islaves)

            for ii, imaster in enumerate(imasters):
                coefs = ccs[ii]

                em = dpn * im + imaster
                rhss[em] = coefs[-1]

                if imaster in ifixed: continue

                # Master DOF is expressed in terms of slave DOFs.
                for ii, islave in enumerate(islaves):
                    es = ii + n_new

                    rows.append(em)
                    cols.append(es)
                    data.append(coefs[ii])

            # Slave DOFs are copied.
            for ii, islave in enumerate(islaves):
                em = dpn * im + islave
                es = ii + n_new

                rows.append(em)
                cols.append(es)
                data.append(1.0)

            n_new += len(islaves)

        rows = nm.array(rows, dtype=nm.int32)
        cols = nm.array(cols, dtype=nm.int32)
        data = nm.array(data, dtype=nm.float64)

        mtx = sp.coo_matrix((data, (rows, cols)), shape=(n_nod * dpn, n_new))

        self.n_mdof = n_nod * dpn
        self.n_new_dof = n_new
        self.mtx = mtx.tocsr()

        self.rhs = rhss
예제 #45
0
    def get_fargs(self, material, virtual,
                  mode=None, term_mode=None, diff_var=None, **kwargs):
        assert_(virtual.n_components == 1)
        geo, _ = self.get_mapping(virtual)

        return material, geo.bf, geo
예제 #46
0
    def describe_dual_surface(self, surface):
        n_fa, n_edge = surface.n_fa, self.sgel.n_edge

        mesh_coors = self.mesh_coors

        # Face centres.
        fcoors = mesh_coors[surface.econn]
        centre_coors = nm.dot(self.bf.squeeze(), fcoors)

        surface_coors = mesh_coors[surface.nodes]

        dual_coors = nm.r_[surface_coors, centre_coors]
        coor_offset = surface.nodes.shape[0]

        # Normals in primary mesh nodes.
        nodal_normals = compute_nodal_normals(surface.nodes, self.region,
                                              self.field)

        ee = surface.leconn[:, self.sgel.edges].copy()
        edges_per_face = ee.copy()
        sh = edges_per_face.shape
        ee.shape = edges_per_face.shape = (sh[0] * sh[1], sh[2])
        edges_per_face.sort(axis=1)

        eo = nm.empty((sh[0] * sh[1], ), dtype=nm.object)
        eo[:] = [tuple(ii) for ii in edges_per_face]

        ueo, e_sort, e_id = unique(eo, return_index=True, return_inverse=True)
        ueo = edges_per_face[e_sort]

        # edge centre, edge point 1, face centre, edge point 2
        conn = nm.empty((n_edge * n_fa, 4), dtype=nm.int32)
        conn[:, 0] = e_id
        conn[:, 1] = ee[:, 0]
        conn[:,2] = nm.repeat(nm.arange(n_fa, dtype=nm.int32), n_edge) \
                    + coor_offset
        conn[:, 3] = ee[:, 1]

        # face centre, edge point 2, edge point 1
        tri_conn = nm.ascontiguousarray(conn[:, [2, 1, 3]])

        # Ensure orientation - outward normal.
        cc = dual_coors[tri_conn]
        v1 = cc[:, 1] - cc[:, 0]
        v2 = cc[:, 2] - cc[:, 0]

        normals = nm.cross(v1, v2)
        nn = nodal_normals[surface.leconn].sum(axis=1).repeat(n_edge, 0)
        centre_normals = (1.0 / surface.n_fp) * nn
        centre_normals /= la.norm_l2_along_axis(centre_normals)[:, None]
        dot = nm.sum(normals * centre_normals, axis=1)

        assert_((dot > 0.0).all())

        # Prepare mapping from reference triangle e_R to a
        # triangle within reference face e_D.
        gel = self.gel.surface_facet
        ref_coors = gel.coors
        ref_centre = nm.dot(self.bf.squeeze(), ref_coors)
        cc = nm.r_[ref_coors, ref_centre[None, :]]
        rconn = nm.empty((n_edge, 3), dtype=nm.int32)
        rconn[:, 0] = gel.n_vertex
        rconn[:, 1] = gel.edges[:, 0]
        rconn[:, 2] = gel.edges[:, 1]

        map_er_ed = VolumeMapping(cc, rconn, gel=gel)

        # Prepare mapping from reference triangle e_R to a
        # physical triangle e.
        map_er_e = SurfaceMapping(dual_coors, tri_conn, gel=gel)

        # Compute triangle basis (edge) vectors.
        nn = surface.nodes[ueo]
        edge_coors = mesh_coors[nn]

        edge_centre_coors = 0.5 * edge_coors.sum(axis=1)

        edge_normals = 0.5 * nodal_normals[ueo].sum(axis=1)

        edge_normals /= la.norm_l2_along_axis(edge_normals)[:, None]

        nn = surface.nodes[ueo]
        edge_dirs = edge_coors[:, 1] - edge_coors[:, 0]
        edge_dirs /= la.norm_l2_along_axis(edge_dirs)[:, None]

        edge_ortho = nm.cross(edge_normals, edge_dirs)
        edge_ortho /= la.norm_l2_along_axis(edge_ortho)[:, None]

        # Primary face - dual sub-faces map.
        # i-th row: indices to conn corresponding to sub-faces of i-th face.
        face_map = nm.arange(n_fa * n_edge, dtype=nm.int32)
        face_map.shape = (n_fa, n_edge)

        # The actual connectivity for assembling (unique nodes per master
        # faces).
        asm_conn = e_id[face_map]

        n_nod = ueo.shape[0]  # One node per unique edge.
        n_components = self.dim - 1

        dual_surface = Struct(name='dual_surface_description',
                              dim=self.dim,
                              n_dual_fa=conn.shape[0],
                              n_dual_fp=self.dim,
                              n_fa=n_fa,
                              n_edge=n_edge,
                              n_nod=n_nod,
                              n_components=n_components,
                              n_dof=n_nod * n_components,
                              dual_coors=dual_coors,
                              coor_offset=coor_offset,
                              e_sort=e_sort,
                              conn=conn,
                              tri_conn=tri_conn,
                              map_er_e=map_er_e,
                              map_er_ed=map_er_ed,
                              face_map=face_map,
                              asm_conn=asm_conn,
                              nodal_normals=nodal_normals,
                              edge_centre_coors=edge_centre_coors,
                              edge_normals=edge_normals,
                              edge_dirs=edge_dirs,
                              edge_ortho=edge_ortho)

        return dual_surface
예제 #47
0
def gen_misc_mesh(mesh_dir,
                  force_create,
                  kind,
                  args,
                  suffix='.mesh',
                  verbose=False):
    """
    Create sphere or cube mesh according to `kind` in the given
    directory if it does not exist and return path to it.
    """
    import os
    from sfepy import data_dir

    defdir = os.path.join(data_dir, 'meshes')
    if mesh_dir is None:
        mesh_dir = defdir

    def retype(args, types, defaults):
        args = list(args)
        args.extend(defaults[len(args):len(defaults)])
        return tuple([type(value) for type, value in zip(types, args)])

    if kind == 'sphere':
        default = [5, 41, args[0]]
        args = retype(args, [float, int, float], default)
        mesh_pattern = os.path.join(mesh_dir, 'sphere-%.2f-%.2f-%i')

    else:
        assert_(kind == 'cube')

        args = retype(args, (int, float, int, float, int, float),
                      (args[0], args[1], args[0], args[1], args[0], args[1]))
        mesh_pattern = os.path.join(mesh_dir, 'cube-%i_%.2f-%i_%.2f-%i_%.2f')

    if verbose:
        output(args)

    filename = mesh_pattern % args
    if not force_create:
        if os.path.exists(filename): return filename
        if os.path.exists(filename + '.mesh'): return filename + '.mesh'
        if os.path.exists(filename + '.vtk'): return filename + '.vtk'

    if kind == 'cube':
        filename = filename + suffix
        ensure_path(filename)

        output('creating new cube mesh')
        output('(%i nodes in %.2f) x (%i nodes in %.2f) x (%i nodes in %.2f)' %
               args)
        output('to file %s...' % filename)

        mesh = gen_block_mesh(args[1::2],
                              args[0::2], (0.0, 0.0, 0.0),
                              name=filename)
        mesh.write(filename, io='auto')
        output('...done')

    else:
        import subprocess
        filename = filename + '.mesh'
        ensure_path(filename)

        output('creating new sphere mesh (%i nodes, r=%.2f) and gradation %d' %
               args)
        output('to file %s...' % filename)

        f = open(os.path.join(defdir, 'quantum', 'sphere.geo'))
        tmpfile = os.path.join(data_dir, 'tmp', 'sphere.geo.temp')
        ff = open(tmpfile, "w")
        ff.write("""
R = %i.0;
n = %i.0;
dens = %f;
""" % args)
        ff.write(f.read())
        f.close()
        ff.close()
        subprocess.call(
            ['gmsh', '-3', tmpfile, '-format', 'mesh', '-o', filename])

        output('...done')

    return filename
예제 #48
0
    def _eval_basis_transform(self, subs):
        """
        """
        from sfepy.discrete import Integral
        from sfepy.discrete.fem import Mesh, FEDomain, Field

        transform = nm.tile(nm.eye(self.econn.shape[1]),
                            (self.econn.shape[0], 1, 1))
        if subs is None:
            return transform

        gel = self.gel
        ao = self.approx_order

        conn = [gel.conn]
        mesh = Mesh.from_data('a', gel.coors, None, [conn], [nm.array([0])],
                              [gel.name])
        cdomain = FEDomain('d', mesh)
        comega = cdomain.create_region('Omega', 'all')
        rcfield = Field.from_args('rc', self.dtype, 1, comega, approx_order=ao)

        fdomain = cdomain.refine()
        fomega = fdomain.create_region('Omega', 'all')
        rffield = Field.from_args('rf', self.dtype, 1, fomega, approx_order=ao)

        def assign_transform(transform, bf, subs, ef):
            if not len(subs): return

            n_sub = (subs.shape[1] - 2) // 2

            for ii, sub in enumerate(subs):
                for ij in range(n_sub):
                    ik = 2 * (ij + 1)

                    fface = ef[sub[ik + 1]]

                    mtx = transform[sub[ik]]
                    ix, iy = nm.meshgrid(fface, fface)

                    cbf = bf[iy, 0, ix]

                    mtx[ix, iy] = cbf

        fcoors = rffield.get_coor()

        coors = fcoors[rffield.econn[0]]
        integral = Integral('i',
                            coors=coors,
                            weights=nm.ones_like(coors[:, 0]))

        rcfield.clear_qp_base()
        bf = rcfield.get_base('v', False, integral)

        if gel.name == '2_4':
            fsubs = subs
            esubs = None

            assign_transform(transform, bf, fsubs, rffield.efaces)

        else:
            fsubs = subs[0]
            esubs = subs[1]

            assign_transform(transform, bf, fsubs, rffield.efaces)
            if esubs is not None:
                assign_transform(transform, bf, esubs, rffield.eedges)

        assert_((nm.abs(transform.sum(1) - 1.0) < 1e-15).all())

        return transform
예제 #49
0
    def map_equations(self, bcs, field, ts, functions, problem=None,
                      warn=False):
        """
        Create the mapping of active DOFs from/to all DOFs.

        Parameters
        ----------
        bcs : Conditions instance
            The Dirichlet or periodic boundary conditions (single
            condition instances). The dof names in the conditions must
            already be canonized.
        field : Field instance
            The field of the variable holding the DOFs.
        ts : TimeStepper instance
            The time stepper.
        functions : Functions instance
            The registered functions.
        problem : Problem instance, optional
            The problem that can be passed to user functions as a context.
        warn : bool, optional
            If True, warn about BC on non-existent nodes.

        Returns
        -------
        active_bcs : set
            The set of boundary conditions active in the current time.

        Notes
        -----
        - Periodic bc: master and slave DOFs must belong to the same
          field (variables can differ, though).
        """
        if bcs is None:
            self._init_empty(field)
            return set()

        eq_ebc = nm.zeros((self.var_di.n_dof,), dtype=nm.int32)
        val_ebc = nm.zeros((self.var_di.n_dof,), dtype=field.dtype)
        master_slave = nm.zeros((self.var_di.n_dof,), dtype=nm.int32)
        chains = []

        active_bcs = set()
        for bc in bcs:
            # Skip conditions that are not active in the current time.
            if not is_active_bc(bc, ts=ts, functions=functions):
                continue

            active_bcs.add(bc.key)
            if isinstance(bc, DGEssentialBC):
                ntype = "DGEBC"
                region = bc.region
            elif isinstance(bc, DGPeriodicBC):
                ntype = "DGEPBC"
                region = bc.regions[0]
            elif isinstance(bc, EssentialBC):
                ntype = 'EBC'
                region = bc.region
            elif isinstance(bc, PeriodicBC):
                ntype = 'EPBC'
                region = bc.regions[0]

            if warn:
                clean_msg = ('warning: ignoring nonexistent %s node (%s) in '
                             % (ntype, self.var_di.var_name))
            else:
                clean_msg = None

            # Get master region nodes.
            master_nod_list = field.get_dofs_in_region(region)
            if len(master_nod_list) == 0:
                continue

            if ntype == 'EBC': # EBC.
                dofs, val = bc.dofs
                ##
                # Evaluate EBC values.
                fun = get_condition_value(val, functions, 'EBC', bc.name)
                if isinstance(fun, Function):
                    aux = fun
                    fun = lambda coors: aux(ts, coors,
                                            bc=bc, problem=problem)

                nods, vv = field.set_dofs(fun, region, len(dofs), clean_msg)

                eq = expand_nodes_to_equations(nods, dofs, self.dof_names)
                # Duplicates removed here...
                eq_ebc[eq] = 1
                if vv is not None: val_ebc[eq] = nm.ravel(vv)
            elif ntype == "DGEBC":

                dofs, val = bc.dofs
                ##
                # Evaluate EBC values.
                fun = get_condition_value(val, functions, 'EBC', bc.name)
                if isinstance(fun, Function):
                    aux = fun
                    fun = lambda coors: aux(ts, coors,
                                            bc=bc, problem=problem)

                values = field.get_bc_facet_values(fun, region, diff=bc.diff)
                bc2bfi = field.get_bc_facet_idx(region)

                self.dg_ebc_val.setdefault(bc.diff, []).append(values)
                self.dg_ebc.setdefault(bc.diff, []).append(bc2bfi)
                self.n_dg_ebc += 1
            elif ntype == "DGEPBC":

                # ensure matching boundaries?
                master_bc2bfi = field.get_bc_facet_idx(region)
                slave_bc2bfi = field.get_bc_facet_idx(bc.regions[1])

                self.dg_epbc.append((master_bc2bfi, slave_bc2bfi))
                self.n_dg_epbc += 1

            else: # EPBC.
                region = bc.regions[1]
                slave_nod_list = field.get_dofs_in_region(region)

                nmaster = nm.unique(master_nod_list)
                # Treat fields not covering the whole domain.
                if nmaster[0] == -1:
                    nmaster = nmaster[1:]

                nslave = nm.unique(slave_nod_list)
                # Treat fields not covering the whole domain.
                if nslave[0] == -1:
                    nslave = nslave[1:]

                ## print nmaster + 1
                ## print nslave + 1
                if nmaster.shape != nslave.shape:
                    msg = 'EPBC list lengths do not match!\n(%s,\n %s)' %\
                          (nmaster, nslave)
                    raise ValueError(msg)

                if (nmaster.shape[0] == 0) and (nslave.shape[0] == 0):
                    continue

                mcoor = field.get_coor(nmaster)
                scoor = field.get_coor(nslave)

                fun = get_condition_value(bc.match, functions, 'EPBC', bc.name)
                if isinstance(fun, Function):
                    i1, i2 = fun(mcoor, scoor)

                else:
                    i1, i2 = fun

                ## print nm.c_[mcoor[i1], scoor[i2]]
                ## print nm.c_[nmaster[i1], nslave[i2]] + 1

                meq = expand_nodes_to_equations(nmaster[i1], bc.dofs[0],
                                                self.dof_names)
                seq = expand_nodes_to_equations(nslave[i2], bc.dofs[1],
                                                self.dof_names)

                m_assigned = nm.where(master_slave[meq] != 0)[0]
                s_assigned = nm.where(master_slave[seq] != 0)[0]
                if m_assigned.size or s_assigned.size: # Chain EPBC.
                    aux = master_slave[meq[m_assigned]]
                    sgn = nm.sign(aux)
                    om_chain = zip(meq[m_assigned], (aux - sgn) * sgn)
                    chains.extend(om_chain)

                    aux = master_slave[seq[s_assigned]]
                    sgn = nm.sign(aux)
                    os_chain = zip(seq[s_assigned], (aux - sgn) * sgn)
                    chains.extend(os_chain)

                    m_chain = zip(meq[m_assigned], seq[m_assigned])
                    chains.extend(m_chain)

                    msd = nm.setdiff1d(s_assigned, m_assigned)
                    s_chain = zip(meq[msd], seq[msd])
                    chains.extend(s_chain)

                    msa = nm.union1d(m_assigned, s_assigned)
                    ii = nm.setdiff1d(nm.arange(meq.size), msa)
                    master_slave[meq[ii]] = seq[ii] + 1
                    master_slave[seq[ii]] = - meq[ii] - 1

                else:
                    master_slave[meq] = seq + 1
                    master_slave[seq] = - meq - 1

        chains = group_chains(chains)
        resolve_chains(master_slave, chains)

        self.master = nm.nonzero(master_slave > 0)[0]
        self.slave = master_slave[self.master] - 1

        # Propagate EBCs via PBCs.
        mask = eq_ebc[self.master] > 0
        im0 = self.master[mask]
        im1 = self.slave[mask]
        mask = eq_ebc[self.slave] > 0
        is0 = self.slave[mask]
        is1 = self.master[mask]
        val_ebc[im1] = val_ebc[im0]
        eq_ebc[im1] = eq_ebc[im0]
        val_ebc[is1] = val_ebc[is0]
        eq_ebc[is1] = eq_ebc[is0]

        self.eq_ebc = nm.nonzero(eq_ebc > 0)[0]
        self.val_ebc = val_ebc[self.eq_ebc]
        assert_((self.eq_ebc.shape == self.val_ebc.shape))

        self.eq[self.eq_ebc] = -2
        self.eq[self.master] = -1

        self._mark_unused(field)

        self.eqi = self.eq[self.eq >= 0]
        self.eq[self.eqi] = nm.arange(self.eqi.shape[0], dtype=nm.int32)
        self.eq[self.master] = self.eq[self.slave]
        self.n_eq = self.eqi.shape[0]
        self.n_ebc = self.eq_ebc.shape[0]
        self.n_epbc = self.master.shape[0]

        return active_bcs
예제 #50
0
def main():
    parser = ArgumentParser(description=__doc__)
    parser.add_argument('--version', action='version', version='%(prog)s')
    parser.add_argument('-b',
                        '--basis',
                        metavar='name',
                        action='store',
                        dest='basis',
                        default='lagrange',
                        help=help['basis'])
    parser.add_argument('-n',
                        '--max-order',
                        metavar='order',
                        type=int,
                        action='store',
                        dest='max_order',
                        default=10,
                        help=help['max_order'])
    parser.add_argument('-m',
                        '--matrix',
                        metavar='type',
                        action='store',
                        dest='matrix_type',
                        default='laplace',
                        help=help['matrix_type'])
    parser.add_argument('-g',
                        '--geometry',
                        metavar='name',
                        action='store',
                        dest='geometry',
                        default='2_4',
                        help=help['geometry'])
    options = parser.parse_args()

    dim, n_ep = int(options.geometry[0]), int(options.geometry[2])
    output('reference element geometry:')
    output('  dimension: %d, vertices: %d' % (dim, n_ep))

    n_c = {'laplace': 1, 'elasticity': dim}[options.matrix_type]

    output('matrix type:', options.matrix_type)
    output('number of variable components:', n_c)

    output('polynomial space:', options.basis)

    output('max. order:', options.max_order)

    mesh = Mesh.from_file(data_dir +
                          '/meshes/elements/%s_1.mesh' % options.geometry)
    domain = FEDomain('domain', mesh)
    omega = domain.create_region('Omega', 'all')

    orders = nm.arange(1, options.max_order + 1, dtype=nm.int)
    conds = []

    order_fix = 0 if options.geometry in ['2_4', '3_8'] else 1

    for order in orders:
        output('order:', order, '...')

        field = Field.from_args('fu',
                                nm.float64,
                                n_c,
                                omega,
                                approx_order=order,
                                space='H1',
                                poly_space_base=options.basis)

        to = field.approx_order
        quad_order = 2 * (max(to - order_fix, 0))
        output('quadrature order:', quad_order)

        integral = Integral('i', order=quad_order)
        qp, _ = integral.get_qp(options.geometry)
        output('number of quadrature points:', qp.shape[0])

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

        m = Material('m', D=stiffness_from_lame(dim, 1.0, 1.0), mu=1.0)

        if options.matrix_type == 'laplace':
            term = Term.new('dw_laplace(m.mu, v, u)',
                            integral,
                            omega,
                            m=m,
                            v=v,
                            u=u)
            n_zero = 1

        else:
            assert_(options.matrix_type == 'elasticity')
            term = Term.new('dw_lin_elastic(m.D, v, u)',
                            integral,
                            omega,
                            m=m,
                            v=v,
                            u=u)
            n_zero = (dim + 1) * dim / 2

        term.setup()

        output('assembling...')
        tt = time.clock()
        mtx, iels = term.evaluate(mode='weak', diff_var='u')
        output('...done in %.2f s' % (time.clock() - tt))
        mtx = mtx[0, 0]

        try:
            assert_(nm.max(nm.abs(mtx - mtx.T)) < 1e-10)

        except:
            from sfepy.base.base import debug
            debug()

        output('matrix shape:', mtx.shape)

        eigs = eig(mtx, method='eig.sgscipy', eigenvectors=False)
        eigs.sort()

        # Zero 'true' zeros.
        eigs[:n_zero] = 0.0

        ii = nm.where(eigs < 0.0)[0]
        if len(ii):
            output('matrix is not positive semi-definite!')

        ii = nm.where(eigs[n_zero:] < 1e-12)[0]
        if len(ii):
            output('matrix has more than %d zero eigenvalues!' % n_zero)

        output('smallest eigs:\n', eigs[:10])

        ii = nm.where(eigs > 0.0)[0]
        emin, emax = eigs[ii[[0, -1]]]

        output('min:', emin, 'max:', emax)

        cond = emax / emin
        conds.append(cond)

        output('condition number:', cond)

        output('...done')

    plt.figure(1)
    plt.semilogy(orders, conds)
    plt.xticks(orders, orders)
    plt.xlabel('polynomial order')
    plt.ylabel('condition number')
    plt.grid()

    plt.figure(2)
    plt.loglog(orders, conds)
    plt.xticks(orders, orders)
    plt.xlabel('polynomial order')
    plt.ylabel('condition number')
    plt.grid()

    plt.show()
예제 #51
0
파일: fields.py 프로젝트: takluyver/sfepy
    def set_dofs(self, fun=0.0, region=None, dpn=None, warn=None):
        """
        Set the values of DOFs given by the `region` using a function of space
        coordinates or value `fun`.

        If `fun` is a function, the l2 projection that is global for all region
        facets is used to set the DOFs.

        If `dpn > 1`, and `fun` is a function, it has to return the values
        DOF-by-DOF, i.e. a single one-dimensional vector with all values of the
        first component, then of the second one etc. concatenated
        together.

        Parameters
        ----------
        fun : float or array of length dpn or callable
            The DOF values.
        region : Region
            The region containing the DOFs.
        dpn : int, optional
            The DOF-per-node count. If not given, the number of field
            components is used.
        warn : str, optional
            The warning message printed when the region selects no DOFs.

        Returns
        -------
        nods : array, shape (n_dof,)
            The field DOFs (or node indices) given by the region.
        vals : array, shape (dpn, n_dof)
            The values of the DOFs, DOF-by-DOF when raveled in C (row-major)
            order.
        """
        if region is None:
            region = self.region

        if dpn is None:
            dpn = self.n_components

        nods = []
        vals = []

        aux = self.get_dofs_in_region(region)
        nods = nm.unique(nm.hstack(aux))

        if nm.isscalar(fun):
            vals = nm.repeat([fun], nods.shape[0] * dpn)

        elif isinstance(fun, nm.ndarray):
            assert_(len(fun) == dpn)
            vals = nm.repeat(fun, nods.shape[0])

        elif callable(fun):
            import scipy.sparse as sps
            from sfepy.solvers.ls import solve
            from sfepy.discrete.integrals import Integral
            from sfepy.discrete.fem.utils import prepare_remap
            import sfepy.discrete.iga as iga
            from sfepy.discrete.iga.extmods.igac import eval_mapping_data_in_qp

            nurbs = self.nurbs
            facets = self._get_facets(region.kind_tdim)

            # Region facet connectivity.
            rconn = self.get_econn('surface', region)

            # Local connectivity.
            remap = prepare_remap(nods, nods.max() + 1)
            lconn = [remap[ii] for ii in rconn]

            # Cell and face(cell) ids for each facet.
            fis = region.get_facet_indices()

            # Integral given by max. NURBS surface degree.
            fdegrees = iga.get_surface_degrees(nurbs.degrees)
            order = fdegrees.max()
            integral = Integral('i', order=2 * order)
            vals, weights = integral.get_qp(self.domain.gel.surface_facet_name)

            # Boundary QP - use tensor product structure.
            bvals = iga.create_boundary_qp(vals, region.tdim)

            # Compute facet basis, jacobians and physical BQP.
            n_dof = len(nods)
            rhs = nm.zeros((dpn, n_dof), dtype=nm.float64)
            rows, cols, mvals = [], [], []
            all_qp = []
            all_fbfs = []
            all_dets = []
            for ii, (ie, ifa) in enumerate(fis):
                qp_coors = bvals[ifa]

                bfs, _, dets = eval_mapping_data_in_qp(qp_coors, nurbs.cps,
                                                       nurbs.weights,
                                                       nurbs.degrees, nurbs.cs,
                                                       nurbs.conn,
                                                       nm.array([ie]))
                # Facet basis.
                fbfs = bfs[..., facets[ifa]][0, :, 0, :]

                # Weight Jacobians by quadrature point weights.
                dets = nm.abs(dets) * weights[None, :, None, None]
                dets = dets[0, :, 0, :]

                # Physical BQP.
                fcps = nurbs.cps[nurbs.conn[ie, facets[ifa]]]
                qp = nm.dot(fbfs, fcps)

                all_qp.append(qp)
                all_fbfs.append(fbfs)
                all_dets.append(dets)

            # DOF values in the physical BQP.
            qps = nm.concatenate(all_qp)
            vals = nm.asarray(fun(qps))
            vals.shape = (dpn, qps.shape[0])

            n_qp_face = len(bvals[0])

            # Assemble l2 projection system.
            for ii, (ie, ifa) in enumerate(fis):
                # Assembling indices.
                elc = lconn[ii]

                fvals = vals[:, n_qp_face * ii:n_qp_face * (ii + 1)]

                fbfs = all_fbfs[ii]
                dets = all_dets[ii]

                # Local projection system.
                for idof in xrange(dpn):
                    lrhs = (fbfs * (fvals[idof, :, None] * dets)).sum(0)
                    rhs[idof, elc] += lrhs

                lmtx = ((fbfs[..., None] * fbfs[:, None, :]) *
                        dets[..., None]).sum(0)

                er, ec = nm.meshgrid(elc, elc)
                rows.append(er.ravel())
                cols.append(ec.ravel())
                mvals.append(lmtx.ravel())

            rows = nm.concatenate(rows)
            cols = nm.concatenate(cols)
            mvals = nm.concatenate(mvals)
            mtx = sps.coo_matrix((mvals, (rows, cols)), shape=(n_dof, n_dof))

            vals = nm.zeros((dpn, n_dof), dtype=nm.float64)

            # Solve l2 projection system.
            for idof in xrange(dpn):
                dofs = solve(mtx, rhs[idof, :])
                vals[idof, remap[nods]] = dofs

        else:
            raise ValueError('unknown function/value type! (%s)' % type(fun))

        return nods, vals
예제 #52
0
def main():
    from sfepy import data_dir

    parser = OptionParser(usage=usage, version='%prog')
    parser.add_option('--diffusivity',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='diffusivity',
                      default=1e-5,
                      help=helps['diffusivity'])
    parser.add_option('--ic-max',
                      metavar='float',
                      type=float,
                      action='store',
                      dest='ic_max',
                      default=2.0,
                      help=helps['ic_max'])
    parser.add_option('--order',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='order',
                      default=2,
                      help=helps['order'])
    parser.add_option('-r',
                      '--refine',
                      metavar='int',
                      type=int,
                      action='store',
                      dest='refine',
                      default=0,
                      help=helps['refine'])
    parser.add_option('-p',
                      '--probe',
                      action="store_true",
                      dest='probe',
                      default=False,
                      help=helps['probe'])
    parser.add_option('-s',
                      '--show',
                      action="store_true",
                      dest='show',
                      default=False,
                      help=helps['show'])
    options, args = parser.parse_args()

    assert_((0 < options.order),
            'temperature approximation order must be at least 1!')

    output('using values:')
    output('  diffusivity:', options.diffusivity)
    output('  max. IC value:', options.ic_max)
    output('uniform mesh refinement level:', options.refine)

    mesh = Mesh.from_file(data_dir + '/meshes/3d/cylinder.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.00001', 'facet')
    right = domain.create_region('Right', 'vertices in x > 0.099999', 'facet')

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

    T = FieldVariable('T', 'unknown', field, history=1)
    s = FieldVariable('s', 'test', field, primary_var_name='T')

    m = Material('m', diffusivity=options.diffusivity * nm.eye(3))

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

    t1 = Term.new('dw_diffusion(m.diffusivity, s, T)',
                  integral,
                  omega,
                  m=m,
                  s=s,
                  T=T)
    t2 = Term.new('dw_volume_dot(s, dT/dt)', integral, omega, s=s, T=T)
    eq = Equation('balance', t1 + t2)
    eqs = Equations([eq])

    # Boundary conditions.
    ebc1 = EssentialBC('T1', left, {'T.0': 2.0})
    ebc2 = EssentialBC('T2', right, {'T.0': -2.0})

    # Initial conditions.
    def get_ic(coors, ic):
        x, y, z = coors.T
        return 2 - 40.0 * x + options.ic_max * nm.sin(4 * nm.pi * x / 0.1)

    ic_fun = Function('ic_fun', get_ic)
    ic = InitialCondition('ic', omega, {'T.0': ic_fun})

    ls = ScipyDirect({})

    nls_status = IndexedStruct()
    nls = Newton({'is_linear': True}, lin_solver=ls, status=nls_status)

    pb = Problem('heat', equations=eqs, nls=nls, ls=ls)
    pb.set_bcs(ebcs=Conditions([ebc1, ebc2]))
    pb.set_ics(Conditions([ic]))

    tss = SimpleTimeSteppingSolver({
        't0': 0.0,
        't1': 100.0,
        'n_step': 11
    },
                                   problem=pb)
    tss.init_time()

    if options.probe:
        # Prepare probe data.
        probes, labels = gen_lines(pb)

        ev = pb.evaluate
        order = 2 * (options.order - 1)

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

        nls_options = {'eps_a': 1e-16, 'i_max': 1}

        if options.show:
            plt.ion()

    # Solve the problem using the time stepping solver.
    suffix = tss.ts.suffix
    for step, time, state in tss():
        if options.probe:
            # Probe the solution.
            dvel_qp = ev('ev_diffusion_velocity.%d.Omega(m.diffusivity, T)' %
                         order,
                         copy_materials=False,
                         mode='qp')
            project_by_component(dvel,
                                 dvel_qp,
                                 component,
                                 order,
                                 nls_options=nls_options)

            all_results = []
            for ii, probe in enumerate(probes):
                fig, results = probe_results(ii, T, dvel, probe, labels[ii])

                all_results.append(results)

            plt.tight_layout()
            fig.savefig('time_poisson_interactive_probe_%s.png' %
                        (suffix % step),
                        bbox_inches='tight')

            if options.show:
                plt.draw()

            for ii, results in enumerate(all_results):
                output('probe %d (%s):' % (ii, probes[ii].name))
                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
예제 #53
0
    def get_graph_conns(self,
                        any_dof_conn=False,
                        rdcs=None,
                        cdcs=None,
                        active_only=True):
        """
        Get DOF connectivities needed for creating tangent matrix graph.

        Parameters
        ----------
        any_dof_conn : bool
            By default, only volume DOF connectivities are used, with
            the exception of trace surface DOF connectivities. If True,
            any kind of DOF connectivities is allowed.
        rdcs, cdcs : arrays, optional
            Additional row and column DOF connectivities, corresponding
            to the variables used in the equations.
        active_only : bool
            If True, the active DOF connectivities have reduced size and are
            created with the reduced (active DOFs only) numbering.

        Returns
        -------
        rdcs, cdcs : arrays
            The row and column DOF connectivities defining the matrix
            graph blocks.
        """
        if rdcs is None:
            rdcs = []
            cdcs = []

        elif cdcs is None:
            cdcs = copy(rdcs)

        else:
            assert_(len(rdcs) == len(cdcs))
            if rdcs is cdcs:  # Make sure the lists are not the same object.
                rdcs = copy(rdcs)

        adcs = self.variables.adof_conns

        # Only volume dof connectivities are used, with the exception of trace
        # surface dof connectivities.
        shared = set()
        for key, ii, info in iter_dict_of_lists(self.conn_info,
                                                return_keys=True):
            rvar, cvar = info.virtual, info.state
            if (rvar is None) or (cvar is None):
                continue

            is_surface = rvar.is_surface or cvar.is_surface

            dct = info.dc_type.type
            if not (dct in ('volume', 'scalar', 'custom') or is_surface
                    or info.is_trace or any_dof_conn):
                continue

            rreg_name = info.get_region_name(can_trace=False)
            creg_name = info.get_region_name()

            rname = rvar.get_primary_name()
            rkey = (rname, rreg_name, dct, False)
            ckey = (cvar.name, creg_name, dct, info.is_trace)

            dc_key = (rkey, ckey)

            if not dc_key in shared:
                rdc = adcs[rkey]
                cdc = adcs[ckey]
                if not active_only:
                    ii = nm.where(rdc < 0)
                    rdc = rdc.copy()
                    rdc[ii] = -1 - rdc[ii]

                    ii = nm.where(cdc < 0)
                    cdc = cdc.copy()
                    cdc[ii] = -1 - cdc[ii]

                rdcs.append(rdc)
                cdcs.append(cdc)

                shared.add(dc_key)

        return rdcs, cdcs
예제 #54
0
    def _region_leaf(level, op):
        token, details = op['token'], op['orig']

        if token != 'KW_Region':
            parse_def = token + '<' + ' '.join(details) + '>'
            region = Region('leaf', rdef, domain, parse_def=parse_def)

        if token == 'KW_Region':
            details = details[1][2:]
            aux = regions.find(details)
            if not aux:
                raise ValueError('region %s does not exist' % details)
            else:
                if rdef[:4] == 'copy':
                    region = aux.copy()
                else:
                    region = aux

        elif token == 'KW_All':
            region.vertices = nm.arange(n_coor, dtype=nm.uint32)

        elif token == 'E_VIR':
            where = details[2]

            if where[0] == '[':
                vertices = nm.array(eval(where), dtype=nm.uint32)
                assert_(nm.amin(vertices) >= 0)
                assert_(nm.amax(vertices) < n_coor)
            else:
                coors = domain.cmesh.coors
                y = z = None
                x = coors[:, 0]

                if dim > 1:
                    y = coors[:, 1]

                if dim > 2:
                    z = coors[:, 2]

                coor_dict = {'x': x, 'y': y, 'z': z}

                vertices = nm.where(eval(where, {}, coor_dict))[0]

            region.vertices = vertices

        elif token == 'E_VOS':
            facets = domain.cmesh.get_surface_facets()

            region.set_kind('facet')
            region.facets = facets

        elif token == 'E_VBF':
            where = details[2]

            coors = domain.cmesh.coors

            fun = functions[where]
            vertices = fun(coors, domain=domain)

            region.vertices = vertices

        elif token == 'E_CBF':
            where = details[2]

            coors = domain.get_centroids(dim)

            fun = functions[where]
            cells = fun(coors, domain=domain)

            region.cells = cells

        elif token == 'E_COG':
            group = int(details[3])

            region.cells = nm.where(domain.cmesh.cell_groups == group)[0]

        elif token == 'E_COSET':
            raise NotImplementedError('element sets not implemented!')

        elif token == 'E_VOG':
            group = int(details[3])

            region.vertices = nm.where(domain.cmesh.vertex_groups == group)[0]

        elif token == 'E_VOSET':
            try:
                vertices = domain.vertex_set_bcs[details[3]]

            except KeyError:
                msg = 'undefined vertex set! (%s)' % details[3]
                raise ValueError(msg)

            region.vertices = vertices

        elif token == 'E_OVIR':
            aux = regions[details[3][2:]]
            region.vertices = aux.vertices[0:1]

        elif token == 'E_VI':
            region.vertices = nm.array([int(ii) for ii in details[1:]],
                                       dtype=nm.uint32)

        elif token == 'E_CI':
            region.cells = nm.array([int(ii) for ii in details[1:]],
                                    dtype=nm.uint32)

        else:
            output('token "%s" unkown - check regions!' % token)
            raise NotImplementedError
        return region
예제 #55
0
def define(dims=(3, 1, 0.5),
           shape=(11, 15, 15),
           u_order=1,
           refine=0,
           ls='ls_d',
           u_inlet=None,
           mode='lcbc',
           term_mode='original',
           backend='numpy',
           optimize='optimal',
           verbosity=0):
    """
    Parameters
    ----------
    dims : tuple
        The block domain dimensions.
    shape : tuple
        The mesh resolution: increase to improve accuracy.
    u_order : int
        The velocity field approximation order.
    refine : int
        The refinement level.
    ls : 'ls_d' or 'ls_i'
        The pre-configured linear solver name.
    u_inlet : float, optional
        The x-component of the inlet velocity.
    mode : 'lcbc' or 'penalty'
        The alternative formulations.
    term_mode : 'original' or 'einsum'
        The switch to use either the original or new experimental einsum-based
        terms.
    backend : str
        The einsum mode backend.
    optimize : str
        The einsum mode optimization (backend dependent).
    verbosity : 0, 1, 2, 3
        The verbosity level of einsum-based terms.
    """
    output('dims: {}, shape: {}, u_order: {}, refine: {}, u_inlet: {}'.format(
        dims, shape, u_order, refine, u_inlet))
    output('linear solver: {}'.format(ls))
    output('mode: {}, term_mode: {}'.format(mode, term_mode))
    if term_mode == 'einsum':
        output('backend: {}, optimize: {}, verbosity: {}'.format(
            backend, optimize, verbosity))

    assert_(mode in {'lcbc', 'penalty'})
    assert_(term_mode in {'original', 'einsum'})
    if u_order > 1:
        assert_(mode == 'penalty', msg='set mode=penalty to use u_order > 1!')
    dims = nm.array(dims, dtype=nm.float64)
    shape = nm.array(shape, dtype=nm.int32)

    def mesh_hook(mesh, mode):
        """
        Generate the block mesh.
        """
        if mode == 'read':
            mesh = gen_block_mesh(dims,
                                  shape, [0, 0, 0],
                                  name='user_block',
                                  verbose=False)
            return mesh

        elif mode == 'write':
            pass

    filename_mesh = UserMeshIO(mesh_hook)

    regions = define_box_regions(3, 0.5 * dims)
    regions.update({
        'Omega':
        'all',
        'Edges_v': ("""(r.Near *v r.Bottom) +v
                        (r.Bottom *v r.Far) +v
                        (r.Far *v r.Top) +v
                        (r.Top *v r.Near)""", 'edge'),
        'Gamma1_f': ('copy r.Top', 'face'),
        'Gamma2_f': ('r.Near +v r.Bottom +v r.Far', 'face'),
        'Gamma_f': ('r.Gamma1_f +v r.Gamma2_f', 'face'),
        'Gamma_v': ('r.Gamma_f -v r.Edges_v', 'face'),
        'Inlet_f': ('r.Left -v r.Gamma_f', 'face'),
    })

    fields = {
        'velocity': ('real', 3, 'Omega', u_order),
        'pressure': ('real', 1, 'Omega', 1),
    }

    def get_u_d(ts, coors, region=None):
        """
        Given stator velocity.
        """
        out = nm.zeros_like(coors)
        out[:] = [1.0, 1.0, 0.0]

        return out

    functions = {
        'get_u_d': (get_u_d, ),
    }

    variables = {
        'u': ('unknown field', 'velocity', 0),
        'v': ('test field', 'velocity', 'u'),
        'u_d': ('parameter field', 'velocity', {
            'setter': 'get_u_d'
        }),
        'p': ('unknown field', 'pressure', 1),
        'q': ('test field', 'pressure', 'p'),
    }

    materials = {
        'm': ({
            'nu': 1e-3,
            'beta': 1e-2,
            'mu': 1e-10,
        }, ),
    }

    ebcs = {}
    if u_inlet is not None:
        ebcs['inlet'] = ('Inlet_f', {'u.0': u_inlet, 'u.[1, 2]': 0.0})

    if mode == 'lcbc':
        lcbcs = {
            'walls': ('Gamma_v', {
                'u.all': None
            }, None, 'no_penetration', 'normals_Gamma.vtk'),
            'edges': ('Edges_v', [(-0.5, 1.5)], {
                'u.all': None
            }, None, 'edge_direction', 'edges_Edges.vtk'),
        }

        if term_mode == 'original':
            equations = {
                'balance':
                """dw_div_grad.5.Omega(m.nu, v, u)
                 - dw_stokes.5.Omega(v, p)
                 + dw_dot.5.Gamma1_f(m.beta, v, u)
                 + dw_dot.5.Gamma2_f(m.beta, v, u)
                 =
                 + dw_dot.5.Gamma1_f(m.beta, v, u_d)""",
                'incompressibility':
                """dw_laplace.5.Omega(m.mu, q, p)
                 + dw_stokes.5.Omega(u, q) = 0""",
            }

        else:
            equations = {
                'balance':
                """de_div_grad.5.Omega(m.nu, v, u)
                 - de_stokes.5.Omega(v, p)
                 + de_dot.5.Gamma1_f(m.beta, v, u)
                 + de_dot.5.Gamma2_f(m.beta, v, u)
                 =
                 + de_dot.5.Gamma1_f(m.beta, v, u_d)""",
                'incompressibility':
                """de_laplace.5.Omega(m.mu, q, p)
                 + de_stokes.5.Omega(u, q) = 0""",
            }

    else:
        materials['m'][0]['np_eps'] = 1e3

        if term_mode == 'original':
            equations = {
                'balance':
                """dw_div_grad.5.Omega(m.nu, v, u)
                 - dw_stokes.5.Omega(v, p)
                 + dw_dot.5.Gamma1_f(m.beta, v, u)
                 + dw_dot.5.Gamma2_f(m.beta, v, u)
                 + dw_non_penetration_p.5.Gamma1_f(m.np_eps, v, u)
                 + dw_non_penetration_p.5.Gamma2_f(m.np_eps, v, u)
                 =
                 + dw_dot.5.Gamma1_f(m.beta, v, u_d)""",
                'incompressibility':
                """dw_laplace.5.Omega(m.mu, q, p)
                 + dw_stokes.5.Omega(u, q) = 0""",
            }

        else:
            equations = {
                'balance':
                """de_div_grad.5.Omega(m.nu, v, u)
                 - de_stokes.5.Omega(v, p)
                 + de_dot.5.Gamma1_f(m.beta, v, u)
                 + de_dot.5.Gamma2_f(m.beta, v, u)
                 + de_non_penetration_p.5.Gamma1_f(m.np_eps, v, u)
                 + de_non_penetration_p.5.Gamma2_f(m.np_eps, v, u)
                 =
                 + de_dot.5.Gamma1_f(m.beta, v, u_d)""",
                'incompressibility':
                """de_laplace.5.Omega(m.mu, q, p)
                 + de_stokes.5.Omega(u, q) = 0""",
            }

    solvers = {
        'ls_d': ('ls.auto_direct', {}),
        'ls_i': (
            'ls.petsc',
            {
                'method': 'bcgsl',  # ksp_type
                'precond': 'bjacobi',  # pc_type
                'sub_precond': 'ilu',  # sub_pc_type
                'eps_a': 0.0,  # abstol
                'eps_r': 1e-12,  # rtol
                'eps_d': 1e10,  # Divergence tolerance.
                'i_max': 200,  # maxits
            }),
        'newton': ('nls.newton', {
            'i_max': 1,
            'eps_a': 1e-10,
        }),
    }

    options = {
        'nls': 'newton',
        'ls': ls,
        'eterm': {
            'verbosity': verbosity,
            'backend_args': {
                'backend': backend,
                'optimize': optimize,
                'layout': None,
            },
        },
        'refinement_level': refine,
    }

    return locals()
예제 #56
0
def get_simplex_circumcentres(coors, force_inside_eps=None):
    """
    Compute the circumcentres of `n_s` simplices in 1D, 2D and 3D.

    Parameters
    ----------
    coors : array
        The coordinates of the simplices with `n_v` vertices given in an
        array of shape `(n_s, n_v, dim)`, where `dim` is the space
        dimension and `2 <= n_v <= (dim + 1)`.
    force_inside_eps : float, optional
        If not None, move the circumcentres that are outside of their
        simplices or closer to their boundary then `force_inside_eps` so
        that they are inside the simplices at the distance given by
        `force_inside_eps`. It is ignored for edges.

    Returns
    -------
    centres : array
        The circumcentre coordinates as an array of shape `(n_s, dim)`.
    """
    n_s, n_v, dim = coors.shape

    assert_(2 <= n_v <= (dim + 1))
    assert_(1 <= dim <= 3)

    if n_v == 2: # Edges.
        centres = 0.5 * nm.sum(coors, axis=1)

    else:
        if n_v == 3: # Triangles.
            a2 = norm(coors[:,1,:] - coors[:,2,:], squared=True)
            b2 = norm(coors[:,0,:] - coors[:,2,:], squared=True)
            c2 = norm(coors[:,0,:] - coors[:,1,:], squared=True)

            bar_coors = nm.c_[a2 * (-a2 + b2 + c2),
                              b2 * (a2 - b2 + c2),
                              c2 * (a2 + b2 - c2)]

        elif n_v == 4: # Tetrahedrons.
            a2 = norm(coors[:,2,:] - coors[:,1,:], squared=True)
            b2 = norm(coors[:,2,:] - coors[:,0,:], squared=True)
            c2 = norm(coors[:,1,:] - coors[:,0,:], squared=True)
            d2 = norm(coors[:,3,:] - coors[:,0,:], squared=True)
            e2 = norm(coors[:,3,:] - coors[:,1,:], squared=True)
            f2 = norm(coors[:,3,:] - coors[:,2,:], squared=True)
            bar_coors = nm.c_[(d2 * a2 * (f2 + e2 - a2)
                               + b2 * e2 * (a2 + f2 - e2)
                               + c2 * f2 * (e2 + a2 - f2)
                               - 2 * a2 * e2 * f2),
                              (e2 * b2 * (f2 + d2 - b2)
                               +  c2 * f2 * (d2 + b2 - f2)
                               +  a2 * d2 * (b2 + f2 - d2)
                               - 2 * b2 * d2 * f2),
                              (f2 * c2 * (e2 + d2 - c2)
                               +  b2 * e2 * (d2 + c2 - e2)
                               +  a2 * d2 * (c2 + e2 - d2)
                               - 2 * c2 * e2 * d2),
                              (d2 * a2 * (b2 + c2 - a2)
                               +  e2 * b2 * (c2 + a2 - b2)
                               +  f2 * c2 * (a2 + b2 - c2)
                               - 2 * a2 * b2 * c2)]

        else:
            raise ValueError('unsupported simplex! (%d vertices)' % n_v)

        bar_coors /= nm.sum(bar_coors, axis=1)[:,None]
        if force_inside_eps is not None:
            bc = 1.0 / n_v
            limit = 0.9 * bc
            bar_centre = nm.array([bc] * n_v, dtype=nm.float64)

            eps = float(force_inside_eps)
            if eps > limit:
                output('force_inside_eps is too big, adjusting! (%e -> %e)'
                       % (eps, limit))
                eps = limit

            # Flag is True where the barycentre is closer to the simplex
            # boundary then eps, or outside of the simplex.
            mb = nm.min(bar_coors, axis=1)
            flag = nm.where(mb < eps)[0]

            # Move the bar_coors[flag] towards bar_centre so that it is
            # inside at the eps distance.
            mb = mb[flag]
            alpha = ((eps - mb) / (bar_centre[0] - mb))[:,None]

            bar_coors[flag] = (1.0 - alpha) * bar_coors[flag] \
                              + alpha * bar_centre[None,:]

        centres = transform_bar_to_space_coors(bar_coors, coors)

    return centres
예제 #57
0
    def call_mlab(self,
                  scene=None,
                  show=True,
                  is_3d=False,
                  view=None,
                  roll=None,
                  parallel_projection=False,
                  fgcolor=(0.0, 0.0, 0.0),
                  bgcolor=(1.0, 1.0, 1.0),
                  colormap='blue-red',
                  layout='rowcol',
                  scalar_mode='iso_surface',
                  vector_mode='arrows_norm',
                  rel_scaling=None,
                  clamping=False,
                  ranges=None,
                  is_scalar_bar=False,
                  is_wireframe=False,
                  opacity=None,
                  subdomains_args=None,
                  rel_text_width=None,
                  fig_filename='view.png',
                  resolution=None,
                  filter_names=None,
                  only_names=None,
                  group_names=None,
                  step=None,
                  time=None,
                  anti_aliasing=None,
                  domain_specific=None):
        """
        By default, all data (point, cell, scalars, vectors, tensors)
        are plotted in a grid layout, except data named 'node_groups',
        'mat_id' which are usually not interesting.

        Parameters
        ----------
        show : bool
            Call mlab.show().
        is_3d : bool
            If True, use scalar cut planes instead of surface for certain
            datasets. Also sets 3D view mode.
        view : tuple
            Azimuth, elevation angles, distance and focal point as in
            `mlab.view()`.
        roll : float
            Roll angle tuple as in mlab.roll().
        parallel_projection: bool
            If True, use parallel projection.
        fgcolor : tuple of floats (R, G, B)
            The foreground color, that is the color of all text
            annotation labels (axes, orientation axes, scalar bar
            labels).
        bgcolor : tuple of floats (R, G, B)
            The background color.
        colormap : str
            The colormap name.
        layout : str
            Grid layout for placing the datasets. Possible values are:
            'row', 'col', 'rowcol', 'colrow'.
        scalar_mode : str
             Mode for plotting scalars and tensor magnitudes, one of
             'cut_plane', 'iso_surface', 'both'.
        vector_mode : str
             Mode for plotting vectors, one of 'arrows', 'norm', 'arrows_norm',
             'warp_norm'.
        rel_scaling : float
            Relative scaling of glyphs for vector datasets.
        clamping : bool
            Clamping for vector datasets.
        ranges : dict
            List of data ranges in the form {name : (min, max), ...}.
        is_scalar_bar : bool
            If True, show a scalar bar for each data.
        is_wireframe : bool
            If True, show a wireframe of mesh surface bar for each data.
        opacity : float
            Global surface and wireframe opacity setting in [0.0, 1.0],
        subdomains_args : tuple
            Tuple of (mat_id_name, threshold_limits, single_color), see
            :func:`add_subdomains_surface`, or None.
        rel_text_width : float
            Relative text width.
        fig_filename : str
            File name for saving the resulting scene figure.
        resolution : tuple
            Scene and figure resolution. If None, it is set
            automatically according to the layout.
        filter_names : list of strings
            Omit the listed datasets. If None, it is initialized to
            ['node_groups', 'mat_id']. Pass [] if you need no filtering.
        only_names : list of strings
            Draw only the listed datasets. If None, it is initialized all names
            besides those in filter_names.
        group_names : list of tuples
            List of data names in the form [(name1, ..., nameN), (...)]. Plots
            of data named in each group are superimposed. Repetitions of names
            are possible.
        step : int, optional
            If not None, the time step to display. The closest higher step is
            used if the desired one is not available. Has precedence over
            `time`.
        time : float, optional
            If not None, the time of the time step to display. The closest
            higher time is used if the desired one is not available.
        anti_aliasing : int
            Value of anti-aliasing.
        domain_specific : dict
            Domain-specific drawing functions and configurations.
        """
        self.fgcolor = fgcolor
        self.bgcolor = bgcolor
        self.colormap = colormap

        if filter_names is None:
            filter_names = ['node_groups', 'mat_id']

        if rel_text_width is None:
            rel_text_width = 0.02

        if isinstance(scalar_mode, basestr):
            if scalar_mode == 'both':
                scalar_mode = ('cut_plane', 'iso_surface')
            elif scalar_mode in ('cut_plane', 'iso_surface'):
                scalar_mode = (scalar_mode, )
            else:
                raise ValueError('bad value of scalar_mode parameter! (%s)' %
                                 scalar_mode)
        else:
            for sm in scalar_mode:
                if not sm in ('cut_plane', 'iso_surface'):
                    raise ValueError(
                        'bad value of scalar_mode parameter! (%s)' % sm)

        if isinstance(vector_mode, basestr):
            if vector_mode == 'arrows_norm':
                vector_mode = ('arrows', 'norm')
            elif vector_mode == 'warp_norm':
                vector_mode = ('warp', 'norm')
            elif vector_mode in ('arrows', 'norm'):
                vector_mode = (vector_mode, )
            elif vector_mode == 'cut_plane':
                if is_3d:
                    vector_mode = ('cut_plane', )
                else:
                    vector_mode = ('arrows', )
            else:
                raise ValueError('bad value of vector_mode parameter! (%s)' %
                                 vector_mode)
        else:
            for vm in vector_mode:
                if not vm in ('arrows', 'norm', 'warp'):
                    raise ValueError(
                        'bad value of vector_mode parameter! (%s)' % vm)

        mlab.options.offscreen = self.offscreen

        self.size_hint = self.get_size_hint(layout, resolution=resolution)

        is_new_scene = False

        if scene is not None:
            if scene is not self.scene:
                is_new_scene = True
                self.scene = scene
            gui = None

        else:
            if (self.scene is not None) and (not self.scene.running):
                self.scene = None

            if self.scene is None:
                if self.offscreen or not show:
                    gui = None
                    scene = mlab.figure(fgcolor=fgcolor,
                                        bgcolor=bgcolor,
                                        size=self.size_hint)

                else:
                    gui = ViewerGUI(viewer=self,
                                    fgcolor=fgcolor,
                                    bgcolor=bgcolor)
                    scene = gui.scene.mayavi_scene

                if scene is not self.scene:
                    is_new_scene = True
                    self.scene = scene

            else:
                gui = self.gui
                scene = self.scene

        self.engine = mlab.get_engine()
        self.engine.current_scene = self.scene

        self.gui = gui

        self.file_source = create_file_source(self.filename,
                                              watch=self.watch,
                                              offscreen=self.offscreen)
        steps, times = self.file_source.get_ts_info()
        has_several_times = len(times) > 1
        has_several_steps = has_several_times or (len(steps) > 1)

        if gui is not None:
            gui.has_several_steps = has_several_steps

        self.reload_source = reload_source = ReloadSource()
        reload_source._viewer = self
        reload_source._source = self.file_source

        if has_several_steps:
            self.set_step = set_step = SetStep()
            set_step._viewer = self
            set_step._source = self.file_source
            if step is not None:
                step = step if step >= 0 else steps[-1] + step + 1
                assert_(steps[0] <= step <= steps[-1],
                        msg='invalid time step! (%d <= %d <= %d)' %
                        (steps[0], step, steps[-1]))
                set_step.step = step

            elif time is not None:
                assert_(times[0] <= time <= times[-1],
                        msg='invalid time! (%e <= %e <= %e)' %
                        (times[0], time, times[-1]))
                set_step.time = time

            else:
                set_step.step = steps[0]

            if self.watch:
                self.file_source.setup_notification(set_step, 'file_changed')

            if gui is not None:
                gui.set_step = set_step

        else:
            if self.watch:
                self.file_source.setup_notification(reload_source,
                                                    'reload_source')

        self.options.update(get_arguments(omit=['self', 'file_source']))

        if gui is None:
            self.render_scene(scene, self.options)
            self.reset_view()
            if is_scalar_bar:
                self.show_scalar_bars(self.scalar_bars)

        else:
            traits_view = View(
                Item(
                    'scene',
                    editor=SceneEditor(scene_class=MayaviScene),
                    show_label=False,
                    width=self.size_hint[0],
                    height=self.size_hint[1],
                    style='custom',
                ),
                Group(
                    Item('set_step',
                         defined_when='set_step is not None',
                         show_label=False,
                         style='custom'), ),
                HGroup(
                    spring,
                    Item('button_make_snapshots_steps',
                         show_label=False,
                         enabled_when='has_several_steps == True'),
                    Item('button_make_animation_steps',
                         show_label=False,
                         enabled_when='has_several_steps == True'),
                    spring,
                    Item('button_make_snapshots_times',
                         show_label=False,
                         enabled_when='has_several_steps == True'),
                    Item('button_make_animation_times',
                         show_label=False,
                         enabled_when='has_several_steps == True'),
                    spring,
                ),
                HGroup(spring, Item('button_reload', show_label=False),
                       Item('button_view', show_label=False),
                       Item('button_quit', show_label=False)),
                resizable=True,
                buttons=[],
                handler=ClosingHandler(),
            )

            if is_new_scene:
                if show:
                    gui.configure_traits(view=traits_view)

                else:
                    gui.edit_traits(view=traits_view)

        return gui
예제 #58
0
 def _build_rhs( self, sols ):
     for sol in sols.itervalues():
         assert_( len( sol ) == 3 )
     return sols
예제 #59
0
def define(dim=2, use_ebcs=True):
    assert_(dim in (2, 3))

    if dim == 2:
        filename_mesh = data_dir + '/meshes/2d/square_quad.mesh'

    else:
        filename_mesh = data_dir + '/meshes/3d/cube_medium_tetra.mesh'

    options = {
        'nls': 'newton',
        'ls': 'ls',
        'post_process_hook': 'post_process'
    }

    def get_constraints(ts, coors, region=None):
        mtx = nm.ones((coors.shape[0], 1, dim), dtype=nm.float64)

        rhs = nm.arange(coors.shape[0], dtype=nm.float64)[:, None]

        rhs *= 0.1 / (coors.shape[0] - 1)

        return mtx, rhs

    functions = {
        'get_constraints': (get_constraints, ),
    }

    fields = {
        'displacement': ('real', dim, 'Omega', 1),
    }

    materials = {
        'm': ({
            'D': stiffness_from_lame(dim, lam=5.769, mu=3.846),
        }, ),
        'load': ({
            'val': -1.0
        }, ),
    }

    variables = {
        'u': ('unknown field', 'displacement', 0),
        'v': ('test field', 'displacement', 'u'),
    }

    regions = {
        'Omega': 'all',
        'Bottom': ('vertices in (y < -0.499) -v r.Left', 'facet'),
        'Top': ('vertices in (y > 0.499) -v r.Left', 'facet'),
        'Left': ('vertices in (x < -0.499)', 'facet'),
        'Right': ('vertices in (x > 0.499) -v (r.Bottom +v r.Top)', 'facet'),
    }

    if dim == 2:
        lcbcs = {
            'nlcbc1': ('Top', {
                'u.all': None
            }, None, 'nodal_combination', ([[1.0, -1.0]], [0.0])),
            'nlcbc2': ('Bottom', {
                'u.all': None
            }, None, 'nodal_combination', ([[1.0, 1.0]], [-0.1])),
            'nlcbc3': ('Right', {
                'u.all': None
            }, None, 'nodal_combination', 'get_constraints'),
        }

    else:
        lcbcs = {
            'nlcbc1': ('Top', {
                'u.all': None
            }, None, 'nodal_combination', ([[1.0, -1.0, 1.0],
                                            [1.0, 0.5, 0.1]], [0.0, 0.05])),
            'nlcbc2': ('Bottom', {
                'u.[2,1]': None
            }, None, 'nodal_combination', ([[1.0, -0.1]], [0.2])),
            'nlcbc3': ('Right', {
                'u.all': None
            }, None, 'nodal_combination', 'get_constraints'),
        }

    if use_ebcs:
        ebcs = {
            'fix': ('Left', {
                'u.all': 0.0
            }),
        }

    else:
        ebcs = {}

        lcbcs.update({
            'nlcbc4': ('Left', {
                'u.all': None
            }, None, 'nodal_combination', (nm.eye(dim), nm.zeros(dim))),
        })

    equations = {
        'elasticity':
        """
            dw_lin_elastic.2.Omega(m.D, v, u)
            = -dw_surface_ltr.2.Right(load.val, v)
        """,
    }

    solvers = {
        'ls': ('ls.scipy_direct', {}),
        'newton': ('nls.newton', {
            'i_max': 1,
            'eps_a': 1e-10,
        }),
    }

    return locals()
예제 #60
0
파일: ls.py 프로젝트: mfkiwl/sfepy
    def __call__(self,
                 rhs,
                 x0=None,
                 conf=None,
                 eps_a=None,
                 eps_r=None,
                 i_max=None,
                 mtx=None,
                 status=None,
                 **kwargs):
        import os, sys, shutil, tempfile
        from sfepy import base_dir, data_dir
        from sfepy.base.ioutils import ensure_path

        eps_a = get_default(eps_a, self.conf.eps_a)
        eps_r = get_default(eps_r, self.conf.eps_r)
        i_max = get_default(i_max, self.conf.i_max)
        eps_d = self.conf.eps_d

        petsc = self.petsc

        # There is no use in caching matrix in the solver - always set as new.
        pmtx, psol, prhs = self.set_matrix(mtx)

        ksp = self.ksp
        ksp.setOperators(pmtx)
        ksp.setFromOptions()  # PETSc.Options() not used yet...
        ksp.setTolerances(atol=eps_a, rtol=eps_r, divtol=eps_d, max_it=i_max)

        output_dir = tempfile.mkdtemp()

        # Set PETSc rhs, solve, get solution from PETSc solution.
        if x0 is not None:
            psol[...] = x0
            sol0_filename = os.path.join(output_dir, 'sol0.dat')

        else:
            sol0_filename = ''

        prhs[...] = rhs

        script_filename = os.path.join(base_dir, 'solvers/petsc_worker.py')

        mtx_filename = os.path.join(output_dir, 'mtx.dat')
        rhs_filename = os.path.join(output_dir, 'rhs.dat')
        sol_filename = os.path.join(output_dir, 'sol.dat')
        status_filename = os.path.join(output_dir, 'status.txt')

        log_filename = os.path.join(data_dir, 'tmp/sol.log')
        ensure_path(log_filename)

        output('storing system to %s...' % output_dir)
        tt = time.clock()
        view_mtx = petsc.Viewer().createBinary(mtx_filename, mode='w')
        view_rhs = petsc.Viewer().createBinary(rhs_filename, mode='w')
        pmtx.view(view_mtx)
        prhs.view(view_rhs)
        if sol0_filename:
            view_sol0 = petsc.Viewer().createBinary(sol0_filename, mode='w')
            psol.view(view_sol0)
        output('...done in %.2f s' % (time.clock() - tt))

        command = [
            'mpiexec -n %d' % self.conf.n_proc,
            sys.executable,
            script_filename,
            '-mtx %s' % mtx_filename,
            '-rhs %s' % rhs_filename,
            '-sol0 %s' % sol0_filename,
            '-sol %s' % sol_filename,
            '-status %s' % status_filename,
            '-ksp_type %s' % self.conf.method,
            '-pc_type %s' % self.conf.precond,
            '-sub_pc_type %s' % self.conf.sub_precond,
            '-ksp_atol %.3e' % self.conf.eps_a,
            '-ksp_rtol %.3e' % self.conf.eps_r,
            '-ksp_max_it %d' % self.conf.i_max,
            '-ksp_monitor %s' % log_filename,
            '-ksp_view %s' % log_filename,
        ]
        if self.conf.precond_side is not None:
            command.append('-ksp_pc_side %s' % self.conf.precond_side)

        out = os.system(" ".join(command))
        assert_(out == 0)

        output('reading solution...')
        tt = time.clock()
        view_sol = self.petsc.Viewer().createBinary(sol_filename, mode='r')
        psol = petsc.Vec().load(view_sol)

        fd = open(status_filename, 'r')
        line = fd.readline().split()
        reason = int(line[0])
        elapsed = float(line[1])
        fd.close()
        output('...done in %.2f s' % (time.clock() - tt))

        sol = psol[...].copy()
        output('%s(%s, %s/proc) convergence: %s (%s)' %
               (self.conf.method, self.conf.precond, self.conf.sub_precond,
                reason, self.converged_reasons[reason]))
        output('elapsed: %.2f [s]' % elapsed)

        shutil.rmtree(output_dir)

        return sol