예제 #1
0
파일: basic.py 프로젝트: deneick/pymor
    def apply_inverse(self, V, mu=None, least_squares=False):
        from pymor.operators.constructions import FixedParameterOperator
        assembled_op = self.assemble(mu)
        if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator):
            return assembled_op.apply_inverse(V, least_squares=least_squares)
        elif self.linear:
            options = self.solver_options.get('inverse') if self.solver_options else None
            return genericsolvers.apply_inverse(assembled_op, V, options=options, least_squares=least_squares)
        else:
            from pymor.algorithms.newton import newton
            from pymor.core.exceptions import NewtonError

            options = self.solver_options.get('inverse') if self.solver_options else None
            if options:
                if isinstance(options, str):
                    assert options == 'newton'
                    options = {}
                else:
                    assert options['type'] == 'newton'
                    options = options.copy()
                    options.pop('type')
            else:
                options = {}
            options['least_squares'] = least_squares

            R = V.empty(reserve=len(V))
            for i in range(len(V)):
                try:
                    R.append(newton(self, V[i], mu=mu, **options)[0])
                except NewtonError as e:
                    raise InversionError(e)
            return R
예제 #2
0
파일: basic.py 프로젝트: denfromufa/pymor
    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        from pymor.operators.constructions import FixedParameterOperator
        assembled_op = self.assemble(mu)
        if assembled_op != self and not isinstance(assembled_op, FixedParameterOperator):
            return assembled_op.apply_inverse(V, ind=ind, least_squares=least_squares)
        elif self.linear:
            options = (self.solver_options.get('inverse') if self.solver_options else
                       'least_squares' if least_squares else
                       None)

            if options and not least_squares:
                solver_type = options if isinstance(options, str) else options['type']
                if solver_type.startswith('least_squares'):
                    self.logger.warn('Least squares solver selected but "least_squares == False"')

            try:
                return genericsolvers.apply_inverse(assembled_op, V.copy(ind), options=options)
            except InversionError as e:
                if least_squares and options:
                    solver_type = options if isinstance(options, str) else options['type']
                    if not solver_type.startswith('least_squares'):
                        msg = str(e) \
                            + '\nNote: linear solver was selected for solving least squares problem ' \
                            + '(maybe not invertible?)'
                        raise InversionError(msg)
                raise e
        else:
            from pymor.algorithms.newton import newton
            from pymor.core.exceptions import NewtonError
            assert V.check_ind(ind)

            options = self.solver_options
            if options:
                if isinstance(options, str):
                    assert options == 'newton'
                    options = {}
                else:
                    assert options['type'] == 'newton'
                    options = options.copy()
                    options.pop('type')
            else:
                options = {}
            options['least_squares'] = least_squares

            ind = (list(range(len(V))) if ind is None else
                   [ind] if isinstance(ind, Number) else
                   ind)
            R = V.empty(reserve=len(ind))
            for i in ind:
                try:
                    R.append(newton(self, V.copy(i), **options)[0])
                except NewtonError as e:
                    raise InversionError(e)
            return R
