Exemple #1
0
    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):
        timer = Timer(start=True)

        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)

        elapsed = timer.stop()
        if status is not None:
            status['time'] = elapsed
            status['n_iter'] = self.ksp.getIterationNumber()

        return result
Exemple #2
0
    def presolve(self, mtx):
        """Prepare A^{-1} B^T for the Schur complement."""

        mtx_a = mtx['A']
        mtx_bt = mtx['BT']
        output('full A size: %.3f MB' % (8.0 * nm.prod(mtx_a.shape) / 1e6))
        output('full B size: %.3f MB' % (8.0 * nm.prod(mtx_bt.shape) / 1e6))

        ls = Solver.any_from_conf(self.problem.ls_conf +
                                  Struct(use_presolve=True),
                                  mtx=mtx_a)
        if self.mode == 'explicit':
            timer = Timer(start=True)
            mtx_aibt = nm.zeros(mtx_bt.shape, dtype=mtx_bt.dtype)
            for ic in range(mtx_bt.shape[1]):
                mtx_aibt[:, ic] = ls(mtx_bt[:, ic].toarray().squeeze())
            output('mtx_aibt: %.2f s' % timer.stop())
            action_aibt = MatrixAction.from_array(mtx_aibt)
        else:
            ##
            # c: 30.08.2007, r: 13.02.2008
            def fun_aibt(vec):
                # Fix me for sparse mtx_bt...
                rhs = sc.dot(mtx_bt, vec)
                out = ls(rhs)
                return out

            action_aibt = MatrixAction.from_function(
                fun_aibt, (mtx_a.shape[0], mtx_bt.shape[1]), nm.float64)
        mtx['action_aibt'] = action_aibt
    def _standard_ts_call(self,
                          vec0=None,
                          nls=None,
                          init_fun=None,
                          prestep_fun=None,
                          poststep_fun=None,
                          status=None,
                          **kwargs):
        timer = Timer(start=True)

        nls = get_default(nls, self.nls,
                          'nonlinear solver has to be specified!')

        init_fun = get_default(init_fun, lambda ts, vec0: vec0)
        prestep_fun = get_default(prestep_fun, lambda ts, vec: None)
        poststep_fun = get_default(poststep_fun, lambda ts, vec: None)

        result = call(self,
                      vec0=vec0,
                      nls=nls,
                      init_fun=init_fun,
                      prestep_fun=prestep_fun,
                      poststep_fun=poststep_fun,
                      status=status,
                      **kwargs)

        elapsed = timer.stop()
        if status is not None:
            status['time'] = elapsed
            status['n_step'] = self.ts.n_step

        return result
Exemple #4
0
    def _standard_call(self,
                       mtx_m,
                       mtx_d,
                       mtx_k,
                       n_eigs=None,
                       eigenvectors=None,
                       status=None,
                       conf=None,
                       **kwargs):
        timer = Timer(start=True)

        conf = get_default(conf, self.conf)
        mtx_m = get_default(mtx_m, self.mtx_m)
        mtx_d = get_default(mtx_d, self.mtx_d)
        mtx_k = get_default(mtx_k, self.mtx_k)
        n_eigs = get_default(n_eigs, self.n_eigs)
        eigenvectors = get_default(eigenvectors, self.eigenvectors)
        status = get_default(status, self.status)

        result = call(self, mtx_m, mtx_d, mtx_k, n_eigs, eigenvectors, status,
                      conf, **kwargs)

        elapsed = timer.stop()
        if status is not None:
            status['time'] = elapsed

        return result
Exemple #5
0
    def time_update(self,
                    ts,
                    equations,
                    mode='normal',
                    problem=None,
                    verbose=True):
        """
        Update material parameters for given time, problem, and equations.

        Parameters
        ----------
        ts : TimeStepper instance
            The time stepper.
        equations : Equations instance
            The equations using the materials.
        mode : 'normal', 'update' or 'force'
            The update mode, see :func:`Material.time_update()`.
        problem : Problem instance, optional
            The problem that can be passed to user functions as a context.
        verbose : bool
            If False, reduce verbosity.
        """
        if verbose: output('updating materials...')
        timer = Timer(start=True)
        for mat in self:
            if verbose: output(' ', mat.name)
            mat.time_update(ts, equations, mode=mode, problem=problem)
        if verbose: output('...done in %.2f s' % timer.stop())
    def create_regions(self, region_defs, functions=None, allow_empty=False):
        output('creating regions...')
        timer = Timer(start=True)

        self.reset_regions()

        ##
        # Sort region definitions by dependencies.
        graph, name_to_sort_name = get_dependency_graph(region_defs)
        sorted_regions = sort_by_dependency(graph)

        ##
        # Define regions.
        for name in sorted_regions:
            sort_name = name_to_sort_name[name]
            rdef = region_defs[sort_name]

            region = self.create_region(name,
                                        rdef.select,
                                        kind=rdef.get('kind', 'cell'),
                                        parent=rdef.get('parent', None),
                                        check_parents=False,
                                        extra_options=rdef.get(
                                            'extra_options', None),
                                        functions=functions,
                                        allow_empty=allow_empty)
            output(' ', region.name)

        output('...done in %.2f s' % timer.stop())

        return self.regions
Exemple #7
0
    def _standard_call(self,
                       mtx_a,
                       mtx_b=None,
                       n_eigs=None,
                       eigenvectors=None,
                       status=None,
                       conf=None,
                       **kwargs):
        timer = Timer(start=True)

        conf = get_default(conf, self.conf)
        mtx_a = get_default(mtx_a, self.mtx_a)
        mtx_b = get_default(mtx_b, self.mtx_b)
        n_eigs = get_default(n_eigs, self.n_eigs)
        eigenvectors = get_default(eigenvectors, self.eigenvectors)
        status = get_default(status, self.status)

        if n_eigs == 0:
            result = self._ret_zero(mtx_a, eigenvectors=eigenvectors)

        else:
            result = call(self, mtx_a, mtx_b, n_eigs, eigenvectors, status,
                          conf, **kwargs)

        elapsed = timer.stop()
        if status is not None:
            status['time'] = elapsed

        return result
Exemple #8
0
    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):
        timer = Timer(start=True)

        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.

        elapsed = timer.stop()
        if status is not None:
            status['time'] = elapsed
            status['n_iter'] = n_iter

        return result
Exemple #9
0
    def __call__(self, vec_x0, conf=None, fun=None, fun_grad=None,
                 lin_solver=None, iter_hook=None, status=None):
        if conf is not None:
            self.set_method(conf)
        else:
            conf = self.conf
        fun = get_default(fun, self.fun)
        status = get_default(status, self.status)

        timer = Timer(start=True)

        kwargs = {'iter' : conf.i_max,
                  'alpha' : conf.alpha,
                  'verbose' : conf.verbose}

        if conf.method == 'broyden_generalized':
            kwargs.update({'M' : conf.M})

        elif conf.method in ['anderson', 'anderson2']:
            kwargs.update({'M' : conf.M, 'w0' : conf.w0})

        if conf.method in ['anderson', 'anderson2',
                           'broyden', 'broyden2' , 'newton_krylov']:
            kwargs.update({'f_tol' : conf.f_tol })

        vec_x = self.solver(fun, vec_x0, **kwargs)
        vec_x = nm.asarray(vec_x)

        if status is not None:
            status['time_stats'] = timer.stop()

        return vec_x
Exemple #10
0
    def create_conn_graph(self, verbose=True):
        """
        Create a graph of mesh connectivity.

        Returns
        -------
        graph : csr_matrix
            The mesh connectivity graph as a SciPy CSR matrix.
        """
        from sfepy.discrete.common.extmods.cmesh import create_mesh_graph

        shape = (self.n_nod, self.n_nod)
        output('graph shape:', shape, verbose=verbose)
        if nm.prod(shape) == 0:
            output('no graph (zero size)!', verbose=verbose)
            return None

        output('assembling mesh graph...', verbose=verbose)
        timer = Timer(start=True)

        conn = self.get_conn(self.descs[0])
        nnz, prow, icol = create_mesh_graph(shape[0], shape[1],
                                            1, [conn], [conn])
        output('...done in %.2f s' % timer.stop(), verbose=verbose)
        output('graph nonzeros: %d (%.2e%% fill)' \
               % (nnz, float(nnz) / nm.prod(shape)), verbose=verbose)

        data = nm.ones((nnz,), dtype=nm.bool)
        graph = sp.csr_matrix((data, icol, prow), shape)

        return graph