예제 #3
0
    def apply_inverse(self,
                      V,
                      mu=None,
                      initial_guess=None,
                      least_squares=False):
        """Apply the inverse operator.

        Parameters
        ----------
        V
            |VectorArray| of vectors to which the inverse operator is applied.
        mu
            The |parameter values| for which to evaluate the inverse operator.
        initial_guess
            |VectorArray| with the same length as `V` containing initial guesses
            for the solution.  Some implementations of `apply_inverse` may
            ignore this parameter.  If `None` a solver-dependent default is used.
        least_squares
            If `True`, solve the least squares problem::

                u = argmin ||op(u) - v||_2.

            Since for an invertible operator the least squares solution agrees
            with the result of the application of the inverse operator,
            setting this option should, in general, have no effect on the result
            for those operators. However, note that when no appropriate
            |solver_options| are set for the operator, most implementations
            will choose a least squares solver by default which may be
            undesirable.

        Returns
        -------
        |VectorArray| of the inverse operator evaluations.

        Raises
        ------
        InversionError
            The operator could not be inverted.
        """
        assert V in self.range
        assert initial_guess is None or initial_guess in self.source and len(
            initial_guess) == len(V)
        from pymor.operators.constructions import FixedParameterOperator
        assembled_op = self.assemble(mu)
        if assembled_op != self and not isinstance(assembled_op,
                                                   FixedParameterOperator):
            return assembled_op.apply_inverse(V,
                                              initial_guess=initial_guess,
                                              least_squares=least_squares)
        elif self.linear:
            options = self.solver_options.get(
                'inverse') if self.solver_options else None
            return genericsolvers.apply_inverse(assembled_op,
                                                V,
                                                initial_guess=initial_guess,
                                                options=options,
                                                least_squares=least_squares)
        else:
            from pymor.algorithms.newton import newton
            from pymor.core.exceptions import NewtonError

            options = self.solver_options.get(
                'inverse') if self.solver_options else None
            if options:
                if isinstance(options, str):
                    assert options == 'newton'
                    options = {}
                else:
                    assert options['type'] == 'newton'
                    options = options.copy()
                    options.pop('type')
            else:
                options = {}
            options['least_squares'] = least_squares

            with self.logger.block(
                    'Solving nonlinear problem using newton algorithm ...'):
                R = V.empty(reserve=len(V))
                for i in range(len(V)):
                    try:
                        R.append(
                            newton(self,
                                   V[i],
                                   initial_guess=initial_guess[i]
                                   if initial_guess is not None else None,
                                   mu=mu,
                                   **options)[0])
                    except NewtonError as e:
                        raise InversionError(e)
            return R
예제 #4
0
def _newton(order):
    mop = MonomOperator(order)
    rhs = NumpyVectorArray([0.0])
    guess = NumpyVectorArray([1.0])
    return newton(mop, rhs, initial_guess=guess)
예제 #5
0
파일: stuff.py 프로젝트: simon-ca/pymor
def _newton(order, **kwargs):
    mop = MonomOperator(order)
    rhs = NumpyVectorArray([0.0])
    guess = NumpyVectorArray([1.0])
    return newton(mop, rhs, initial_guess=guess, **kwargs)
예제 #6
0
def _newton(mop, initial_value=1.0, **kwargs):
    rhs = NumpyVectorSpace.from_numpy([0.0])
    guess = NumpyVectorSpace.from_numpy([initial_value])
    return newton(mop, rhs, initial_guess=guess, **kwargs)
예제 #7
0
    def apply_inverse(self, V, mu=None, least_squares=False):
        """Apply the inverse operator.

        Parameters
        ----------
        V
            |VectorArray| of vectors to which the inverse operator is applied.
        mu
            The |Parameter| for which to evaluate the inverse operator.
        least_squares
            If `True`, solve the least squares problem::

                u = argmin ||op(u) - v||_2.

            Since for an invertible operator the least squares solution agrees
            with the result of the application of the inverse operator,
            setting this option should, in general, have no effect on the result
            for those operators. However, note that when no appropriate
            |solver_options| are set for the operator, most implementations
            will choose a least squares solver by default which may be
            undesirable.

        Returns
        -------
        |VectorArray| of the inverse operator evaluations.

        Raises
        ------
        InversionError
            The operator could not be inverted.
        """
        from pymor.operators.constructions import FixedParameterOperator
        assembled_op = self.assemble(mu)
        if assembled_op != self and not isinstance(assembled_op,
                                                   FixedParameterOperator):
            return assembled_op.apply_inverse(V, least_squares=least_squares)
        elif self.linear:
            options = self.solver_options.get(
                'inverse') if self.solver_options else None
            return genericsolvers.apply_inverse(assembled_op,
                                                V,
                                                options=options,
                                                least_squares=least_squares)
        else:
            from pymor.algorithms.newton import newton
            from pymor.core.exceptions import NewtonError

            options = self.solver_options.get(
                'inverse') if self.solver_options else None
            if options:
                if isinstance(options, str):
                    assert options == 'newton'
                    options = {}
                else:
                    assert options['type'] == 'newton'
                    options = options.copy()
                    options.pop('type')
            else:
                options = {}
            options['least_squares'] = least_squares

            R = V.empty(reserve=len(V))
            for i in range(len(V)):
                try:
                    R.append(newton(self, V[i], mu=mu, **options)[0])
                except NewtonError as e:
                    raise InversionError(e)
            return R