def assemble_mtx_to_petsc(pmtx,
                          mtx,
                          pdofs,
                          drange,
                          is_overlap=True,
                          comm=None,
                          verbose=False):
    """
    Assemble a local CSR matrix to a global PETSc matrix.
    """
    if comm is None:
        comm = PETSc.COMM_WORLD

    timer = Timer()

    lgmap = PETSc.LGMap().create(pdofs, comm=comm)
    pmtx.setLGMap(lgmap, lgmap)
    if is_overlap:
        output('setting matrix values...', verbose=verbose)
        timer.start()
        mask = (pdofs < drange[0]) | (pdofs >= drange[1])
        nnz_per_row = nm.diff(mtx.indptr)
        mtx2 = mtx.copy()
        mtx2.data[nm.repeat(mask, nnz_per_row)] = 0
        mtx2.eliminate_zeros()
        pmtx.setValuesLocalCSR(mtx2.indptr, mtx2.indices, mtx2.data,
                               PETSc.InsertMode.INSERT_VALUES)
        output('...done in', timer.stop(), verbose=verbose)

        output('assembling matrix...', verbose=verbose)
        timer.start()
        pmtx.assemble()
        output('...done in', timer.stop(), verbose=verbose)

    else:
        output('setting matrix values...', verbose=verbose)
        timer.start()
        pmtx.setValuesLocalCSR(mtx.indptr, mtx.indices, mtx.data,
                               PETSc.InsertMode.ADD_VALUES)
        output('...done in', timer.stop(), verbose=verbose)

        output('assembling matrix...', verbose=verbose)
        timer.start()
        pmtx.assemble()
        output('...done in', timer.stop(), verbose=verbose)
Exemple #12
0
    def solve_eigen_problem(self):
        opts = self.app_options
        pb = self.problem

        pb.set_equations(pb.conf.equations)
        pb.time_update()

        output('assembling lhs...')
        timer = Timer(start=True)
        mtx_a = pb.evaluate(pb.conf.equations['lhs'],
                            mode='weak',
                            auto_init=True,
                            dw_mode='matrix')
        output('...done in %.2f s' % timer.stop())

        if 'rhs' in pb.conf.equations:
            output('assembling rhs...')
            timer.start()
            mtx_b = pb.evaluate(pb.conf.equations['rhs'],
                                mode='weak',
                                dw_mode='matrix')
            output('...done in %.2f s' % timer.stop())

        else:
            mtx_b = None

        _n_eigs = get_default(opts.n_eigs, mtx_a.shape[0])

        output('solving eigenvalue problem for {} values...'.format(_n_eigs))
        eig = Solver.any_from_conf(pb.get_solver_conf(opts.evps))
        if opts.eigs_only:
            eigs = eig(mtx_a, mtx_b, opts.n_eigs, eigenvectors=False)
            svecs = None

        else:
            eigs, svecs = eig(mtx_a, mtx_b, opts.n_eigs, eigenvectors=True)

        output('...done')

        vecs = self.make_full(svecs)
        self.save_results(eigs, vecs)

        return Struct(pb=pb, eigs=eigs, vecs=vecs)
def assemble_rhs_to_petsc(prhs,
                          rhs,
                          pdofs,
                          drange,
                          is_overlap=True,
                          comm=None,
                          verbose=False):
    """
    Assemble a local right-hand side vector to a global PETSc vector.
    """
    if comm is None:
        comm = PETSc.COMM_WORLD

    timer = Timer()
    if is_overlap:
        output('setting rhs values...', verbose=verbose)
        timer.start()
        rdofs = nm.where((pdofs < drange[0]) | (pdofs >= drange[1]), -1, pdofs)
        prhs.setOption(prhs.Option.IGNORE_NEGATIVE_INDICES, True)
        prhs.setValues(rdofs, rhs, PETSc.InsertMode.INSERT_VALUES)
        output('...done in', timer.stop(), verbose=verbose)

        output('assembling rhs...', verbose=verbose)
        timer.start()
        prhs.assemble()
        output('...done in', timer.stop(), verbose=verbose)

    else:
        output('setting rhs values...', verbose=verbose)
        timer.start()
        prhs.setValues(pdofs, rhs, PETSc.InsertMode.ADD_VALUES)
        output('...done in', timer.stop(), verbose=verbose)

        output('assembling rhs...', verbose=verbose)
        timer.start()
        prhs.assemble()
        output('...done in', timer.stop(), verbose=verbose)
Exemple #14
0
    def from_file(filename=None,
                  io='auto',
                  prefix_dir=None,
                  omit_facets=False,
                  file_format=None):
        """
        Read a mesh from a file.

        Parameters
        ----------
        filename : string or function or MeshIO instance or Mesh instance
            The name of file to read the mesh from. For convenience, a
            mesh creation function or a MeshIO instance or directly a Mesh
            instance can be passed in place of the file name.
        io : *MeshIO instance
            Passing *MeshIO instance has precedence over filename.
        prefix_dir : str
            If not None, the filename is relative to that directory.
        omit_facets : bool
            If True, do not read cells of lower dimension than the space
            dimension (faces and/or edges). Only some MeshIO subclasses
            support this!
        """
        if isinstance(filename, Mesh):
            return filename

        if io == 'auto':
            if filename is None:
                output('filename or io must be specified!')
                raise ValueError
            else:
                io = MeshIO.any_from_filename(filename,
                                              prefix_dir=prefix_dir,
                                              file_format=file_format)

        output('reading mesh (%s)...' % io.filename)
        timer = Timer(start=True)

        trunk = io.get_filename_trunk()
        mesh = Mesh(trunk)
        mesh = io.read(mesh, omit_facets=omit_facets)

        output('...done in %.2f s' % timer.stop())

        mesh._set_shape_info()

        return mesh
Exemple #15
0
    def __call__(self, volume=None, problem=None, data=None):
        problem = get_default(problem, self.problem)
        opts = self.app_options

        evp, dv_info = [data[ii] for ii in self.requires]

        output('computing eigenmomenta...')

        if opts.transform is not None:
            fun = problem.conf.get_function(opts.transform[0])

            def wrap_transform(vec, shape):
                return fun(vec, shape, *opts.eig_vector_transform[1:])

        else:
            wrap_transform = None

        timer = Timer(start=True)
        eigenmomenta = compute_eigenmomenta(self.expression, opts.var_name,
                                            problem, evp.eig_vectors,
                                            wrap_transform)
        output('...done in %.2f s' % timer.stop())

        n_eigs = evp.eigs.shape[0]

        mag = norm_l2_along_axis(eigenmomenta)

        if opts.threshold_is_relative:
            tol = opts.threshold * mag.max()
        else:
            tol = opts.threshold

        valid = nm.where(mag < tol, False, True)
        mask = nm.where(valid == False)[0]
        eigenmomenta[mask, :] = 0.0
        n_zeroed = mask.shape[0]

        output('%d of %d eigenmomenta zeroed (under %.2e)'\
                % (n_zeroed, n_eigs, tol))

        out = Struct(name='eigenmomenta',
                     n_zeroed=n_zeroed,
                     eigenmomenta=eigenmomenta,
                     valid=valid,
                     to_file_txt=None)
        return out