예제 #8
0
    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        from pymor.operators.constructions import FixedParameterOperator
        assembled_op = self.assemble(mu)
        if assembled_op != self and not isinstance(assembled_op,
                                                   FixedParameterOperator):
            return assembled_op.apply_inverse(V,
                                              ind=ind,
                                              least_squares=least_squares)
        elif self.linear:
            options = (self.solver_options.get('inverse')
                       if self.solver_options else
                       'least_squares' if least_squares else None)

            if options and not least_squares:
                solver_type = options if isinstance(options,
                                                    str) else options['type']
                if solver_type.startswith('least_squares'):
                    self.logger.warn(
                        'Least squares solver selected but "least_squares == False"'
                    )

            try:
                return genericsolvers.apply_inverse(assembled_op,
                                                    V.copy(ind),
                                                    options=options)
            except InversionError as e:
                if least_squares and options:
                    solver_type = options if isinstance(
                        options, str) else options['type']
                    if not solver_type.startswith('least_squares'):
                        msg = str(e) \
                            + '\nNote: linear solver was selected for solving least squares problem ' \
                            + '(maybe not invertible?)'
                        raise InversionError(msg)
                raise e
        else:
            from pymor.algorithms.newton import newton
            from pymor.core.exceptions import NewtonError
            assert V.check_ind(ind)

            options = self.solver_options
            if options:
                if isinstance(options, str):
                    assert options == 'newton'
                    options = {}
                else:
                    assert options['type'] == 'newton'
                    options = options.copy()
                    options.pop('type')
            else:
                options = {}
            options['least_squares'] = least_squares

            ind = (list(range(len(V))) if ind is None else
                   [ind] if isinstance(ind, Number) else ind)
            R = V.empty(reserve=len(ind))
            for i in ind:
                try:
                    R.append(newton(self, V.copy(i), **options)[0])
                except NewtonError as e:
                    raise InversionError(e)
            return R
예제 #9
0
def main(
        dim: int = Argument(..., help='Spatial dimension of the problem.'),
        n: int = Argument(
            ..., help='Number of mesh intervals per spatial dimension.'),
        order: int = Argument(..., help='Finite element order.'),
):
    """Reduces a FEniCS-based nonlinear diffusion problem using POD/DEIM."""

    from pymor.tools import mpi

    if mpi.parallel:
        from pymor.models.mpi import mpi_wrap_model
        local_models = mpi.call(mpi.function_call_manage, discretize, dim, n,
                                order)
        fom = mpi_wrap_model(local_models,
                             use_with=True,
                             pickle_local_spaces=False)
    else:
        fom = discretize(dim, n, order)

    parameter_space = fom.parameters.space((0, 1000.))

    # ### ROM generation (POD/DEIM)
    from pymor.algorithms.ei import ei_greedy
    from pymor.algorithms.newton import newton
    from pymor.algorithms.pod import pod
    from pymor.operators.ei import EmpiricalInterpolatedOperator
    from pymor.reductors.basic import StationaryRBReductor

    U = fom.solution_space.empty()
    residuals = fom.solution_space.empty()
    for mu in parameter_space.sample_uniformly(10):
        UU, data = newton(fom.operator,
                          fom.rhs.as_vector(),
                          mu=mu,
                          rtol=1e-6,
                          return_residuals=True)
        U.append(UU)
        residuals.append(data['residuals'])

    dofs, cb, _ = ei_greedy(residuals, rtol=1e-7)
    ei_op = EmpiricalInterpolatedOperator(fom.operator,
                                          collateral_basis=cb,
                                          interpolation_dofs=dofs,
                                          triangular=True)

    rb, svals = pod(U, rtol=1e-7)
    fom_ei = fom.with_(operator=ei_op)
    reductor = StationaryRBReductor(fom_ei, rb)
    rom = reductor.reduce()
    # the reductor currently removes all solver_options so we need to add them again
    rom = rom.with_(operator=rom.operator.with_(
        solver_options=fom.operator.solver_options))

    # ### ROM validation
    import time
    import numpy as np

    # ensure that FFC is not called during runtime measurements
    rom.solve(1)

    errs = []
    speedups = []
    for mu in parameter_space.sample_randomly(10):
        tic = time.perf_counter()
        U = fom.solve(mu)
        t_fom = time.perf_counter() - tic

        tic = time.perf_counter()
        u_red = rom.solve(mu)
        t_rom = time.perf_counter() - tic

        U_red = reductor.reconstruct(u_red)
        errs.append(((U - U_red).norm() / U.norm())[0])
        speedups.append(t_fom / t_rom)
    print(f'Maximum relative ROM error: {max(errs)}')
    print(f'Median of ROM speedup: {np.median(speedups)}')
예제 #10
0
def _newton(order, **kwargs):
    mop = MonomOperator(order)
    rhs = NumpyVectorSpace.from_data([0.0])
    guess = NumpyVectorSpace.from_data([1.0])
    return newton(mop, rhs, initial_guess=guess, **kwargs)
def fenics_nonlinear_demo(args):
    DIM = int(args['DIM'])
    N = int(args['N'])
    ORDER = int(args['ORDER'])

    from pymor.tools import mpi

    if mpi.parallel:
        from pymor.models.mpi import mpi_wrap_model
        local_models = mpi.call(mpi.function_call_manage, discretize, DIM, N,
                                ORDER)
        fom = mpi_wrap_model(local_models,
                             use_with=True,
                             pickle_local_spaces=False)
    else:
        fom = discretize(DIM, N, ORDER)

    # ### ROM generation (POD/DEIM)
    from pymor.algorithms.ei import ei_greedy
    from pymor.algorithms.newton import newton
    from pymor.algorithms.pod import pod
    from pymor.operators.ei import EmpiricalInterpolatedOperator
    from pymor.reductors.basic import StationaryRBReductor

    U = fom.solution_space.empty()
    residuals = fom.solution_space.empty()
    for mu in fom.parameter_space.sample_uniformly(10):
        UU, data = newton(fom.operator,
                          fom.rhs.as_vector(),
                          mu=mu,
                          rtol=1e-6,
                          return_residuals=True)
        U.append(UU)
        residuals.append(data['residuals'])

    dofs, cb, _ = ei_greedy(residuals, rtol=1e-7)
    ei_op = EmpiricalInterpolatedOperator(fom.operator,
                                          collateral_basis=cb,
                                          interpolation_dofs=dofs,
                                          triangular=True)

    rb, svals = pod(U, rtol=1e-7)
    fom_ei = fom.with_(operator=ei_op)
    reductor = StationaryRBReductor(fom_ei, rb)
    rom = reductor.reduce()
    # the reductor currently removes all solver_options so we need to add them again
    rom = rom.with_(operator=rom.operator.with_(
        solver_options=fom.operator.solver_options))

    # ### ROM validation
    import time
    import numpy as np

    # ensure that FFC is not called during runtime measurements
    rom.solve(1)

    errs = []
    speedups = []
    for mu in fom.parameter_space.sample_randomly(10):
        tic = time.time()
        U = fom.solve(mu)
        t_fom = time.time() - tic

        tic = time.time()
        u_red = rom.solve(mu)
        t_rom = time.time() - tic

        U_red = reductor.reconstruct(u_red)
        errs.append(((U - U_red).l2_norm() / U.l2_norm())[0])
        speedups.append(t_fom / t_rom)
    print(f'Maximum relative ROM error: {max(errs)}')
    print(f'Median of ROM speedup: {np.median(speedups)}')