Exemple #16
0
def check_tangent_matrix(conf, vec_x0, fun, fun_grad):
    """
    Verify the correctness of the tangent matrix as computed by `fun_grad()` by
    comparing it with its finite difference approximation evaluated by
    repeatedly calling `fun()` with `vec_x0` items perturbed by a small delta.
    """
    vec_x = vec_x0.copy()
    delta = conf.delta

    vec_r = fun(vec_x) # Update state.
    mtx_a0 = fun_grad(vec_x)

    mtx_a = mtx_a0.tocsc()
    mtx_d = mtx_a.copy()
    mtx_d.data[:] = 0.0

    vec_dx = nm.zeros_like(vec_r)

    for ic in range(vec_dx.shape[0]):
        vec_dx[ic] = delta
        xx = vec_x.copy() - vec_dx
        vec_r1 = fun(xx)

        vec_dx[ic] = -delta
        xx = vec_x.copy() - vec_dx
        vec_r2 = fun(xx)

        vec_dx[ic] = 0.0;

        vec = 0.5 * (vec_r2 - vec_r1) / delta

        ir = mtx_a.indices[mtx_a.indptr[ic]:mtx_a.indptr[ic+1]]
        mtx_d.data[mtx_a.indptr[ic]:mtx_a.indptr[ic+1]] = vec[ir]

    vec_r = fun(vec_x) # Restore.

    timer = Timer(start=True)
    output(mtx_a, '.. analytical')
    output(mtx_d, '.. difference')
    import sfepy.base.plotutils as plu
    plu.plot_matrix_diff(mtx_d, mtx_a, delta, ['difference', 'analytical'],
                         conf.check)

    return timer.stop()
def partition_mesh(mesh, n_parts, use_metis=True, verbose=False):
    """
    Partition the mesh cells into `n_parts` subdomains, using metis, if
    available.
    """
    output('partitioning mesh into %d subdomains...' % n_parts,
           verbose=verbose)
    timer = Timer(start=True)

    if use_metis:
        try:
            from pymetis import part_graph

        except ImportError:
            output('pymetis is not available, using naive partitioning!')
            part_graph = None

    if use_metis and (part_graph is not None):
        cmesh = mesh.cmesh
        cmesh.setup_connectivity(cmesh.dim, cmesh.dim)
        graph = cmesh.get_conn(cmesh.dim, cmesh.dim)

        cuts, cell_tasks = part_graph(n_parts,
                                      xadj=graph.offsets.astype(int),
                                      adjncy=graph.indices.astype(int))
        cell_tasks = nm.array(cell_tasks, dtype=nm.int32)

    else:
        ii = nm.arange(n_parts)
        n_cell_parts = mesh.n_el // n_parts + ((mesh.n_el % n_parts) > ii)
        output('cell counts:', n_cell_parts, verbose=verbose)
        assert_(sum(n_cell_parts) == mesh.n_el)
        assert_(nm.all(n_cell_parts > 0))

        offs = nm.cumsum(nm.r_[0, n_cell_parts])
        cell_tasks = nm.digitize(nm.arange(offs[-1]), offs) - 1

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

    return cell_tasks
Exemple #18
0
    def init_solvers(self, problem):
        """
        Setup solvers. Use local options if these are defined,
        otherwise use the global ones.

        For linear problems, assemble the matrix and try to presolve the
        linear system.
        """

        if hasattr(self, 'solvers'):
            opts = self.solvers

        else:
            opts = problem.conf.options

        problem.set_conf_solvers(problem.conf.solvers, opts)
        problem.init_solvers()

        if self.is_linear:
            output('linear problem, trying to presolve...')
            timer = Timer(start=True)

            ev = problem.get_evaluator()

            state = problem.create_state()
            try:
                mtx_a = ev.eval_tangent_matrix(state(), is_full=True)
            except ValueError:
                output('matrix evaluation failed, giving up...')
                raise

            problem.set_linear(True)
            problem.try_presolve(mtx_a)

            output('...done in %.2f s' % timer.stop())

        else:
            problem.set_linear(False)
    def __call__(self,
                 x0,
                 conf=None,
                 obj_fun=None,
                 obj_fun_grad=None,
                 status=None,
                 obj_args=None):
        import inspect

        if conf is not None:
            self.set_method(conf)

        else:
            conf = self.conf

        obj_fun = get_default(obj_fun, self.obj_fun)
        obj_fun_grad = get_default(obj_fun_grad, self.obj_fun_grad)
        status = get_default(status, self.status)
        obj_args = get_default(obj_args, self.obj_args)

        timer = Timer(start=True)

        kwargs = {self._i_max_name[conf.method]: conf.i_max, 'args': obj_args}

        if conf.method in self._has_grad:
            kwargs['fprime'] = obj_fun_grad

        if 'disp' in inspect.getargspec(self.solver)[0]:
            kwargs['disp'] = conf.verbose

        kwargs.update(self.build_solver_kwargs(conf))

        out = self.solver(obj_fun, x0, **kwargs)

        if status is not None:
            status['time_stats'] = timer.stop()

        return out
Exemple #20
0
    def evaluate_at(self,
                    coors,
                    source_vals,
                    mode='val',
                    strategy='general',
                    close_limit=0.1,
                    get_cells_fun=None,
                    cache=None,
                    ret_cells=False,
                    ret_status=False,
                    ret_ref_coors=False,
                    verbose=False):
        """
        Evaluate source DOF values corresponding to the field in the given
        coordinates using the field interpolation.

        Parameters
        ----------
        coors : array, shape ``(n_coor, dim)``
            The coordinates the source values should be interpolated into.
        source_vals : array, shape ``(n_nod, n_components)``
            The source DOF values corresponding to the field.
        mode : {'val', 'grad'}, optional
            The evaluation mode: the field value (default) or the field value
            gradient.
        strategy : {'general', 'convex'}, optional
            The strategy for finding the elements that contain the
            coordinates. For convex meshes, the 'convex' strategy might be
            faster than the 'general' one.
        close_limit : float, optional
            The maximum limit distance of a point from the closest
            element allowed for extrapolation.
        get_cells_fun : callable, optional
            If given, a function with signature ``get_cells_fun(coors, cmesh,
            **kwargs)`` returning cells and offsets that potentially contain
            points with the coordinates `coors`. Applicable only when
            `strategy` is 'general'. When not given,
            :func:`get_potential_cells()
            <sfepy.discrete.common.global_interp.get_potential_cells>` is used.
        cache : Struct, optional
            To speed up a sequence of evaluations, the field mesh and other
            data can be cached. Optionally, the cache can also contain the
            reference element coordinates as `cache.ref_coors`, `cache.cells`
            and `cache.status`, if the evaluation occurs in the same
            coordinates repeatedly. In that case the mesh related data are
            ignored. See :func:`Field.get_evaluate_cache()
            <sfepy.discrete.fem.fields_base.FEField.get_evaluate_cache()>`.
        ret_ref_coors : bool, optional
            If True, return also the found reference element coordinates.
        ret_status : bool, optional
            If True, return also the enclosing cell status for each point.
        ret_cells : bool, optional
            If True, return also the cell indices the coordinates are in.
        verbose : bool
            If False, reduce verbosity.

        Returns
        -------
        vals : array
            The interpolated values with shape ``(n_coor, n_components)`` or
            gradients with shape ``(n_coor, n_components, dim)`` according to
            the `mode`. If `ret_status` is False, the values where the status
            is greater than one are set to ``numpy.nan``.
        ref_coors : array
            The found reference element coordinates, if `ret_ref_coors` is True.
        cells : array
            The cell indices, if `ret_ref_coors` or `ret_cells` or `ret_status`
            are True.
        status : array
            The status, if `ret_ref_coors` or `ret_status` are True, with the
            following meaning: 0 is success, 1 is extrapolation within
            `close_limit`, 2 is extrapolation outside `close_limit`, 3 is
            failure, 4 is failure due to non-convergence of the Newton
            iteration in tensor product cells. If close_limit is 0, then for
            the 'general' strategy the status 5 indicates points outside of the
            field domain that had no potential cells.
        """
        from sfepy.discrete.common.global_interp import get_ref_coors
        from sfepy.discrete.common.extmods.crefcoors import evaluate_in_rc
        from sfepy.base.base import complex_types

        output('evaluating in %d points...' % coors.shape[0], verbose=verbose)

        ref_coors, cells, status = get_ref_coors(self,
                                                 coors,
                                                 strategy=strategy,
                                                 close_limit=close_limit,
                                                 get_cells_fun=get_cells_fun,
                                                 cache=cache,
                                                 verbose=verbose)

        timer = Timer(start=True)

        # Interpolate to the reference coordinates.
        source_dtype = nm.float64 if source_vals.dtype in complex_types\
            else source_vals.dtype
        if mode == 'val':
            vals = nm.empty((coors.shape[0], source_vals.shape[1], 1),
                            dtype=source_dtype)
            cmode = 0

        elif mode == 'grad':
            vals = nm.empty(
                (coors.shape[0], source_vals.shape[1], coors.shape[1]),
                dtype=source_dtype)
            cmode = 1

        ctx = self.create_basis_context()

        if source_vals.dtype in complex_types:
            valsi = vals.copy()
            evaluate_in_rc(vals, ref_coors, cells, status,
                           nm.ascontiguousarray(source_vals.real),
                           self.get_econn('volume', self.region), cmode, ctx)
            evaluate_in_rc(valsi, ref_coors, cells, status,
                           nm.ascontiguousarray(source_vals.imag),
                           self.get_econn('volume', self.region), cmode, ctx)
            vals = vals + valsi * 1j
        else:
            evaluate_in_rc(vals, ref_coors, cells, status, source_vals,
                           self.get_econn('volume', self.region), cmode, ctx)

        output('interpolation: %f s' % timer.stop(), verbose=verbose)

        output('...done', verbose=verbose)

        if mode == 'val':
            vals.shape = (coors.shape[0], source_vals.shape[1])

        if not ret_status:
            ii = nm.where(status > 1)[0]
            vals[ii] = nm.nan

        if ret_ref_coors:
            return vals, ref_coors, cells, status

        elif ret_status:
            return vals, cells, status

        elif ret_cells:
            return vals, cells

        else:
            return vals
Exemple #21
0
def recover_micro_hook_eps(micro_filename, region,
                           eval_var, nodal_values, const_values, eps0,
                           recovery_file_tag='',
                           define_args=None, verbose=False):
    # Create a micro-problem instance.
    required, other = get_standard_keywords()
    required.remove('equations')
    conf = ProblemConf.from_file(micro_filename, required, other,
                                 verbose=False, define_args=define_args)

    coefs_filename = conf.options.get('coefs_filename', 'coefs')
    output_dir = conf.options.get('output_dir', '.')
    coefs_filename = op.join(output_dir, coefs_filename) + '.h5'

    # Coefficients and correctors
    coefs = Coefficients.from_file_hdf5(coefs_filename)
    corrs = get_correctors_from_file_hdf5(dump_names=coefs.save_names)

    recovery_hook = conf.options.get('recovery_hook', None)

    if recovery_hook is not None:
        recovery_hook = conf.get_function(recovery_hook)
        pb = Problem.from_conf(conf, init_equations=False, init_solvers=False)

        # Get tiling of a given region
        rcoors = region.domain.mesh.coors[region.get_entities(0), :]
        rcmin = nm.min(rcoors, axis=0)
        rcmax = nm.max(rcoors, axis=0)
        nn = nm.round((rcmax - rcmin) / eps0)
        if nm.prod(nn) == 0:
            output('inconsistency in recovery region and microstructure size!')
            return

        cs = []
        for ii, n in enumerate(nn):
            cs.append(nm.arange(n) * eps0 + rcmin[ii])

        x0 = nm.empty((int(nm.prod(nn)), nn.shape[0]), dtype=nm.float64)
        for ii, icoor in enumerate(nm.meshgrid(*cs, indexing='ij')):
            x0[:, ii] = icoor.flatten()

        mesh = pb.domain.mesh

        coors, conn, outs, ndoffset = [], [], [], 0
        # Recover region
        mic_coors = (mesh.coors - mesh.get_bounding_box()[0, :]) * eps0
        evfield = eval_var.field

        output('recovering microsctructures...')
        timer = Timer(start=True)
        output_fun = output.output_function
        output_level = output.level

        for ii, c0 in enumerate(x0):
            local_macro = {'eps0': eps0}
            local_coors = mic_coors + c0
            # Inside recovery region?
            v = nm.ones((evfield.region.entities[0].shape[0], 1))
            v[evfield.vertex_remap[region.entities[0]]] = 0
            no = nm.sum(v)
            aux = evfield.evaluate_at(local_coors, v)
            if no > 0 and (nm.sum(aux) / no) > 1e-3:
                continue

            output.level = output_level
            output('micro: %d' % ii)

            for k, v in six.iteritems(nodal_values):
                local_macro[k] = evfield.evaluate_at(local_coors, v)
            for k, v in six.iteritems(const_values):
                local_macro[k] = v

            output.set_output(quiet=not(verbose))
            outs.append(recovery_hook(pb, corrs, local_macro))
            output.output_function = output_fun
            coors.append(local_coors)
            conn.append(mesh.get_conn(mesh.descs[0]) + ndoffset)
            ndoffset += mesh.n_nod

    output('...done in %.2f s' % timer.stop())

    # Collect output variables
    outvars = {}
    for k, v in six.iteritems(outs[0]):
        if v.var_name in outvars:
            outvars[v.var_name].append(k)
        else:
            outvars[v.var_name] = [k]

    # Split output by variables/regions
    pvs = pb.create_variables(outvars.keys())
    outregs = {k: pvs[k].field.region.get_entities(-1) for k in outvars.keys()}
    nrve = len(coors)
    coors = nm.vstack(coors)
    ngroups = nm.tile(mesh.cmesh.vertex_groups.squeeze(), (nrve,))
    conn = nm.vstack(conn)
    cgroups = nm.tile(mesh.cmesh.cell_groups.squeeze(), (nrve,))

    # Get region mesh and data
    for k, cidxs in six.iteritems(outregs):
        gcidxs = nm.hstack([cidxs + mesh.n_el * ii for ii in range(nrve)])
        rconn = conn[gcidxs]
        remap = -nm.ones((coors.shape[0],), dtype=nm.int32)
        remap[rconn] = 1
        vidxs = nm.where(remap > 0)[0]
        remap[vidxs] = nm.arange(len(vidxs))
        rconn = remap[rconn]
        rcoors = coors[vidxs, :]

        out = {}
        for ifield in outvars[k]:
            data = [outs[ii][ifield].data for ii in range(nrve)]
            out[ifield] = Struct(name='output_data',
                                 mode=outs[0][ifield].mode,
                                 dofs=None,
                                 var_name=k,
                                 data=nm.vstack(data))

        micro_name = pb.get_output_name(extra='recovered%s_%s'
                                        % (recovery_file_tag, k))
        filename = op.join(output_dir, op.basename(micro_name))
        mesh_out = Mesh.from_data('recovery_%s' % k, rcoors, ngroups[vidxs],
                                  [rconn], [cgroups[gcidxs]], [mesh.descs[0]])
        mesh_out.write(filename, io='auto', out=out)
Exemple #22
0
def solve_problem(mesh_filename, options, comm):
    order_u = options.order_u
    order_p = options.order_p

    rank, size = comm.Get_rank(), comm.Get_size()

    output('rank', rank, 'of', size)

    stats = Struct()
    timer = Timer('solve_timer')

    timer.start()
    mesh = Mesh.from_file(mesh_filename)
    stats.t_read_mesh = timer.stop()

    timer.start()
    if rank == 0:
        cell_tasks = pl.partition_mesh(mesh, size, use_metis=options.metis,
                                       verbose=True)

    else:
        cell_tasks = None

    stats.t_partition_mesh = timer.stop()

    output('creating global domain and fields...')
    timer.start()

    domain = FEDomain('domain', mesh)
    omega = domain.create_region('Omega', 'all')
    field1 = Field.from_args('fu', nm.float64, mesh.dim, omega,
                             approx_order=order_u)
    field2 = Field.from_args('fp', nm.float64, 1, omega,
                             approx_order=order_p)
    fields = [field1, field2]

    stats.t_create_global_fields = timer.stop()
    output('...done in', timer.dt)

    output('distributing fields...')
    timer.start()

    distribute = pl.distribute_fields_dofs
    lfds, gfds = distribute(fields, cell_tasks,
                            is_overlap=True,
                            use_expand_dofs=True,
                            save_inter_regions=options.save_inter_regions,
                            output_dir=options.output_dir,
                            comm=comm, verbose=True)

    stats.t_distribute_fields_dofs = timer.stop()
    output('...done in', timer.dt)

    output('creating local problem...')
    timer.start()

    cells = lfds[0].cells

    omega_gi = Region.from_cells(cells, domain)
    omega_gi.finalize()
    omega_gi.update_shape()

    pb = create_local_problem(omega_gi, [order_u, order_p])

    variables = pb.get_variables()

    state = State(variables)
    state.fill(0.0)
    state.apply_ebc()

    stats.t_create_local_problem = timer.stop()
    output('...done in', timer.dt)

    output('allocating global system...')
    timer.start()

    sizes, drange, pdofs = pl.setup_composite_dofs(lfds, fields, variables,
                                                   verbose=True)
    pmtx, psol, prhs = pl.create_petsc_system(pb.mtx_a, sizes, pdofs, drange,
                                              is_overlap=True, comm=comm,
                                              verbose=True)

    stats.t_allocate_global_system = timer.stop()
    output('...done in', timer.dt)

    output('creating solver...')
    timer.start()

    conf = Struct(method='bcgsl', precond='jacobi', sub_precond='none',
                  i_max=10000, eps_a=1e-50, eps_r=1e-6, eps_d=1e4,
                  verbose=True)
    status = {}
    ls = PETScKrylovSolver(conf, comm=comm, mtx=pmtx, status=status)

    field_ranges = {}
    for ii, variable in enumerate(variables.iter_state(ordered=True)):
        field_ranges[variable.name] = lfds[ii].petsc_dofs_range

    ls.set_field_split(field_ranges, comm=comm)

    ev = PETScParallelEvaluator(pb, pdofs, drange, True,
                                psol, comm, verbose=True)

    nls_status = {}
    conf = Struct(method='newtonls',
                  i_max=5, eps_a=0, eps_r=1e-5, eps_s=0.0,
                  verbose=True)
    nls = PETScNonlinearSolver(conf, pmtx=pmtx, prhs=prhs, comm=comm,
                               fun=ev.eval_residual,
                               fun_grad=ev.eval_tangent_matrix,
                               lin_solver=ls, status=nls_status)

    stats.t_create_solver = timer.stop()
    output('...done in', timer.dt)

    output('solving...')
    timer.start()

    state = pb.create_state()
    state.apply_ebc()

    ev.psol_i[...] = state()
    ev.gather(psol, ev.psol_i)

    psol = nls(psol)

    ev.scatter(ev.psol_i, psol)
    sol0_i = ev.psol_i[...]

    stats.t_solve = timer.stop()
    output('...done in', timer.dt)

    output('saving solution...')
    timer.start()

    state.set_full(sol0_i)
    out = state.create_output_dict()

    filename = os.path.join(options.output_dir, 'sol_%02d.h5' % comm.rank)
    pb.domain.mesh.write(filename, io='auto', out=out)

    gather_to_zero = pl.create_gather_to_zero(psol)

    psol_full = gather_to_zero(psol)

    if comm.rank == 0:
        sol = psol_full[...].copy()

        u = FieldVariable('u', 'parameter', field1,
                          primary_var_name='(set-to-None)')
        remap = gfds[0].id_map
        ug = sol[remap]

        p = FieldVariable('p', 'parameter', field2,
                          primary_var_name='(set-to-None)')
        remap = gfds[1].id_map
        pg = sol[remap]

        if (((order_u == 1) and (order_p == 1))
            or (options.linearization == 'strip')):
            out = u.create_output(ug)
            out.update(p.create_output(pg))
            filename = os.path.join(options.output_dir, 'sol.h5')
            mesh.write(filename, io='auto', out=out)

        else:
            out = u.create_output(ug, linearization=Struct(kind='adaptive',
                                                           min_level=0,
                                                           max_level=order_u,
                                                           eps=1e-3))

            filename = os.path.join(options.output_dir, 'sol_u.h5')
            out['u'].mesh.write(filename, io='auto', out=out)

            out = p.create_output(pg, linearization=Struct(kind='adaptive',
                                                           min_level=0,
                                                           max_level=order_p,
                                                           eps=1e-3))

            filename = os.path.join(options.output_dir, 'sol_p.h5')
            out['p'].mesh.write(filename, io='auto', out=out)

    stats.t_save_solution = timer.stop()
    output('...done in', timer.dt)

    stats.t_total = timer.total

    stats.n_dof = sizes[1]
    stats.n_dof_local = sizes[0]
    stats.n_cell = omega.shape.n_cell
    stats.n_cell_local = omega_gi.shape.n_cell

    return stats
Exemple #23
0
    def __call__(self, vec_x0, conf=None, fun=None, fun_grad=None,
                 lin_solver=None, iter_hook=None, status=None):
        """
        Nonlinear system solver call.

        Solves a nonlinear system :math:`f(x) = 0` using the Newton method with
        backtracking line-search, starting with an initial guess :math:`x^0`.

        Parameters
        ----------
        vec_x0 : array
            The initial guess vector :math:`x_0`.
        conf : Struct instance, optional
            The solver configuration parameters,
        fun : function, optional
            The function :math:`f(x)` whose zero is sought - the residual.
        fun_grad : function, optional
            The gradient of :math:`f(x)` - the tangent matrix.
        lin_solver : LinearSolver instance, optional
            The linear solver for each nonlinear iteration.
        iter_hook : function, optional
            User-supplied function to call before each iteration.
        status : dict-like, optional
            The user-supplied object to hold convergence statistics.

        Notes
        -----
        * The optional parameters except `iter_hook` and `status` need
          to be given either here or upon `Newton` construction.
        * Setting `conf.is_linear == True` means a pre-assembled and possibly
          pre-solved matrix. This is mostly useful for linear time-dependent
          problems.
        """
        conf = get_default(conf, self.conf)
        fun = get_default(fun, self.fun)
        fun_grad = get_default(fun_grad, self.fun_grad)
        lin_solver = get_default(lin_solver, self.lin_solver)
        iter_hook = get_default(iter_hook, self.iter_hook)
        status = get_default(status, self.status)

        ls_eps_a, ls_eps_r = lin_solver.get_tolerance()
        eps_a = get_default(ls_eps_a, 1.0)
        eps_r = get_default(ls_eps_r, 1.0)
        lin_red = conf.eps_a * conf.lin_red

        timer = Timer()
        time_stats_keys = ['residual', 'matrix', 'solve']
        time_stats = {key : 0.0 for key in time_stats_keys}

        vec_x = vec_x0.copy()
        vec_x_last = vec_x0.copy()
        vec_dx = None

        if self.log is not None:
            self.log.plot_vlines(color='r', linewidth=1.0)

        err = err0 = -1.0
        err_last = -1.0
        it = 0
        ls_status = {}
        ls_n_iter = 0
        while 1:
            if iter_hook is not None:
                iter_hook(self, vec_x, it, err, err0)

            ls = 1.0
            vec_dx0 = vec_dx;
            while 1:
                timer.start()

                try:
                    vec_r = fun(vec_x)

                except ValueError:
                    if (it == 0) or (ls < conf.ls_min):
                        output('giving up!')
                        raise

                    else:
                        ok = False

                else:
                    ok = True

                time_stats['residual'] = timer.stop()
                if ok:
                    try:
                        err = nla.norm(vec_r)
                    except:
                        output('infs or nans in the residual:', vec_r)
                        output(nm.isfinite(vec_r).all())
                        debug()

                    if self.log is not None:
                        self.log(err, it)

                    if it == 0:
                        err0 = err;
                        break
                    if err < (err_last * conf.ls_on): break
                    red = conf.ls_red;
                    output('linesearch: iter %d, (%.5e < %.5e) (new ls: %e)'
                           % (it, err, err_last * conf.ls_on, red * ls))
                else: # Failure.
                    if conf.give_up_warp:
                        output('giving up!')
                        break

                    red = conf.ls_red_warp;
                    output('residual computation failed for iter %d'
                           ' (new ls: %e)!' % (it, red * ls))

                if ls < conf.ls_min:
                    output('linesearch failed, continuing anyway')
                    break

                ls *= red;

                vec_dx = ls * vec_dx0;
                vec_x = vec_x_last.copy() - vec_dx
            # End residual loop.

            if self.log is not None:
                self.log.plot_vlines([1], color='g', linewidth=0.5)

            err_last = err;
            vec_x_last = vec_x.copy()

            condition = conv_test(conf, it, err, err0)
            if condition >= 0:
                break

            if (not ok) and conf.give_up_warp:
                condition = 2
                break

            timer.start()
            if not conf.is_linear:
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad('linear')

            time_stats['matrix'] = timer.stop()

            if conf.check:
                timer.start()
                wt = check_tangent_matrix(conf, vec_x, fun, fun_grad)
                time_stats['check'] = timer.stop() - wt

            if conf.lin_precision is not None:
                if ls_eps_a is not None:
                    eps_a = max(err * conf.lin_precision, ls_eps_a)

                elif ls_eps_r is not None:
                    eps_r = max(conf.lin_precision, ls_eps_r)

                lin_red = max(eps_a, err * eps_r)

            if conf.verbose:
                output('solving linear system...')

            timer.start()
            vec_dx = lin_solver(vec_r, x0=vec_x,
                                eps_a=eps_a, eps_r=eps_r, mtx=mtx_a,
                                status=ls_status)
            ls_n_iter += ls_status['n_iter']
            time_stats['solve'] = timer.stop()

            if conf.verbose:
                output('...done')

            for key in time_stats_keys:
                output('%10s: %7.2f [s]' % (key, time_stats[key]))

            vec_e = mtx_a * vec_dx - vec_r
            lerr = nla.norm(vec_e)
            if lerr > lin_red:
                output('warning: linear system solution precision is lower')
                output('then the value set in solver options! (err = %e < %e)'
                       % (lerr, lin_red))

            vec_x -= vec_dx
            it += 1

        if status is not None:
            status['time_stats'] = time_stats
            status['err0'] = err0
            status['err'] = err
            status['n_iter'] = it
            status['ls_n_iter'] = ls_n_iter if ls_n_iter >= 0 else -1
            status['condition'] = condition

        if conf.log.plot is not None:
            if self.log is not None:
                self.log(save_figure=conf.log.plot)

        return vec_x
Exemple #24
0
    def __call__(self, vec_x0, conf=None, fun=None, fun_grad=None,
                 lin_solver=None, iter_hook=None, status=None,
                 pmtx=None, prhs=None, comm=None):
        conf = self.conf
        fun = get_default(fun, self.fun)
        fun_grad = get_default(fun_grad, self.fun_grad)
        lin_solver = get_default(lin_solver, self.lin_solver)
        iter_hook = get_default(iter_hook, self.iter_hook)
        status = get_default(status, self.status)
        pmtx = get_default(pmtx, self.pmtx)
        prhs = get_default(prhs, self.prhs)
        comm = get_default(comm, self.comm)

        timer = Timer(start=True)

        if isinstance(vec_x0, self.petsc.Vec):
            psol = vec_x0

        else:
            psol = pmtx.getVecLeft()
            psol[...] = vec_x0

        snes = self.petsc.SNES()
        snes.create(comm)
        snes.setType(conf.method)

        ksp = lin_solver.create_ksp()
        snes.setKSP(ksp)
        ls_conf = lin_solver.conf
        ksp.setTolerances(atol=ls_conf.eps_a, rtol=ls_conf.eps_r,
                          divtol=ls_conf.eps_d, max_it=ls_conf.i_max)

        snes.setFunction(fun, prhs)
        snes.setJacobian(fun_grad, pmtx)

        snes.setTolerances(atol=conf.eps_a, rtol=conf.eps_r,
                           stol=conf.eps_s, max_it=conf.i_max)
        snes.setMaxFunctionEvaluations(conf.if_max)
        snes.setFromOptions()

        fun(snes, psol, prhs)
        err0 = prhs.norm()

        snes.solve(prhs.duplicate(), psol)

        if status is not None:
            status['time_stats'] = timer.stop()

        if snes.reason in self.converged_reasons:
            reason = 'snes: %s' % self.converged_reasons[snes.reason]

        else:
            reason = 'ksp: %s' % self.ksp_converged_reasons[snes.reason]

        output('%s(%s): %d iterations in the last step'
               % (ksp.getType(), ksp.getPC().getType(),
                  ksp.getIterationNumber()),
               verbose=conf.verbose)

        output('%s convergence: %s (%s, %d iterations, %d function evaluations)'
               % (snes.getType(), snes.reason, reason,
                  snes.getIterationNumber(), snes.getFunctionEvaluations()),
               verbose=conf.verbose)

        converged = snes.reason >= 0

        if not converged:
            # PETSc does not update the solution if KSP have not converged.
            dpsol = snes.getSolutionUpdate()
            psol -= dpsol

            fun(snes, psol, prhs)
            err = prhs.norm()

        else:
            try:
                err = snes.getFunctionNorm()

            except AttributeError:
                fun(snes, psol, prhs)
                err = prhs.norm()

        if status is not None:
            status['err0'] = err0
            status['err'] = err
            status['n_iter'] = snes.getIterationNumber()
            status['ls_n_iter'] = snes.getLinearSolveIterations()
            status['condition'] = 0 if converged else -1

        if isinstance(vec_x0, self.petsc.Vec):
            sol = psol

        else:
            sol = psol[...].copy()

        return sol
Exemple #25
0
    def __call__(self,
                 vec_x0,
                 conf=None,
                 fun=None,
                 fun_grad=None,
                 lin_solver=None,
                 status=None,
                 problem=None):
        """
        Oseen solver is problem-specific - it requires a Problem instance.
        """
        conf = get_default(conf, self.conf)
        fun = get_default(fun, self.fun)
        fun_grad = get_default(fun_grad, self.fun_grad)
        lin_solver = get_default(lin_solver, self.lin_solver)
        status = get_default(status, self.status)
        problem = get_default(problem, conf.problem,
                              '`problem` parameter needs to be set!')

        timer = Timer()
        time_stats = {}

        stabil = problem.get_materials()[conf.stabil_mat]
        ns, ii = stabil.function.function.get_maps()

        variables = problem.get_variables()
        update_var = variables.set_from_state
        make_full_vec = variables.make_full_vec

        output('problem size:')
        output('    velocity: %s' % ii['us'])
        output('    pressure: %s' % ii['ps'])

        vec_x = vec_x0.copy()
        vec_x_prev = vec_x0.copy()
        vec_dx = None

        if self.log is not None:
            self.log.plot_vlines(color='r', linewidth=1.0)

        err0 = -1.0
        it = 0
        while 1:
            vec_x_prev_f = make_full_vec(vec_x_prev)
            update_var(ns['b'], vec_x_prev_f, ns['u'])

            vec_b = vec_x_prev_f[ii['u']]
            b_norm = nla.norm(vec_b, nm.inf)
            output('|b|_max: %.12e' % b_norm)

            vec_x_f = make_full_vec(vec_x)
            vec_u = vec_x_f[ii['u']]
            u_norm = nla.norm(vec_u, nm.inf)
            output('|u|_max: %.2e' % u_norm)

            stabil.function.set_extra_args(b_norm=b_norm)
            stabil.time_update(None,
                               problem.equations,
                               mode='force',
                               problem=problem)
            max_pars = stabil.reduce_on_datas(lambda a, b: max(a, b.max()))
            output('stabilization parameters:')
            output('                   gamma: %.12e' % max_pars[ns['gamma']])
            output('            max(delta): %.12e' % max_pars[ns['delta']])
            output('              max(tau): %.12e' % max_pars[ns['tau']])

            if (not are_close(b_norm, 1.0)) and conf.adimensionalize:
                adimensionalize = True
            else:
                adimensionalize = False

            timer.start()
            try:
                vec_r = fun(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['residual'] = timer.stop()
            if ok:
                err = nla.norm(vec_r)
                if it == 0:
                    err0 = err
                else:
                    err += nla.norm(vec_dx)
            else:  # Failure.
                output('residual computation failed for iter %d!' % it)
                raise RuntimeError('giving up...')

            if self.log is not None:
                self.log(err, it, max_pars[ns['gamma']], max_pars[ns['delta']],
                         max_pars[ns['tau']])

            condition = conv_test(conf, it, err, err0)
            if condition >= 0:
                break

            if adimensionalize:
                output('adimensionalizing')
                ## mat.viscosity = viscosity / b_norm
                ## vec_r[indx_us] /= b_norm

            timer.start()
            try:
                mtx_a = fun_grad(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['matrix'] = timer.stop()
            if not ok:
                raise RuntimeError('giving up...')

            timer.start()
            vec_dx = lin_solver(vec_r, x0=vec_x, mtx=mtx_a)
            time_stats['solve'] = timer.stop()

            vec_e = mtx_a * vec_dx - vec_r
            lerr = nla.norm(vec_e)
            if lerr > (conf.eps_a * conf.lin_red):
                output('linear system not solved! (err = %e)' % lerr)

            if adimensionalize:
                output('restoring pressure...')
                ## vec_dx[indx_ps] *= b_norm

            dx_norm = nla.norm(vec_dx)
            output('||dx||: %.2e' % dx_norm)

            for kv in six.iteritems(time_stats):
                output('%10s: %7.2f [s]' % kv)

            vec_x_prev = vec_x.copy()
            vec_x -= vec_dx
            it += 1

        if conf.check_navier_stokes_residual:

            t1 = '+ dw_div_grad.%s.%s(%s.viscosity, %s, %s)' \
                 % (ns['i2'], ns['omega'], ns['fluid'], ns['v'], ns['u'])
            # t2 = '+ dw_lin_convect.%s(%s, %s, %s)' % (ns['omega'],
            #                                           ns['v'], b_name, ns['u'])
            t2 = '+ dw_convect.%s.%s(%s, %s)' % (ns['i2'], ns['omega'],
                                                 ns['v'], ns['u'])
            t3 = '- dw_stokes.%s.%s(%s, %s)' % (ns['i1'], ns['omega'], ns['v'],
                                                ns['p'])
            t4 = 'dw_stokes.%s.%s(%s, %s)' % (ns['i1'], ns['omega'], ns['u'],
                                              ns['q'])
            equations = {
                'balance': ' '.join((t1, t2, t3)),
                'incompressibility': t4,
            }
            problem.set_equations(equations)
            try:
                vec_rns0 = fun(vec_x0)
                vec_rns = fun(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            if not ok:
                output('Navier-Stokes residual computation failed!')
                err_ns = err_ns0 = None
            else:
                err_ns0 = nla.norm(vec_rns0)
                err_ns = nla.norm(vec_rns)
            output('Navier-Stokes residual0: %.8e' % err_ns0)
            output('Navier-Stokes residual : %.8e' % err_ns)
            output('b - u: %.8e' % nla.norm(vec_b - vec_u))
            output(condition)

        else:
            err_ns = None

        if status is not None:
            status['time_stats'] = time_stats
            status['err0'] = err0
            status['err'] = err
            status['err_ns'] = err_ns
            status['condition'] = condition

        if conf.log.plot is not None:
            if self.log is not None:
                self.log(save_figure=conf.log.plot)

        return vec_x
def get_ref_coors_convex(field,
                         coors,
                         close_limit=0.1,
                         cache=None,
                         verbose=False):
    """
    Get reference element coordinates and elements corresponding to given
    physical coordinates.

    Parameters
    ----------
    field : Field instance
        The field defining the approximation.
    coors : array
        The physical coordinates.
    close_limit : float, optional
        The maximum limit distance of a point from the closest
        element allowed for extrapolation.
    cache : Struct, optional
        To speed up a sequence of evaluations, the field mesh and other data
        can be cached. Optionally, the cache can also contain the reference
        element coordinates as `cache.ref_coors`, `cache.cells` and
        `cache.status`, if the evaluation occurs in the same coordinates
        repeatedly. In that case the mesh related data are ignored.
    verbose : bool
        If False, reduce verbosity.

    Returns
    -------
    ref_coors : array
        The reference coordinates.
    cells : array
        The cell indices corresponding to the reference coordinates.
    status : array
        The status: 0 is success, 1 is extrapolation within `close_limit`, 2 is
        extrapolation outside `close_limit`, 3 is failure, 4 is failure due to
        non-convergence of the Newton iteration in tensor product cells.

    Notes
    -----
    Outline of the algorithm for finding xi such that X(xi) = P:

    1. make inverse connectivity - for each vertex have cells it is in.
    2. find the closest vertex V.
    3. choose initial cell: i0 = first from cells incident to V.
    4. while not P in C_i, change C_i towards P, check if P in new C_i.
    """
    timer = Timer()

    ref_coors = get_default_attr(cache, 'ref_coors', None)
    if ref_coors is None:
        extrapolate = close_limit > 0.0

        ref_coors = nm.empty_like(coors)
        cells = nm.empty((coors.shape[0], ), dtype=nm.int32)
        status = nm.empty((coors.shape[0], ), dtype=nm.int32)

        cmesh = get_default_attr(cache, 'cmesh', None)
        if cmesh is None:
            timer.start()
            mesh = field.create_mesh(extra_nodes=False)
            cmesh = mesh.cmesh

            gels = create_geometry_elements()

            cmesh.set_local_entities(gels)
            cmesh.setup_entities()

            centroids = cmesh.get_centroids(cmesh.tdim)

            if field.gel.name != '3_8':
                normals0 = cmesh.get_facet_normals()
                normals1 = None

            else:
                normals0 = cmesh.get_facet_normals(0)
                normals1 = cmesh.get_facet_normals(1)

            output('cmesh setup: %f s' % timer.stop(), verbose=verbose)

        else:
            centroids = cache.centroids
            normals0 = cache.normals0
            normals1 = cache.normals1

        kdtree = get_default_attr(cache, 'kdtree', None)
        if kdtree is None:
            from scipy.spatial import cKDTree as KDTree

            timer.start()
            kdtree = KDTree(cmesh.coors)
            output('kdtree: %f s' % timer.stop(), verbose=verbose)

        timer.start()
        ics = kdtree.query(coors)[1]
        output('kdtree query: %f s' % timer.stop(), verbose=verbose)

        ics = nm.asarray(ics, dtype=nm.int32)

        coors = nm.ascontiguousarray(coors)
        ctx = field.create_basis_context()

        timer.start()
        crc.find_ref_coors_convex(ref_coors, cells, status, coors, cmesh,
                                  centroids, normals0, normals1, ics,
                                  extrapolate, 1e-15, close_limit, ctx)
        output('ref. coordinates: %f s' % timer.stop(), verbose=verbose)

    else:
        cells = cache.cells
        status = cache.status

    return ref_coors, cells, status
def get_ref_coors_general(field,
                          coors,
                          close_limit=0.1,
                          get_cells_fun=None,
                          cache=None,
                          verbose=False):
    """
    Get reference element coordinates and elements corresponding to given
    physical coordinates.

    Parameters
    ----------
    field : Field instance
        The field defining the approximation.
    coors : array
        The physical coordinates.
    close_limit : float, optional
        The maximum limit distance of a point from the closest
        element allowed for extrapolation.
    get_cells_fun : callable, optional
        If given, a function with signature ``get_cells_fun(coors, cmesh,
        **kwargs)`` returning cells and offsets that potentially contain points
        with the coordinates `coors`. When not given,
        :func:`get_potential_cells()` is used.
    cache : Struct, optional
        To speed up a sequence of evaluations, the field mesh and other data
        can be cached. Optionally, the cache can also contain the reference
        element coordinates as `cache.ref_coors`, `cache.cells` and
        `cache.status`, if the evaluation occurs in the same coordinates
        repeatedly. In that case the mesh related data are ignored.
    verbose : bool
        If False, reduce verbosity.

    Returns
    -------
    ref_coors : array
        The reference coordinates.
    cells : array
        The cell indices corresponding to the reference coordinates.
    status : array
        The status: 0 is success, 1 is extrapolation within `close_limit`, 2 is
        extrapolation outside `close_limit`, 3 is failure, 4 is failure due to
        non-convergence of the Newton iteration in tensor product cells. If
        close_limit is 0, then status 5 indicates points outside of the field
        domain that had no potential cells.
    """
    timer = Timer()

    ref_coors = get_default_attr(cache, 'ref_coors', None)
    if ref_coors is None:
        extrapolate = close_limit > 0.0

        get = get_potential_cells if get_cells_fun is None else get_cells_fun

        ref_coors = nm.empty_like(coors)
        cells = nm.empty((coors.shape[0], ), dtype=nm.int32)
        status = nm.empty((coors.shape[0], ), dtype=nm.int32)

        cmesh = get_default_attr(cache, 'cmesh', None)
        if cmesh is None:
            timer.start()
            mesh = field.create_mesh(extra_nodes=False)
            cmesh = mesh.cmesh

            if get_cells_fun is None:
                centroids = cmesh.get_centroids(cmesh.tdim)

            else:
                centroids = None

            output('cmesh setup: %f s' % timer.stop(), verbose=verbose)

        else:
            centroids = cache.centroids

        timer.start()
        potential_cells, offsets = get(coors,
                                       cmesh,
                                       centroids=centroids,
                                       extrapolate=extrapolate)
        output('potential cells: %f s' % timer.stop(), verbose=verbose)

        coors = nm.ascontiguousarray(coors)
        ctx = field.create_basis_context()

        eval_cmesh = get_default_attr(cache, 'eval_cmesh', None)
        if eval_cmesh is None:
            timer.start()
            mesh = field.create_eval_mesh()
            if mesh is None:
                eval_cmesh = cmesh

            else:
                eval_cmesh = mesh.cmesh

            output('eval_cmesh setup: %f s' % timer.stop(), verbose=verbose)

        timer.start()

        crc.find_ref_coors(ref_coors, cells, status, coors, eval_cmesh,
                           potential_cells, offsets, extrapolate, 1e-15,
                           close_limit, ctx)
        if extrapolate:
            assert_(nm.all(status < 5))

        output('ref. coordinates: %f s' % timer.stop(), verbose=verbose)

    else:
        cells = cache.cells
        status = cache.status

    return ref_coors, cells, status
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
Exemple #29
0
def recover_micro_hook(micro_filename, region, macro,
                       naming_scheme='step_iel',
                       recovery_file_tag='',
                       define_args=None, verbose=False):
    # Create a micro-problem instance.
    required, other = get_standard_keywords()
    required.remove('equations')
    conf = ProblemConf.from_file(micro_filename, required, other,
                                 verbose=False, define_args=define_args)

    coefs_filename = conf.options.get('coefs_filename', 'coefs')
    output_dir = conf.options.get('output_dir', '.')
    coefs_filename = op.join(output_dir, coefs_filename) + '.h5'

    # Coefficients and correctors
    coefs = Coefficients.from_file_hdf5(coefs_filename)
    corrs = get_correctors_from_file_hdf5(dump_names=coefs.save_names)

    recovery_hook = conf.options.get('recovery_hook', None)

    if recovery_hook is not None:
        recovery_hook = conf.get_function(recovery_hook)
        pb = Problem.from_conf(conf, init_equations=False, init_solvers=False)

        format = get_print_info(pb.domain.mesh.n_el, fill='0')[1]

        output('recovering microsctructures...')
        timer = Timer(start=True)
        output_fun = output.output_function
        output_level = output.level
        for ii, iel in enumerate(region.cells):
            output.level = output_level
            output('micro: %d (el=%d)' % (ii, iel))

            local_macro = {}
            for k, v in six.iteritems(macro):
                local_macro[k] = v[ii, 0]

            output.set_output(quiet=not(verbose))
            out = recovery_hook(pb, corrs, local_macro)
            output.output_function = output_fun

            if ii == 0:
                new_keys = []
                new_data = {}
                new_idxs = []
                for k in six.iterkeys(local_macro):
                    if k not in macro:
                        new_keys.append(k)
                        new_data[k] = []

            new_idxs.append(ii)
            for jj in new_keys:
                new_data[jj].append(local_macro[jj])

            # save data
            if out is not None:
                suffix = format % iel
                micro_name = pb.get_output_name(extra='recovered_'
                                                + recovery_file_tag + suffix)
                filename = op.join(output_dir, op.basename(micro_name))
                fpv = pb.conf.options.get('file_per_var', False)
                pb.save_state(filename, out=out,
                              file_per_var=fpv)

        output('...done in %.2f s' % timer.stop())

        for jj in new_keys:
            lout = new_data[jj]
            macro[jj] = nm.zeros((nm.max(new_idxs) + 1, 1) + lout[0].shape,
                                 dtype=lout[0].dtype)
            out = macro[jj]
            for kk, ii in enumerate(new_idxs):
                out[ii, 0] = lout[kk]
    def create_matrix_graph(self,
                            any_dof_conn=False,
                            rdcs=None,
                            cdcs=None,
                            shape=None,
                            active_only=True,
                            verbose=True):
        """
        Create tangent matrix graph, i.e. preallocate and initialize the
        sparse storage needed for the tangent matrix. Order of DOF
        connectivities is not important.

        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.
        shape : tuple, optional
            The required shape, if it is different from the shape
            determined by the equations variables. This may be needed if
            additional row and column DOF connectivities are passed in.
        active_only : bool
            If True, the matrix graph has reduced size and is created with the
            reduced (active DOFs only) numbering.
        verbose : bool
            If False, reduce verbosity.

        Returns
        -------
        matrix : csr_matrix
            The matrix graph in the form of a CSR matrix with
            preallocated structure and zero data.
        """
        if not self.variables.has_virtuals():
            output('no matrix (no test variables)!')
            return None

        shape = get_default(shape, self.variables.get_matrix_shape())

        output('matrix shape:', shape, verbose=verbose)
        if nm.prod(shape) == 0:
            output('no matrix (zero size)!')
            return None

        rdcs, cdcs = self.get_graph_conns(any_dof_conn=any_dof_conn,
                                          rdcs=rdcs,
                                          cdcs=cdcs,
                                          active_only=active_only)

        if not len(rdcs):
            output('no matrix (empty dof connectivities)!')
            return None

        output('assembling matrix graph...', verbose=verbose)
        timer = Timer(start=True)

        nnz, prow, icol = create_mesh_graph(shape[0], shape[1], len(rdcs),
                                            rdcs, cdcs)

        output('...done in %.2f s' % timer.stop(), verbose=verbose)
        output('matrix structural nonzeros: %d (%.2e%% fill)' \
               % (nnz, float(nnz) / nm.prod(shape)), verbose=verbose)

        data = nm.zeros((nnz, ), dtype=self.variables.dtype)
        matrix = sp.csr_matrix((data, icol, prow), shape)

        return matrix