예제 #1
0
    def __init__(self, conf, context=None, **kwargs):
        NonlinearSolver.__init__(self, conf, context=context, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        conf.problem = context

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'], ['%.8e', '%.8e',
                                                       '%.8e']])

        else:
            self.log = None
예제 #2
0
파일: test_log.py 프로젝트: xiaoyao79/sfepy
    def test_log_create(self):
        from sfepy.base.log import Log

        log = Log([['x^3']],
                  plot_kwargs=[{
                      'color': 'b',
                      'ls': '',
                      'marker': 'o'
                  }],
                  yscales=['linear'],
                  xlabels=['x'],
                  ylabels=['a cubic function'],
                  is_plot=False,
                  aggregate=0,
                  sleep=0.0,
                  log_filename=self.log_filename,
                  formats=[['{:.5e}']])

        for x in nm.linspace(0, 1, 11):
            log(x**3, x=[x])
            if nm.allclose(x, 0.5):
                log.plot_vlines([0], color='g', linewidth=2)

        log(finished=True)

        return True
예제 #3
0
def main():
    cwd = os.path.split(os.path.join(os.getcwd(), __file__))[0]

    log = Log((['sin(x) + i sin(x**2)', 'cos(x)'], ['exp(x)']),
              yscales=['linear', 'log'],
              xlabels=['angle', None],
              ylabels=[None, 'a function'],
              aggregate=1000,
              sleep=0.05,
              log_filename=os.path.join(cwd, 'live_plot.log'))
    log2 = Log([['x^3']],
               yscales=['linear'],
               xlabels=['x'],
               ylabels=['a cubic function'],
               aggregate=1000,
               sleep=0.05,
               log_filename=os.path.join(cwd, 'live_plot2.log'),
               formats=[['{:.5e}']])

    added = 0
    for x in nm.linspace(0, 4.0 * nm.pi, 200):
        output('x: ', x)

        if x < (2.0 * nm.pi):
            log(nm.sin(x) + 1j * nm.sin(x**2),
                nm.cos(x),
                nm.exp(x),
                x=[x, None])

        else:
            if added:
                log(nm.sin(x) + 1j * nm.sin(x**2),
                    nm.cos(x),
                    nm.exp(x),
                    x**2,
                    x=[x, None, x])
            else:
                log.plot_vlines(color='r', linewidth=2)
                log.add_group(['x^2'],
                              yscale='linear',
                              xlabel='new x',
                              ylabel='square',
                              formats=['%+g'])
            added += 1

        if (added == 20) or (added == 50):
            log.plot_vlines([2], color='g', linewidth=2)

        log2(x * x * x, x=[x])

    print(log)
    print(log2)
    pause()

    log(finished=True)
    log2(finished=True)
예제 #4
0
    def __init__(self, conf, **kwargs):
        OptimizationSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log(
                [[r'$||\Psi||$'], [r'$||\nabla \Psi||$'], [r'$\alpha$'],
                 ['iteration']],
                xlabels=['', '', 'all iterations', 'all iterations'],
                yscales=conf.yscales,
                is_plot=conf.log.plot is not None,
                log_filename=conf.log.text,
                formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None
예제 #5
0
    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None
예제 #6
0
파일: oseen.py 프로젝트: Nasrollah/sfepy
    def __init__(self, conf, problem, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        conf.problem = problem

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'],
                                    ['%.8e', '%.8e', '%.8e']])

        else:
            self.log = None
예제 #7
0
파일: oseen.py 프로젝트: LeiDai/sfepy
    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'], ['%.8e', '%.8e',
                                                       '%.8e']])

        else:
            self.log = None
예제 #8
0
파일: parametric.py 프로젝트: certik/sfepy
def vary_incident_wave_dir( problem ):
    default_printer.prefix = 'vary_incident_wave_dir:'

    log_conf = {
        'is_plot' : True,
        'yscales' : ['linear'],
        'xaxes' : ['incident wave angle [degrees]'],
        'yaxes' : ['phase velocity [m/s]'],
    }
    dim = problem.domain.mesh.dim
    log = Log.from_conf( log_conf,
                         ['phase velocity %d' % ii for ii in range( dim )] )
    
    alphas = nm.linspace( 0.0, 360.0, 37 )
    output( 'running for angles:', alphas )
    pause()
    for ii, alpha in enumerate( alphas ):
        output( 'iteration %d: alpha %2f' % (ii, alpha) )
        opts = problem.conf.options

        ra = nm.pi * alpha / 180.0
        iwd = nm.zeros( (dim,), dtype = nm.float64 )
        iwd[0:2] = [nm.cos( ra ), nm.sin( ra )]
        opts.incident_wave_dir = iwd

        out = []
        yield problem, out
        
        #You have: sqrt( 10^10Pa / 10^4kg * m^3 )
        #You want:
        #Definition: 1000 m / s
        convert_to_ms = 1000.0
        phase_velocity = out[0] * convert_to_ms # to m/s.
        log( x = [alpha], *phase_velocity )

        output( 'phase velocity [m/s]:', phase_velocity )
        if opts.homogeneous:
            mat = problem.materials['matrix']
            # dilatation wave: vp = \sqrt{ (\lambda + 2\mu) / \rho }
            vd = nm.sqrt( (mat.D[0,0]) / mat.density) * convert_to_ms
            # shear wave: vs = \sqrt{ \mu / \rho }
            vs = nm.sqrt( mat.D[-1,-1] / mat.density ) * convert_to_ms
            output( 'analytical dilatation: %f, shear: %f' % (vd, vs) )
#            pause()

        yield None

    print log
    pause()

    if opts.homogeneous:
        name = 'homogeneous'
    else:
        name = 'perforated'
    fig_name = os.path.join( problem.output_dir,
                             'phase_velocity_%s%s' % (name, opts.fig_suffix) )
    log( save_figure = fig_name, finished = True )
예제 #9
0
 def iter_step(self, x, first_step=False):
     if first_step:
         self.log = Log([['O'], ['E_f', 'E_m'], ['v_f', 'v_m']],
             ylabels=['Obj. fun.', "Young's modulus", "Poisson's ratio"],
             xlabels=['iter', 'iter', 'iter'],
             aggregate=0)
         self.istep = 0
         self.log(0.5, x[0], x[2], x[1], x[3],
             x=[0, 0, 0, 0])
     else:
         self.istep += 1
         self.log(self.eval_f[-1], x[0], x[2], x[1], x[3],
             x=(self.istep,)*4)
예제 #10
0
파일: nls.py 프로젝트: LeiDai/sfepy
    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None
예제 #11
0
    def __init__( self, conf, **kwargs ):
        OptimizationSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||\Psi||$'], [r'$||\nabla \Psi||$'],
                            [r'$\alpha$'], ['iteration']],
                           xlabels=['', '', 'all iterations', 'all iterations'],
                           yscales=conf.yscales,
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None
예제 #12
0
파일: nls.py 프로젝트: taldcroft/sfepy
    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log(
                [[r"$||r||$"], ["iteration"]],
                xlabels=["", "all iterations"],
                ylabels=[r"$||r||$", "iteration"],
                yscales=["log", "linear"],
                is_plot=conf.log.plot is not None,
                log_filename=conf.log.text,
                formats=[["%.8e"], ["%d"]],
            )

        else:
            self.log = None
예제 #13
0
def main():
    cwd = os.path.split(os.path.join(os.getcwd(), __file__))[0]

    log = Log(
        (["sin(x)", "cos(x)"], ["exp(x)"]),
        yscales=["linear", "log"],
        xlabels=["angle", None],
        ylabels=[None, "a function"],
        log_filename=os.path.join(cwd, "live_plot.log"),
    )
    log2 = Log(
        [["x^3"]],
        yscales=["linear"],
        xlabels=["x"],
        ylabels=["a cubic function"],
        log_filename=os.path.join(cwd, "live_plot2.log"),
    )

    added = 0
    for x in nm.linspace(0, 4.0 * nm.pi, 200):
        output("x: ", x)

        if x < (2.0 * nm.pi):
            log(nm.sin(x), nm.cos(x), nm.exp(x), x=[x, None])

        else:
            if added:
                log(nm.sin(x), nm.cos(x), nm.exp(x), x ** 2, x=[x, None, x])
            else:
                log.plot_vlines(color="r", linewidth=2)
                log.add_group(["x^2"], "linear", "new x", "square", formats=["%+g"])
            added += 1

        if (added == 20) or (added == 50):
            log.plot_vlines([2], color="g", linewidth=2)

        log2(x * x * x, x=[x])

    print log
    print log2
    pause()

    log(finished=True)
    log2(finished=True)
예제 #14
0
파일: live_plot.py 프로젝트: certik/sfepy
def main():

    log_conf = {
        'is_plot' : True,
        'aggregate' : 200,
        'yscales' : ['linear', 'log'],
        'xaxes' : ['angle', None],
        'yaxes' : [None, 'a function'],
    }

    log = Log.from_conf( log_conf, (['sin( x )', 'cos( x )'],['exp( x )']) )

    for x in nm.linspace( 0, 4.0 * nm.pi, 200 ):
        output( 'x: ', x )
        log( nm.sin( x ), nm.cos( x ), nm.exp( x ), x = [x, None] )

    print log
    pause()

    log( finished = True )
예제 #15
0
파일: nls.py 프로젝트: cheon7886/sfepy
    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None
예제 #16
0
파일: live_plot.py 프로젝트: rc/sfepy
def main():
    cwd = os.path.split(os.path.join(os.getcwd(), __file__))[0]

    log = Log((['sin(x) + i sin(x**2)', 'cos(x)'], ['exp(x)']),
              yscales=['linear', 'log'],
              xlabels=['angle', None], ylabels=[None, 'a function'],
              log_filename=os.path.join(cwd, 'live_plot.log'))
    log2 = Log([['x^3']],
               yscales=['linear'],
               xlabels=['x'], ylabels=['a cubic function'],
               aggregate=50, sleep=0.05,
               log_filename=os.path.join(cwd, 'live_plot2.log'),
               formats=[['{:.5e}']])

    added = 0
    for x in nm.linspace(0, 4.0 * nm.pi, 200):
        output('x: ', x)

        if x < (2.0 * nm.pi):
            log(nm.sin(x)+1j*nm.sin(x**2), nm.cos(x), nm.exp(x), x=[x, None])

        else:
            if added:
                log(nm.sin(x)+1j*nm.sin(x**2), nm.cos(x), nm.exp(x), x**2,
                    x=[x, None, x])
            else:
                log.plot_vlines(color='r', linewidth=2)
                log.add_group(['x^2'], yscale='linear', xlabel='new x',
                              ylabel='square', formats=['%+g'])
            added += 1

        if (added == 20) or (added == 50):
            log.plot_vlines([2], color='g', linewidth=2)

        log2(x*x*x, x=[x])

    print(log)
    print(log2)
    pause()

    log(finished=True)
    log2(finished=True)
예제 #17
0
파일: oseen.py 프로젝트: snilek/sfepy
class Oseen( NonlinearSolver ):
    name = 'nls.oseen'

    @staticmethod
    def process_conf(conf, kwargs):
        """
        Missing items are set to default values.

        Example configuration, all items::

            solver_1 = {
                'name' : 'oseen',
                'kind' : 'nls.oseen',

                'needs_problem_instance' : True,
                'stabil_mat' : 'stabil',

                'adimensionalize' : False,
                'check_navier_stokes_rezidual' : False,

                'i_max'      : 10,
                'eps_a'      : 1e-8,
                'eps_r'      : 1.0,
                'macheps'    : 1e-16,
                'lin_red'    : 1e-2, # Linear system error < (eps_a * lin_red).
                'is_plot'    : False,
                'log'        : {'text' : 'oseen_log.txt',
                                'plot' : 'oseen_log.png'},
            }
        """
        get = make_get_conf(conf, kwargs)
        common = NonlinearSolver.process_conf(conf)

        # Compulsory.
        needs_problem_instance = get('needs_problem_instance', True)
        if not needs_problem_instance:
            msg = 'set solver option "needs_problem_instance" to True!'
            raise ValueError(msg)

        stabil_mat = get('stabil_mat', None, 'missing "stabil_mat" in options!')

        # With defaults.
        adimensionalize = get('adimensionalize', False)
        if adimensionalize:
            raise NotImplementedError

        check = get('check_navier_stokes_rezidual', False)

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        return Struct(needs_problem_instance=needs_problem_instance,
                      stabil_mat=stabil_mat,
                      adimensionalize=adimensionalize,
                      check_navier_stokes_rezidual=check,
                      i_max=get('i_max', 1),
                      eps_a=get('eps_a', 1e-10),
                      eps_r=get('eps_r', 1.0),
                      macheps=get('macheps', nm.finfo(nm.float64).eps),
                      lin_red=get('lin_red', 1.0),
                      lin_precision=get('lin_precision', None),
                      is_plot=get('is_plot', False),
                      log=log,
                      is_any_log=is_any_log) + common

    def __init__( self, conf, **kwargs ):
        NonlinearSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'],
                                    ['%.8e', '%.8e', '%.8e']])

        else:
            self.log = None

    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.
        """
        import sfepy.base.plotutils as plu

        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, self.problem )

        if problem is None:
            msg = 'set solver option "needs_problem_instance" to True!'
            raise ValueError(msg)

        time_stats = {}

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

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

        print 'problem size:'
        print '    velocity: %s' % ii['us']
        print '    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 )
            print '|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 )
            print '|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() ) )
            print 'stabilization parameters:'
            print '                   gamma: %.12e' % max_pars[ns['gamma']]
            print '            max( delta ): %.12e' % max_pars[ns['delta']]
            print '              max( tau ): %.12e' % max_pars[ns['tau']]

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

            tt = time.clock()
            try:
                vec_r = fun( vec_x )
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['rezidual'] = time.clock() - tt
            if ok:
                err = nla.norm( vec_r )
                if it == 0:
                    err0 = err;
                else:
                    err += nla.norm( vec_dx )
            else: # Failure.
                output( 'rezidual 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

            tt = time.clock()
            try:
                mtx_a = fun_grad( vec_x )
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['matrix'] = time.clock() - tt
            if not ok:
                raise RuntimeError( 'giving up...' )

            tt = time.clock() 
            vec_dx = lin_solver(vec_r, x0=vec_x, mtx=mtx_a)
            time_stats['solve'] = time.clock() - tt

            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 time_stats.iteritems():
                output( '%10s: %7.2f [s]' % kv )

            vec_x_prev = vec_x.copy()
            vec_x -= vec_dx

            if conf.is_plot:
                plu.plt.ion()
                plu.plt.gcf().clear()
                plu.plt.subplot( 2, 2, 1 )
                plu.plt.plot( vec_x_prev )
                plu.plt.ylabel( r'$x_{i-1}$' )
                plu.plt.subplot( 2, 2, 2 )
                plu.plt.plot( vec_r )
                plu.plt.ylabel( r'$r$' )
                plu.plt.subplot( 2, 2, 4 )
                plu.plt.plot( vec_dx )
                plu.plt.ylabel( r'$\_delta x$' )
                plu.plt.subplot( 2, 2, 3 )
                plu.plt.plot( vec_x )
                plu.plt.ylabel( r'$x_i$' )
                plu.plt.draw()
                plu.plt.ioff()
                pause()

            it += 1

        if conf.check_navier_stokes_rezidual:

            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:
                print 'Navier-Stokes rezidual computation failed!'
                err_ns = err_ns0 = None
            else:
                err_ns0 = nla.norm( vec_rns0 )
                err_ns = nla.norm( vec_rns )
            print 'Navier-Stokes rezidual0: %.8e' % err_ns0
            print 'Navier-Stokes rezidual : %.8e' % err_ns
            print 'b - u: %.8e' % nla.norm( vec_b - vec_u )
            print condition
    ##         print vec_rns - vec_rns1
            plu.plt.ion()
            plu.plt.gcf().clear()
            plu.plt.plot( vec_rns )
    ##         plu.plt.gcf().clear()
    ##         plu.plt.plot( vec_rns1 )
            plu.plt.draw()
            plu.plt.ioff()
            pause()
        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
예제 #18
0
def solve_eigen_problem_n( conf, options ):

    pb = ProblemDefinition.from_conf( conf )
    dim = pb.domain.mesh.dim

    pb.time_update()

    dummy = pb.create_state_vector()

    output( 'assembling rhs...' )
    tt = time.clock()
    mtx_b = eval_term_op( dummy, conf.equations['rhs'], pb,
                       dw_mode = 'matrix', tangent_matrix = pb.mtx_a.copy() )
    output( '...done in %.2f s' % (time.clock() - tt) )

    #mtxA.save( 'tmp/a.txt', format='%d %d %.12f\n' )
    #mtxB.save( 'tmp/b.txt', format='%d %d %.12f\n' )

    try:
        n_eigs = conf.options.n_eigs
    except AttributeError:
        n_eigs = mtx_a.shape[0]

    if n_eigs is None:
        n_eigs = mtx_a.shape[0]

##     mtx_a.save( 'a.txt', format='%d %d %.12f\n' )
##     mtx_b.save( 'b.txt', format='%d %d %.12f\n' )

    if options.plot:
        log_conf = {
            'is_plot' : True,
            'aggregate' : 1,
            'yscales' : ['linear', 'log'],
        }
    else:
        log_conf = {
            'is_plot' : False,
        }
    log =  Log.from_conf( log_conf, ([r'$|F(x)|$'], [r'$|F(x)|$']) )

    eig_conf = pb.get_solver_conf( conf.options.eigen_solver )
    eig_solver = Solver.any_from_conf( eig_conf )
    vec_vhxc = nm.zeros( (pb.variables.di.ptr[-1],), dtype = nm.float64 )
    aux = wrap_function( iterate,
                         (pb, conf, eig_solver, n_eigs, mtx_b, log) )
    ncalls, times, nonlin_v = aux
    vec_vhxc = broyden3( nonlin_v, vec_vhxc, verbose = True )
    out = iterate( vec_vhxc, pb, conf, eig_solver, n_eigs, mtx_b )
    eigs, mtx_s_phi, vec_n, vec_vh, vec_vxc = out

    if options.plot:
        log( finished = True )
        pause()
        
    coor = pb.domain.get_mesh_coors()
    r = coor[:,0]**2 + coor[:,1]**2 + coor[:,2]**2
    vec_nr2 = vec_n * r

    n_eigs = eigs.shape[0]

    mtx_phi = nm.empty( (pb.variables.di.ptr[-1], mtx_s_phi.shape[1]),
                       dtype = nm.float64 )
    for ii in xrange( n_eigs ):
        mtx_phi[:,ii] = pb.variables.make_full_vec( mtx_s_phi[:,ii] )

    save = get_default_attr( conf.options, 'save_eig_vectors', None )
    out = {}
    for ii in xrange( n_eigs ):
        if save is not None:
            if (ii >= save[0]) and (ii < (n_eigs - save[1])): continue
        aux = pb.state_to_output( mtx_phi[:,ii] )
        key = aux.keys()[0]
        out[key+'%03d' % ii] = aux[key]

    update_state_to_output( out, pb, vec_n, 'n' )
    update_state_to_output( out, pb, vec_nr2, 'nr2' )
    update_state_to_output( out, pb, vec_vh, 'vh' )
    update_state_to_output( out, pb, vec_vxc, 'vxc' )

    ofn_trunk = options.output_filename_trunk
    pb.domain.mesh.write( ofn_trunk + '.vtk', io = 'auto', out = out )

    fd = open( ofn_trunk + '_eigs.txt', 'w' )
    eigs.tofile( fd, ' ' )
    fd.close()

    return Struct( pb = pb, eigs = eigs, mtx_phi = mtx_phi )
예제 #19
0
파일: nls.py 프로젝트: cheon7886/sfepy
class Newton(NonlinearSolver):
    r"""
    Solves a nonlinear system :math:`f(x) = 0` using the Newton method with
    backtracking line-search, starting with an initial guess :math:`x^0`.
    """
    name = 'nls.newton'

    __metaclass__ = SolverMeta

    _parameters = [
        ('i_max', 'int', 1, False,
         'The maximum number of iterations.'),
        ('eps_a', 'float', 1e-10, False,
         'The absolute tolerance for the residual, i.e. :math:`||f(x^i)||`.'),
        ('eps_r', 'float', 1.0, False,
         """The relative tolerance for the residual, i.e. :math:`||f(x^i)|| /
            ||f(x^0)||`."""),
        ('eps_mode', "'and' or 'or'", 'and', False,
         """The logical operator to use for combining the absolute and relative
            tolerances."""),
        ('macheps', 'float', nm.finfo(nm.float64).eps, False,
         'The float considered to be machine "zero".'),
        ('lin_red', 'float', 1.0, False,
         """The linear system solution error should be smaller than (`eps_a` *
            `lin_red`), otherwise a warning is printed."""),
        ('lin_precision', 'float or None', None, False,
         """If not None, the linear system solution tolerances are set in each
            nonlinear iteration relative to the current residual norm by the
            `lin_precision` factor. Ignored for direct linear solvers."""),
        ('ls_on', 'float', 0.99999, False,
         """Start the backtracking line-search by reducing the step, if
            :math:`||f(x^i)|| / ||f(x^{i-1})||` is larger than `ls_on`."""),
        ('ls_red', '0.0 < float < 1.0', 0.1, False,
         'The step reduction factor in case of correct residual assembling.'),
        ('ls_red_warp', '0.0 < float < 1.0', 0.001, False,
         """The step reduction factor in case of failed residual assembling
            (e.g. the "warp violation" error caused by a negative volume
            element resulting from too large deformations)."""),
        ('ls_min', '0.0 < float < 1.0', 1e-5, False,
         'The minimum step reduction factor.'),
        ('give_up_warp', 'bool', False, False,
         'If True, abort on the "warp violation" error.'),
        ('check', '0, 1 or 2', 0, False,
         """If >= 1, check the tangent matrix using finite differences.  If 2,
            plot the resulting sparsity patterns."""),
        ('delta', 'float', 1e-6, False,
         r"""If `check >= 1`, the finite difference matrix is taken as
            :math:`A_{ij} = \frac{f_i(x_j + \delta) - f_i(x_j - \delta)}{2
            \delta}`."""),
        ('log', 'dict or None', None, False,
         """If not None, log the convergence according to the configuration in
            the following form: ``{'text' : 'log.txt', 'plot' : 'log.pdf'}``.
            Each of the dict items can be None."""),
        ('is_linear', 'bool', False, False,
         'If True, the problem is considered to be linear.'),
    ]

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None

    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

        time_stats = {}

        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
        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:
                tt = time.clock()

                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['rezidual'] = time.clock() - tt
                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('rezidual 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

            tt = time.clock()
            if not conf.is_linear:
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad('linear')

            time_stats['matrix'] = time.clock() - tt

            if conf.check:
                tt = time.clock()
                wt = check_tangent_matrix(conf, vec_x, fun, fun_grad)
                time_stats['check'] = time.clock() - tt - 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...')

            tt = time.clock()
            vec_dx = lin_solver(vec_r, x0=vec_x,
                                eps_a=eps_a, eps_r=eps_r, mtx=mtx_a)
            time_stats['solve'] = time.clock() - tt

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

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

            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['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
예제 #20
0
파일: optimize.py 프로젝트: Gkdnz/sfepy
class FMinSteepestDescent(OptimizationSolver):
    """
    Steepest descent optimization solver.
    """
    name = 'opt.fmin_sd'

    __metaclass__ = SolverMeta

    _parameters = [
        ('i_max', 'int', 10, False,
         'The maximum number of iterations.'),
        ('eps_rd', 'float', 1e-5, False,
         'The relative delta of the objective function.'),
        ('eps_of', 'float', 1e-4, False,
         'The tolerance for the objective function.'),
        ('eps_ofg', 'float', 1e-8, False,
         'The tolerance for the objective function gradient.'),
        ('norm', 'numpy norm', nm.Inf, False,
         'The norm to be used.'),
        ('ls', 'bool', True, False,
         'If True, use a line-search.'),
        ('ls_method', "{'backtracking', 'full'}", 'backtracking', False,
         'The line-search method.'),
        ('ls_on', 'float', 0.99999, False,
         """Start the backtracking line-search by reducing the step, if
            :math:`||f(x^i)|| / ||f(x^{i-1})||` is larger than `ls_on`."""),
        ('ls0', '0.0 < float < 1.0', 1.0, False,
         'The initial step.'),
        ('ls_red', '0.0 < float < 1.0', 0.5, False,
         'The step reduction factor in case of correct residual assembling.'),
        ('ls_red_warp', '0.0 < float < 1.0', 0.1, False,
         """The step reduction factor in case of failed residual assembling
            (e.g. the "warp violation" error caused by a negative volume
            element resulting from too large deformations)."""),
        ('ls_min', '0.0 < float < 1.0', 1e-5, False,
         'The minimum step reduction factor.'),
        ('check', '0, 1 or 2', 0, False,
         """If >= 1, check the tangent matrix using finite differences.  If 2,
            plot the resulting sparsity patterns."""),
        ('delta', 'float', 1e-6, False,
         r"""If `check >= 1`, the finite difference matrix is taken as
            :math:`A_{ij} = \frac{f_i(x_j + \delta) - f_i(x_j - \delta)}{2
            \delta}`."""),
        ('output', 'function', None, False,
         """If given, use it instead of :func:`output()
            <sfepy.base.base.output()>` function."""),
        ('yscales', 'list of str', ['linear', 'log', 'log', 'linear'], False,
         'The list of four convergence log subplot scales.'),
        ('log', 'dict or None', None, False,
         """If not None, log the convergence according to the configuration in
            the following form: ``{'text' : 'log.txt', 'plot' : 'log.pdf'}``.
            Each of the dict items can be None."""),
    ]

    def __init__(self, conf, **kwargs):
        OptimizationSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        if conf.is_any_log:
            self.log = Log([[r'$||\Psi||$'], [r'$||\nabla \Psi||$'],
                            [r'$\alpha$'], ['iteration']],
                           xlabels=['', '', 'all iterations', 'all iterations'],
                           yscales=conf.yscales,
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None

    def __call__(self, x0, conf=None, obj_fun=None, obj_fun_grad=None,
                 status=None, obj_args=None):
        conf = get_default(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)

        if conf.output:
            globals()['output'] = conf.output

        output('entering optimization loop...')

        nc_of, tt_of, fn_of = wrap_function(obj_fun, obj_args)
        nc_ofg, tt_ofg, fn_ofg = wrap_function(obj_fun_grad, obj_args)

        time_stats = {'of' : tt_of, 'ofg': tt_ofg, 'check' : []}

        ofg = None

        it = 0
        xit = x0.copy()
        while 1:

            of = fn_of(xit)

            if it == 0:
                of0 = ofit0 = of_prev = of
                of_prev_prev = of + 5000.0

            if ofg is None:
                ofg = fn_ofg(xit)

            if conf.check:
                tt = time.clock()
                check_gradient(xit, ofg, fn_of, conf.delta, conf.check)
                time_stats['check'].append(time.clock() - tt)

            ofg_norm = nla.norm(ofg, conf.norm)

            ret = conv_test(conf, it, of, ofit0, ofg_norm)
            if ret >= 0:
                break
            ofit0 = of

            ##
            # Backtrack (on errors).
            alpha = conf.ls0
            can_ls = True
            while 1:
                xit2 = xit - alpha * ofg
                aux = fn_of(xit2)

                if self.log is not None:
                    self.log(of, ofg_norm, alpha, it)

                if aux is None:
                    alpha *= conf.ls_red_warp
                    can_ls = False
                    output('warp: reducing step (%f)' % alpha)
                elif conf.ls and conf.ls_method == 'backtracking':
                    if aux < of * conf.ls_on: break
                    alpha *= conf.ls_red
                    output('backtracking: reducing step (%f)' % alpha)
                else:
                    of_prev_prev = of_prev
                    of_prev = aux
                    break

                if alpha < conf.ls_min:
                    if aux is None:
                        raise RuntimeError, 'giving up...'
                    output('linesearch failed, continuing anyway')
                    break

            # These values are modified by the line search, even if it fails
            of_prev_bak = of_prev
            of_prev_prev_bak = of_prev_prev

            if conf.ls and can_ls and conf.ls_method == 'full':
                output('full linesearch...')
                alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                    linesearch.line_search(fn_of,fn_ofg,xit,
                                           -ofg,ofg,of_prev,of_prev_prev,
                                           c2=0.4)
                if alpha is None:  # line search failed -- use different one.
                    alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                        sopt.line_search(fn_of,fn_ofg,xit,
                                         -ofg,ofg,of_prev_bak,
                                         of_prev_prev_bak)
                    if alpha is None or alpha == 0:
                        # This line search also failed to find a better
                        # solution.
                        ret = 3
                        break
                output(' -> alpha: %.8e' % alpha)
            else:
                if conf.ls_method == 'full':
                    output('full linesearch off (%s and %s)'
                           % (conf.ls, can_ls))
                ofg1 = None

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

            xit = xit - alpha * ofg
            if ofg1 is None:
                ofg = None
            else:
                ofg = ofg1.copy()

            for key, val in time_stats.iteritems():
                if len(val):
                    output('%10s: %7.2f [s]' % (key, val[-1]))

            it = it + 1

        output('status:               %d' % ret)
        output('initial value:        %.8e' % of0)
        output('current value:        %.8e' % of)
        output('iterations:           %d' % it)
        output('function evaluations: %d in %.2f [s]'
               % (nc_of[0], nm.sum(time_stats['of'])))
        output('gradient evaluations: %d in %.2f [s]'
               % (nc_ofg[0], nm.sum(time_stats['ofg'])))

        if self.log is not None:
            self.log(of, ofg_norm, alpha, it)

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

            else:
                self.log(finished=True)

        if status is not None:
            status['log'] = self.log
            status['status'] = status
            status['of0'] = of0
            status['of'] = of
            status['it'] = it
            status['nc_of'] = nc_of[0]
            status['nc_ofg'] = nc_ofg[0]
            status['time_stats'] = time_stats

        return xit
예제 #21
0
def main():
    # Aluminium and epoxy.
    default_pars = '70e9,0.35,2.799e3, 3.8e9,0.27,1.142e3'
    default_solver_conf = ("kind='eig.scipy',method='eigh',tol=1.0e-5,"
                           "maxiter=1000,which='LM',sigma=0.0")

    parser = ArgumentParser(description=__doc__,
                            formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('--pars',
                        metavar='young1,poisson1,density1'
                        ',young2,poisson2,density2',
                        action='store',
                        dest='pars',
                        default=default_pars,
                        help=helps['pars'])
    parser.add_argument('--conf',
                        metavar='filename',
                        action='store',
                        dest='conf',
                        default=None,
                        help=helps['conf'])
    parser.add_argument('--mesh-size',
                        type=float,
                        metavar='float',
                        action='store',
                        dest='mesh_size',
                        default=None,
                        help=helps['mesh_size'])
    parser.add_argument('--unit-multipliers',
                        metavar='c_time,c_length,c_mass',
                        action='store',
                        dest='unit_multipliers',
                        default='1.0,1.0,1.0',
                        help=helps['unit_multipliers'])
    parser.add_argument('--plane',
                        action='store',
                        dest='plane',
                        choices=['strain', 'stress'],
                        default='strain',
                        help=helps['plane'])
    parser.add_argument('--wave-dir',
                        metavar='float,float[,float]',
                        action='store',
                        dest='wave_dir',
                        default='1.0,0.0,0.0',
                        help=helps['wave_dir'])
    parser.add_argument('--mode',
                        action='store',
                        dest='mode',
                        choices=['omega', 'kappa'],
                        default='omega',
                        help=helps['mode'])
    parser.add_argument('--range',
                        metavar='start,stop,count',
                        action='store',
                        dest='range',
                        default='10,100,10',
                        help=helps['range'])
    parser.add_argument('--order',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='order',
                        default=1,
                        help=helps['order'])
    parser.add_argument('--refine',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='refine',
                        default=0,
                        help=helps['refine'])
    parser.add_argument('-n',
                        '--n-eigs',
                        metavar='int',
                        type=int,
                        action='store',
                        dest='n_eigs',
                        default=6,
                        help=helps['n_eigs'])
    parser.add_argument('--eigs-only',
                        action='store_true',
                        dest='eigs_only',
                        default=False,
                        help=helps['eigs_only'])
    parser.add_argument('--solver-conf',
                        metavar='dict-like',
                        action='store',
                        dest='solver_conf',
                        default=default_solver_conf,
                        help=helps['solver_conf'])
    parser.add_argument('--save-materials',
                        action='store_true',
                        dest='save_materials',
                        default=False,
                        help=helps['save_materials'])
    parser.add_argument('--log-std-waves',
                        action='store_true',
                        dest='log_std_waves',
                        default=False,
                        help=helps['log_std_waves'])
    parser.add_argument('--silent',
                        action='store_true',
                        dest='silent',
                        default=False,
                        help=helps['silent'])
    parser.add_argument('-c',
                        '--clear',
                        action='store_true',
                        dest='clear',
                        default=False,
                        help=helps['clear'])
    parser.add_argument('-o',
                        '--output-dir',
                        metavar='path',
                        action='store',
                        dest='output_dir',
                        default='output',
                        help=helps['output_dir'])
    parser.add_argument('mesh_filename',
                        default='',
                        help=helps['mesh_filename'])
    options = parser.parse_args()

    output_dir = options.output_dir

    output.set_output(filename=os.path.join(output_dir, 'output_log.txt'),
                      combined=options.silent == False)

    if options.conf is not None:
        mod = import_file(options.conf)
        apply_units = mod.apply_units
        define = mod.define
        set_wave_dir = mod.set_wave_dir

    else:
        apply_units = apply_units_le
        define = define_le
        set_wave_dir = set_wave_dir_le

    options.pars = [float(ii) for ii in options.pars.split(',')]
    options.unit_multipliers = [
        float(ii) for ii in options.unit_multipliers.split(',')
    ]
    options.wave_dir = [float(ii) for ii in options.wave_dir.split(',')]
    aux = options.range.split(',')
    options.range = [float(aux[0]), float(aux[1]), int(aux[2])]
    options.solver_conf = dict_from_string(options.solver_conf)

    if options.clear:
        remove_files_patterns(output_dir, ['*.h5', '*.vtk', '*.txt'],
                              ignores=['output_log.txt'],
                              verbose=True)

    filename = os.path.join(output_dir, 'options.txt')
    ensure_path(filename)
    save_options(filename, [('options', vars(options))])

    pars = apply_units(options.pars, options.unit_multipliers)
    output('material parameters with applied unit multipliers:')
    output(pars)

    if options.mode == 'omega':
        rng = copy(options.range)
        rng[:2] = apply_unit_multipliers(options.range[:2],
                                         ['wave_number', 'wave_number'],
                                         options.unit_multipliers)
        output('wave number range with applied unit multipliers:', rng)

    else:
        rng = copy(options.range)
        rng[:2] = apply_unit_multipliers(options.range[:2],
                                         ['frequency', 'frequency'],
                                         options.unit_multipliers)
        output('frequency range with applied unit multipliers:', rng)

    define_problem = functools.partial(define,
                                       filename_mesh=options.mesh_filename,
                                       pars=pars,
                                       approx_order=options.order,
                                       refinement_level=options.refine,
                                       solver_conf=options.solver_conf,
                                       plane=options.plane)

    conf = ProblemConf.from_dict(define_problem(), sys.modules[__name__])

    pb = Problem.from_conf(conf)
    dim = pb.domain.shape.dim

    if dim != 2:
        options.plane = 'strain'

    wdir = nm.asarray(options.wave_dir[:dim], dtype=nm.float64)
    wdir = wdir / nm.linalg.norm(wdir)

    stepper = TimeStepper(rng[0], rng[1], dt=None, n_step=rng[2])

    bbox = pb.domain.mesh.get_bounding_box()
    size = (bbox[1] - bbox[0]).max()
    scaling0 = apply_unit_multipliers([1.0], ['length'],
                                      options.unit_multipliers)[0]
    scaling = scaling0
    if options.mesh_size is not None:
        scaling *= options.mesh_size / size
    output('scaling factor of periodic cell mesh coordinates:', scaling)
    output('new mesh size with applied unit multipliers:', scaling * size)
    pb.domain.mesh.coors[:] *= scaling
    pb.set_mesh_coors(pb.domain.mesh.coors, update_fields=True)

    bzone = 2.0 * nm.pi / (scaling * size)
    output('1. Brillouin zone size:', bzone * scaling0)
    output('1. Brillouin zone size with applied unit multipliers:', bzone)

    pb.time_update()
    pb.update_materials()

    if options.save_materials or options.log_std_waves:
        stiffness = pb.evaluate('ev_integrate_mat.2.Omega(m.D, u)',
                                mode='el_avg',
                                copy_materials=False,
                                verbose=False)
        young, poisson = mc.youngpoisson_from_stiffness(stiffness,
                                                        plane=options.plane)
        density = pb.evaluate('ev_integrate_mat.2.Omega(m.density, u)',
                              mode='el_avg',
                              copy_materials=False,
                              verbose=False)

    if options.save_materials:
        out = {}
        out['young'] = Struct(name='young',
                              mode='cell',
                              data=young[..., None, None])
        out['poisson'] = Struct(name='poisson',
                                mode='cell',
                                data=poisson[..., None, None])
        out['density'] = Struct(name='density', mode='cell', data=density)
        materials_filename = os.path.join(output_dir, 'materials.vtk')
        pb.save_state(materials_filename, out=out)

    # Set the normalized wave vector direction to the material(s).
    set_wave_dir(pb.get_materials(), wdir)

    conf = pb.solver_confs['eig']
    eig_solver = Solver.any_from_conf(conf)

    # Assemble the matrices.
    mtx_m = pb.mtx_a.copy()
    eq_m = pb.equations['M']
    mtx_m = eq_m.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_m)
    mtx_m.eliminate_zeros()

    mtx_k = pb.mtx_a.copy()
    eq_k = pb.equations['K']
    mtx_k = eq_k.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_k)
    mtx_k.eliminate_zeros()

    mtx_s = pb.mtx_a.copy()
    eq_s = pb.equations['S']
    mtx_s = eq_s.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_s)
    mtx_s.eliminate_zeros()

    mtx_r = pb.mtx_a.copy()
    eq_r = pb.equations['R']
    mtx_r = eq_r.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx_r)
    mtx_r.eliminate_zeros()

    output('symmetry checks of real blocks:')
    output('M - M^T:', _max_diff_csr(mtx_m, mtx_m.T))
    output('K - K^T:', _max_diff_csr(mtx_k, mtx_k.T))
    output('S - S^T:', _max_diff_csr(mtx_s, mtx_s.T))
    output('R + R^T:', _max_diff_csr(mtx_r, -mtx_r.T))

    n_eigs = options.n_eigs
    if options.n_eigs > mtx_k.shape[0]:
        options.n_eigs = mtx_k.shape[0]
        n_eigs = None

    if options.mode == 'omega':
        eigenshapes_filename = os.path.join(
            output_dir, 'frequency-eigenshapes-%s.vtk' % stepper.suffix)

        extra = []
        extra_plot_kwargs = []
        if options.log_std_waves:
            lam, mu = mc.lame_from_youngpoisson(young,
                                                poisson,
                                                plane=options.plane)
            alam = nm.average(lam)
            amu = nm.average(mu)
            adensity = nm.average(density)

            cp = nm.sqrt((alam + 2.0 * amu) / adensity)
            cs = nm.sqrt(amu / adensity)
            output('average p-wave speed:', cp)
            output('average shear wave speed:', cs)

            extra = [r'$\omega_p$', r'$\omega_s$']
            extra_plot_kwargs = [{
                'ls': '--',
                'color': 'k'
            }, {
                'ls': '--',
                'color': 'gray'
            }]

        log = Log(
            [[r'$\lambda_{%d}$' % ii for ii in range(options.n_eigs)],
             [r'$\omega_{%d}$' % ii for ii in range(options.n_eigs)] + extra],
            plot_kwargs=[{}, [{}] * options.n_eigs + extra_plot_kwargs],
            yscales=['linear', 'linear'],
            xlabels=[r'$\kappa$', r'$\kappa$'],
            ylabels=[r'eigenvalues $\lambda_i$', r'frequencies $\omega_i$'],
            log_filename=os.path.join(output_dir, 'frequencies.txt'),
            aggregate=1000,
            sleep=0.1)

        for iv, wmag in stepper:
            output('step %d: wave vector %s' % (iv, wmag * wdir))

            mtx_a = mtx_k + wmag**2 * mtx_s + (1j * wmag) * mtx_r
            mtx_b = mtx_m

            output('A - A^H:', _max_diff_csr(mtx_a, mtx_a.H))

            if options.eigs_only:
                eigs = eig_solver(mtx_a,
                                  mtx_b,
                                  n_eigs=n_eigs,
                                  eigenvectors=False)
                svecs = None

            else:
                eigs, svecs = eig_solver(mtx_a,
                                         mtx_b,
                                         n_eigs=options.n_eigs,
                                         eigenvectors=True)
            omegas = nm.sqrt(eigs)

            output('eigs, omegas:\n', nm.c_[eigs, omegas])

            out = tuple(eigs) + tuple(omegas)
            if options.log_std_waves:
                out = out + (cp * wmag, cs * wmag)
            log(*out, x=[wmag, wmag])

            save_eigenvectors(eigenshapes_filename % iv, svecs, pb)

        log(save_figure=os.path.join(output_dir, 'frequencies.png'))
        log(finished=True)

    else:
        import scipy.sparse as sps
        from sksparse.cholmod import cholesky

        eigenshapes_filename = os.path.join(
            output_dir, 'wave-number-eigenshapes-%s.vtk' % stepper.suffix)

        factor = cholesky(mtx_s)
        perm = factor.P()
        ir = nm.arange(len(perm))
        mtx_p = sps.coo_matrix((nm.ones_like(perm), (ir, perm)))
        mtx_l = mtx_p.T * factor.L()
        mtx_eye = sps.eye(mtx_l.shape[0], dtype=nm.float64)

        output('S - LL^T:', _max_diff_csr(mtx_s, mtx_l * mtx_l.T))

        log = Log([[r'$\kappa_{%d}$' % ii for ii in range(options.n_eigs)]],
                  plot_kwargs=[{
                      'ls': 'None',
                      'marker': 'o'
                  }],
                  yscales=['linear'],
                  xlabels=[r'$\omega$'],
                  ylabels=[r'wave numbers $\kappa_i$'],
                  log_filename=os.path.join(output_dir, 'wave-numbers.txt'),
                  aggregate=1000,
                  sleep=0.1)
        for io, omega in stepper:
            output('step %d: frequency %s' % (io, omega))

            mtx_a = sps.bmat([[mtx_k - omega**2 * mtx_m, None],
                              [None, mtx_eye]])
            mtx_b = sps.bmat([[1j * mtx_r, mtx_l], [mtx_l.T, None]])

            output('A - A^T:', _max_diff_csr(mtx_a, mtx_a.T))
            output('A - A^H:', _max_diff_csr(mtx_a, mtx_a.T))
            output('B - B^H:', _max_diff_csr(mtx_b, mtx_b.H))

            if options.eigs_only:
                eigs = eig_solver(mtx_a,
                                  mtx_b,
                                  n_eigs=n_eigs,
                                  eigenvectors=False)
                svecs = None

            else:
                eigs, svecs = eig_solver(mtx_a,
                                         mtx_b,
                                         n_eigs=options.n_eigs,
                                         eigenvectors=True)
            kappas = eigs

            output('kappas:\n', kappas[:, None])

            out = tuple(kappas)
            log(*out, x=[omega])

            save_eigenvectors(eigenshapes_filename % io, svecs, pb)

        log(save_figure=os.path.join(output_dir, 'wave-numbers.png'))
        log(finished=True)
예제 #22
0
파일: shaper.py 프로젝트: brbr520/sfepy
def solve_navier_stokes(conf, options):
    opts = conf.options

    dpb = ProblemDefinition.from_conf(conf, init_equations=False)
    equations = getattr(conf, "_".join(("equations_direct", opts.problem)))
    dpb.set_equations(equations)

    ls_conf = dpb.get_solver_conf(opts.ls)
    nls_conf = dpb.get_solver_conf(opts.nls_direct)

    method = opts.direct_method
    if method == "stationary":
        data = {}
        dpb.time_update(None)
        state_dp = dpb.solve(nls_conf=nls_conf)

    elif method == "transient":
        ls = Solver.any_from_conf(ls_conf)
        ts_conf = dpb.get_solver_conf(opts.ts_direct)

        data = {"ts": Struct(dt=ts_conf.dt)}

        # Plug in mass term.
        mequations = {}
        for key, eq in equations.iteritems():
            if "dw_div_grad" in eq:
                eq = "+".join((ts_conf.mass_term, eq)).replace("++", "+")
            mequations[key] = eq

        if ts_conf.stokes_init:
            state_dp0 = solve_stokes(dpb, conf.equations_direct_stokes, nls_conf)
            dpb.set_equations(mequations)
        else:
            dpb.set_equations(mequations)
            state_dp0 = dpb.create_state()
            dpb.time_update(None)
            state_dp0.apply_ebc()

        from sfepy.base.log import Log

        log = Log.from_conf(Struct(is_plot=True), ([r"$||u||$"], [r"$||p||$"]))

        output("Navier-Stokes...")
        ev = BasicEvaluator(dpb, ts=Struct(dt=ts_conf.dt))
        nls = Solver.any_from_conf(nls_conf, evaluator=ev, lin_solver=ls)

        n_step = ts_conf.n_step
        step = 0
        while 1:
            for ii in xrange(n_step):
                output(step)

                vec_u = state_dp0("w")
                vec_p = state_dp0("r")
                log(nm.linalg.norm(vec_u), nm.linalg.norm(vec_p))

                dpb.variables.set_data_from_state("w_0", state_dp0(), "w")
                vec_dp = nls(state_dp0())

                step += 1
                state_dp = state_dp0.copy()
                state_dp.set_reduced(vec_dp)

                state_dp0 = state_dp

            if ts_conf.interactive:
                try:
                    n_step = int(raw_input("continue: "))
                    if n_step <= 0:
                        break
                except:
                    break

        vec_u = state_dp("w")
        vec_p = state_dp("r")
        log(nm.linalg.norm(vec_u), nm.linalg.norm(vec_p), finished=True)

    else:
        raise "unknown Navier-Stokes solution method (%s)!" % method

    return dpb, state_dp, data
예제 #23
0
class FMinSteepestDescent( OptimizationSolver ):
    name = 'opt.fmin_sd'

    def process_conf( conf ):
        """
        Missing items are set to default values.
        
        Example configuration, all items::
        
            solver_0 = {
                'name'      : 'fmin_sd',
                'kind'      : 'opt.fmin_sd',

                'i_max'      : 10,
                'eps_rd'     : 1e-5, # Relative delta of objective function
                'eps_of'     : 1e-4,
                'eps_ofg'    : 1e-8,
                'norm'      : nm.Inf,
                'ls'        : True, # Linesearch.
                'ls_method'  : 'backtracking', # 'backtracking' or 'full'
                'ls0'       : 0.25,
                'ls_red'     : 0.5,
                'ls_red_warp' : 0.1,
                'ls_on'      : 0.99999,
                'ls_min'     : 1e-5,
                'check'     : 0,
                'delta'     : 1e-6,
                'output'    : None, # 'itc'
                'log'       : {'text' : 'output/log.txt',
                               'plot' : 'output/log.png'},
                'yscales'   : ['linear', 'log', 'log', 'linear'],
            }
        """
        get = conf.get_default_attr

        i_max = get( 'i_max', 10 )
        eps_rd = get( 'eps_rd', 1e-5 )
        eps_of = get( 'eps_of', 1e-4 )
        eps_ofg = get( 'eps_ofg', 1e-8 )
        norm = get( 'norm', nm.Inf )
        ls = get( 'ls', True )
        ls_method = get( 'ls_method', 'backtracking' )
        ls0 = get( 'ls0', 0.25 )
        ls_red = get( 'ls_red', 0.5 )
        ls_red_warp = get( 'ls_red_warp', 0.1 )
        ls_on = get( 'ls_on', 0.99999 )
        ls_min = get( 'ls_min', 1e-5 )
        check = get( 'check', 0 )
        delta = get( 'delta', 1e-6)
        output = get( 'output', None )
        yscales = get( 'yscales', ['linear', 'log', 'log', 'linear'] )

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        common = OptimizationSolver.process_conf( conf )
        return Struct( **locals() ) + common
    process_conf = staticmethod( process_conf )

    ##
    # 17.10.2007, c
    def __init__( self, conf, **kwargs ):
        OptimizationSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||\Psi||$'], [r'$||\nabla \Psi||$'],
                            [r'$\alpha$'], ['iteration']],
                           xlabels=['', '', 'all iterations', 'all iterations'],
                           yscales=conf.yscales,
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None

    ##
    # 19.04.2006, c
    # 20.04.2006
    # 21.04.2006
    # 26.04.2006
    # 06.06.2006
    # 07.06.2006
    # 04.09.2006
    # 21.03.2007
    # 17.10.2007, from fmin_sd()
    def __call__( self, x0, conf = None, obj_fun = None, obj_fun_grad = None,
                  status = None, obj_args = None ):
#    def fmin_sd( conf, x0, fn_of, fn_ofg, args = () ):

        conf = get_default( 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 )

        if conf.output:
            globals()['output'] = conf.output

        output( 'entering optimization loop...' )

        nc_of, tt_of, fn_of = wrap_function( obj_fun, obj_args )
        nc_ofg, tt_ofg, fn_ofg = wrap_function( obj_fun_grad, obj_args )

        time_stats = {'of' : tt_of, 'ofg': tt_ofg, 'check' : []}

        ofg = None

        it = 0
        xit = x0.copy()
        while 1:

            of = fn_of( xit )

            if it == 0:
                of0 = ofit0 = of_prev = of
                of_prev_prev = of + 5000.0

            if ofg is None:
                ofg = fn_ofg( xit )

            if conf.check:
                tt = time.clock()
                check_gradient( xit, ofg, fn_of, conf.delta, conf.check )
                time_stats['check'].append( time.clock() - tt )

            ofg_norm = nla.norm( ofg, conf.norm )

            ret = conv_test( conf, it, of, ofit0, ofg_norm )
            if ret >= 0:
                break
            ofit0 = of

            ##
            # Backtrack (on errors).
            alpha = conf.ls0
            can_ls = True
            while 1:
                xit2 = xit - alpha * ofg
                aux = fn_of( xit2 )

                if self.log is not None:
                    self.log(of, ofg_norm, alpha, it)

                if aux is None:
                    alpha *= conf.ls_red_warp
                    can_ls = False
                    output( 'warp: reducing step (%f)' % alpha )
                elif conf.ls and conf.ls_method == 'backtracking':
                    if aux < of * conf.ls_on: break
                    alpha *= conf.ls_red
                    output( 'backtracking: reducing step (%f)' % alpha )
                else:
                    of_prev_prev = of_prev
                    of_prev = aux
                    break

                if alpha < conf.ls_min:
                    if aux is None:
                        raise RuntimeError, 'giving up...'
                    output( 'linesearch failed, continuing anyway' )
                    break

            # These values are modified by the line search, even if it fails
            of_prev_bak = of_prev
            of_prev_prev_bak = of_prev_prev

            if conf.ls and can_ls and conf.ls_method == 'full':
                output( 'full linesearch...' )
                alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                       linesearch.line_search(fn_of,fn_ofg,xit,
                                              -ofg,ofg,of_prev,of_prev_prev,
                                              c2=0.4)
                if alpha is None:  # line search failed -- use different one.
                    alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                           sopt.line_search(fn_of,fn_ofg,xit,
                                            -ofg,ofg,of_prev_bak,
                                            of_prev_prev_bak)
                    if alpha is None or alpha == 0:
                        # This line search also failed to find a better solution.
                        ret = 3
                        break
                output( ' -> alpha: %.8e' % alpha )
            else:
                if conf.ls_method == 'full':
                    output( 'full linesearch off (%s and %s)' % (conf.ls,
                                                                 can_ls) )
                ofg1 = None

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

            xit = xit - alpha * ofg
            if ofg1 is None:
                ofg = None
            else:
                ofg = ofg1.copy()

            for key, val in time_stats.iteritems():
                if len( val ):
                    output( '%10s: %7.2f [s]' % (key, val[-1]) )

            it = it + 1

        output( 'status:               %d' % ret )
        output( 'initial value:        %.8e' % of0 )
        output( 'current value:        %.8e' % of )
        output( 'iterations:           %d' % it )
        output( 'function evaluations: %d in %.2f [s]' \
              % (nc_of[0], nm.sum( time_stats['of'] ) ) )
        output( 'gradient evaluations: %d in %.2f [s]' \
              % (nc_ofg[0], nm.sum( time_stats['ofg'] ) ) )

        if self.log is not None:
            self.log(of, ofg_norm, alpha, it)

            if conf.log.plot is not None:
                self.log(save_figure=conf.log.plot,
                         finished=True)
            else:
                self.log(finished=True)
                
        if status is not None:
            status['log'] = self.log
            status['status'] = status
            status['of0'] = of0
            status['of'] = of
            status['it'] = it
            status['nc_of'] = nc_of[0]
            status['nc_ofg'] = nc_ofg[0]
            status['time_stats'] = time_stats

        return xit
예제 #24
0
파일: nls.py 프로젝트: lokik/sfepy
class Newton(NonlinearSolver):
    r"""
    Solves a nonlinear system :math:`f(x) = 0` using the Newton method with
    backtracking line-search, starting with an initial guess :math:`x^0`.
    """
    name = 'nls.newton'

    __metaclass__ = SolverMeta

    _parameters = [
        ('i_max', 'int', 1, False, 'The maximum number of iterations.'),
        ('eps_a', 'float', 1e-10, False,
         'The absolute tolerance for the residual, i.e. :math:`||f(x^i)||`.'),
        ('eps_r', 'float', 1.0, False,
         """The relative tolerance for the residual, i.e. :math:`||f(x^i)|| /
            ||f(x^0)||`."""),
        ('eps_mode', "'and' or 'or'", 'and', False,
         """The logical operator to use for combining the absolute and relative
            tolerances."""),
        ('macheps', 'float', nm.finfo(nm.float64).eps, False,
         'The float considered to be machine "zero".'),
        ('lin_red', 'float', 1.0, False,
         """The linear system solution error should be smaller than (`eps_a` *
            `lin_red`), otherwise a warning is printed."""),
        ('lin_precision', 'float or None', None, False,
         """If not None, the linear system solution tolerances are set in each
            nonlinear iteration relative to the current residual norm by the
            `lin_precision` factor. Ignored for direct linear solvers."""),
        ('ls_on', 'float', 0.99999, False,
         """Start the backtracking line-search by reducing the step, if
            :math:`||f(x^i)|| / ||f(x^{i-1})||` is larger than `ls_on`."""),
        ('ls_red', '0.0 < float < 1.0', 0.1, False,
         'The step reduction factor in case of correct residual assembling.'),
        ('ls_red_warp', '0.0 < float < 1.0', 0.001, False,
         """The step reduction factor in case of failed residual assembling
            (e.g. the "warp violation" error caused by a negative volume
            element resulting from too large deformations)."""),
        ('ls_min', '0.0 < float < 1.0', 1e-5, False,
         'The minimum step reduction factor.'),
        ('give_up_warp', 'bool', False, False,
         'If True, abort on the "warp violation" error.'),
        ('check', '0, 1 or 2', 0, False,
         """If >= 1, check the tangent matrix using finite differences.  If 2,
            plot the resulting sparsity patterns."""),
        ('delta', 'float', 1e-6, False,
         r"""If `check >= 1`, the finite difference matrix is taken as
            :math:`A_{ij} = \frac{f_i(x_j + \delta) - f_i(x_j - \delta)}{2
            \delta}`."""),
        ('log', 'dict or None', None, False,
         """If not None, log the convergence according to the configuration in
            the following form: ``{'text' : 'log.txt', 'plot' : 'log.pdf'}``.
            Each of the dict items can be None."""),
        ('is_linear', 'bool', False, False,
         'If True, the problem is considered to be linear.'),
    ]

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None

    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

        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:
                tt = time.clock()

                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'] = time.clock() - tt
                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

            tt = time.clock()
            if not conf.is_linear:
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad('linear')

            time_stats['matrix'] = time.clock() - tt

            if conf.check:
                tt = time.clock()
                wt = check_tangent_matrix(conf, vec_x, fun, fun_grad)
                time_stats['check'] = time.clock() - tt - 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...')

            tt = time.clock()
            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'] = time.clock() - tt

            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
예제 #25
0
파일: nls.py 프로젝트: taldcroft/sfepy
class Newton(NonlinearSolver):
    name = "nls.newton"

    @staticmethod
    def process_conf(conf, kwargs):
        """
        Missing items are set to default values for a linear problem.

        Example configuration, all items::

            solver_1 = {
                'name' : 'newton',
                'kind' : 'nls.newton',

                'i_max' : 2,
                'eps_a' : 1e-8,
                'eps_r' : 1e-2,
                'macheps' : 1e-16,
                'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
                'lin_precision' : None,
                'ls_red' : 0.1,
                'ls_red_warp' : 0.001,
                'ls_on' : 0.99999,
                'ls_min' : 1e-5,
                'give_up_warp' : False,
                'check' : 0,
                'delta' : 1e-6,
                'is_plot' : False,
                'log' : None, # 'nonlinear' or 'linear' (ignore i_max)
                'problem' : 'nonlinear',
            }
        """
        get = make_get_conf(conf, kwargs)
        common = NonlinearSolver.process_conf(conf)

        log = get_logging_conf(conf)
        log = Struct(name="log_conf", **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        return (
            Struct(
                i_max=get("i_max", 1),
                eps_a=get("eps_a", 1e-10),
                eps_r=get("eps_r", 1.0),
                macheps=get("macheps", nm.finfo(nm.float64).eps),
                lin_red=get("lin_red", 1.0),
                lin_precision=get("lin_precision", None),
                ls_red=get("ls_red", 0.1),
                ls_red_warp=get("ls_red_warp", 0.001),
                ls_on=get("ls_on", 0.99999),
                ls_min=get("ls_min", 1e-5),
                give_up_warp=get("give_up_warp", False),
                check=get("check", 0),
                delta=get("delta", 1e-6),
                is_plot=get("is_plot", False),
                problem=get("problem", "nonlinear"),
                log=log,
                is_any_log=is_any_log,
            )
            + common
        )

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log(
                [[r"$||r||$"], ["iteration"]],
                xlabels=["", "all iterations"],
                ylabels=[r"$||r||$", "iteration"],
                yscales=["log", "linear"],
                is_plot=conf.log.plot is not None,
                log_filename=conf.log.text,
                formats=[["%.8e"], ["%d"]],
            )

        else:
            self.log = None

    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 :math:`f(x) = 0` by the Newton method with backtracking
        linesearch.

        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.problem == 'linear'` means 1 iteration and no
          rezidual check!
        """
        import sfepy.base.plotutils as plu

        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

        time_stats = {}

        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
        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:
                tt = time.clock()

                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["rezidual"] = time.clock() - tt
                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("rezidual 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

            tt = time.clock()
            if conf.problem == "nonlinear":
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad("linear")

            time_stats["matrix"] = time.clock() - tt

            if conf.check:
                tt = time.clock()
                wt = check_tangent_matrix(conf, vec_x, fun, fun_grad)
                time_stats["check"] = time.clock() - tt - 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...")

            tt = time.clock()
            vec_dx = lin_solver(vec_r, x0=vec_x, eps_a=eps_a, eps_r=eps_r, mtx=mtx_a)
            time_stats["solve"] = time.clock() - tt

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

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

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

            vec_x -= vec_dx

            if conf.is_plot:
                plu.plt.ion()
                plu.plt.gcf().clear()
                plu.plt.subplot(2, 2, 1)
                plu.plt.plot(vec_x_last)
                plu.plt.ylabel(r"$x_{i-1}$")
                plu.plt.subplot(2, 2, 2)
                plu.plt.plot(vec_r)
                plu.plt.ylabel(r"$r$")
                plu.plt.subplot(2, 2, 4)
                plu.plt.plot(vec_dx)
                plu.plt.ylabel(r"$\_delta x$")
                plu.plt.subplot(2, 2, 3)
                plu.plt.plot(vec_x)
                plu.plt.ylabel(r"$x_i$")
                plu.plt.draw()
                plu.plt.ioff()
                pause()

            it += 1

        if status is not None:
            status["time_stats"] = time_stats
            status["err0"] = err0
            status["err"] = err
            status["n_iter"] = it
            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
예제 #26
0
파일: oseen.py 프로젝트: Nasrollah/sfepy
class Oseen(NonlinearSolver):
    """
    The Oseen solver for Navier-Stokes equations.
    """
    name = 'nls.oseen'

    __metaclass__ = SolverMeta

    _parameters = [
        ('stabil_mat', 'str', None, True,
         'The name of stabilization material.'),
        ('adimensionalize', 'bool', False, False,
         'If True, adimensionalize the problem (not implemented!).'),
        ('check_navier_stokes_rezidual', 'bool', False, False,
         'If True, check the Navier-Stokes rezidual after the nonlinear loop.'),
        ('i_max', 'int', 1, False,
         'The maximum number of iterations.'),
        ('eps_a', 'float', 1e-10, False,
         'The absolute tolerance for the residual, i.e. :math:`||f(x^i)||`.'),
        ('eps_r', 'float', 1.0, False,
         """The relative tolerance for the residual, i.e. :math:`||f(x^i)|| /
            ||f(x^0)||`."""),
        ('macheps', 'float', nm.finfo(nm.float64).eps, False,
         'The float considered to be machine "zero".'),
        ('lin_red', 'float', 1.0, False,
         """The linear system solution error should be smaller than (`eps_a` *
            `lin_red`), otherwise a warning is printed."""),
        ('lin_precision', 'float or None', None, False,
         """If not None, the linear system solution tolerances are set in each
            nonlinear iteration relative to the current residual norm by the
            `lin_precision` factor. Ignored for direct linear solvers."""),
    ]

    def __init__(self, conf, problem, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        conf.problem = problem

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'],
                                    ['%.8e', '%.8e', '%.8e']])

        else:
            self.log = None

    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!')

        time_stats = {}

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

        variables = problem.get_variables()
        update_var = variables.set_data_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

            tt = time.clock()
            try:
                vec_r = fun(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['rezidual'] = time.clock() - tt
            if ok:
                err = nla.norm(vec_r)
                if it == 0:
                    err0 = err;
                else:
                    err += nla.norm(vec_dx)
            else: # Failure.
                output('rezidual 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

            tt = time.clock()
            try:
                mtx_a = fun_grad(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['matrix'] = time.clock() - tt
            if not ok:
                raise RuntimeError('giving up...')

            tt = time.clock()
            vec_dx = lin_solver(vec_r, x0=vec_x, mtx=mtx_a)
            time_stats['solve'] = time.clock() - tt

            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_rezidual:

            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 rezidual computation failed!')
                err_ns = err_ns0 = None
            else:
                err_ns0 = nla.norm(vec_rns0)
                err_ns = nla.norm(vec_rns)
            output('Navier-Stokes rezidual0: %.8e' % err_ns0)
            output('Navier-Stokes rezidual : %.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
예제 #27
0
파일: optimize.py 프로젝트: uberstig/sfepy
class FMinSteepestDescent(OptimizationSolver):
    """
    Steepest descent optimization solver.
    """
    name = 'opt.fmin_sd'

    __metaclass__ = SolverMeta

    _parameters = [
        ('i_max', 'int', 10, False, 'The maximum number of iterations.'),
        ('eps_rd', 'float', 1e-5, False,
         'The relative delta of the objective function.'),
        ('eps_of', 'float', 1e-4, False,
         'The tolerance for the objective function.'),
        ('eps_ofg', 'float', 1e-8, False,
         'The tolerance for the objective function gradient.'),
        ('norm', 'numpy norm', nm.Inf, False, 'The norm to be used.'),
        ('ls', 'bool', True, False, 'If True, use a line-search.'),
        ('ls_method', "{'backtracking', 'full'}", 'backtracking', False,
         'The line-search method.'),
        ('ls_on', 'float', 0.99999, False,
         """Start the backtracking line-search by reducing the step, if
            :math:`||f(x^i)|| / ||f(x^{i-1})||` is larger than `ls_on`."""),
        ('ls0', '0.0 < float < 1.0', 1.0, False, 'The initial step.'),
        ('ls_red', '0.0 < float < 1.0', 0.5, False,
         'The step reduction factor in case of correct residual assembling.'),
        ('ls_red_warp', '0.0 < float < 1.0', 0.1, False,
         """The step reduction factor in case of failed residual assembling
            (e.g. the "warp violation" error caused by a negative volume
            element resulting from too large deformations)."""),
        ('ls_min', '0.0 < float < 1.0', 1e-5, False,
         'The minimum step reduction factor.'),
        ('check', '0, 1 or 2', 0, False,
         """If >= 1, check the tangent matrix using finite differences.  If 2,
            plot the resulting sparsity patterns."""),
        ('delta', 'float', 1e-6, False,
         r"""If `check >= 1`, the finite difference matrix is taken as
            :math:`A_{ij} = \frac{f_i(x_j + \delta) - f_i(x_j - \delta)}{2
            \delta}`."""),
        ('output', 'function', None, False,
         """If given, use it instead of :func:`output()
            <sfepy.base.base.output()>` function."""),
        ('yscales', 'list of str', ['linear', 'log', 'log', 'linear'], False,
         'The list of four convergence log subplot scales.'),
        ('log', 'dict or None', None, False,
         """If not None, log the convergence according to the configuration in
            the following form: ``{'text' : 'log.txt', 'plot' : 'log.pdf'}``.
            Each of the dict items can be None."""),
    ]

    def __init__(self, conf, **kwargs):
        OptimizationSolver.__init__(self, conf, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        if conf.is_any_log:
            self.log = Log(
                [[r'$||\Psi||$'], [r'$||\nabla \Psi||$'], [r'$\alpha$'],
                 ['iteration']],
                xlabels=['', '', 'all iterations', 'all iterations'],
                yscales=conf.yscales,
                is_plot=conf.log.plot is not None,
                log_filename=conf.log.text,
                formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None

    def __call__(self,
                 x0,
                 conf=None,
                 obj_fun=None,
                 obj_fun_grad=None,
                 status=None,
                 obj_args=None):
        conf = get_default(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)

        if conf.output:
            globals()['output'] = conf.output

        output('entering optimization loop...')

        nc_of, tt_of, fn_of = wrap_function(obj_fun, obj_args)
        nc_ofg, tt_ofg, fn_ofg = wrap_function(obj_fun_grad, obj_args)

        time_stats = {'of': tt_of, 'ofg': tt_ofg, 'check': []}

        ofg = None

        it = 0
        xit = x0.copy()
        while 1:

            of = fn_of(xit)

            if it == 0:
                of0 = ofit0 = of_prev = of
                of_prev_prev = of + 5000.0

            if ofg is None:
                ofg = fn_ofg(xit)

            if conf.check:
                tt = time.clock()
                check_gradient(xit, ofg, fn_of, conf.delta, conf.check)
                time_stats['check'].append(time.clock() - tt)

            ofg_norm = nla.norm(ofg, conf.norm)

            ret = conv_test(conf, it, of, ofit0, ofg_norm)
            if ret >= 0:
                break
            ofit0 = of

            ##
            # Backtrack (on errors).
            alpha = conf.ls0
            can_ls = True
            while 1:
                xit2 = xit - alpha * ofg
                aux = fn_of(xit2)

                if self.log is not None:
                    self.log(of, ofg_norm, alpha, it)

                if aux is None:
                    alpha *= conf.ls_red_warp
                    can_ls = False
                    output('warp: reducing step (%f)' % alpha)
                elif conf.ls and conf.ls_method == 'backtracking':
                    if aux < of * conf.ls_on: break
                    alpha *= conf.ls_red
                    output('backtracking: reducing step (%f)' % alpha)
                else:
                    of_prev_prev = of_prev
                    of_prev = aux
                    break

                if alpha < conf.ls_min:
                    if aux is None:
                        raise RuntimeError, 'giving up...'
                    output('linesearch failed, continuing anyway')
                    break

            # These values are modified by the line search, even if it fails
            of_prev_bak = of_prev
            of_prev_prev_bak = of_prev_prev

            if conf.ls and can_ls and conf.ls_method == 'full':
                output('full linesearch...')
                alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                    linesearch.line_search(fn_of,fn_ofg,xit,
                                           -ofg,ofg,of_prev,of_prev_prev,
                                           c2=0.4)
                if alpha is None:  # line search failed -- use different one.
                    alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                        sopt.line_search(fn_of,fn_ofg,xit,
                                         -ofg,ofg,of_prev_bak,
                                         of_prev_prev_bak)
                    if alpha is None or alpha == 0:
                        # This line search also failed to find a better
                        # solution.
                        ret = 3
                        break
                output(' -> alpha: %.8e' % alpha)
            else:
                if conf.ls_method == 'full':
                    output('full linesearch off (%s and %s)' %
                           (conf.ls, can_ls))
                ofg1 = None

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

            xit = xit - alpha * ofg
            if ofg1 is None:
                ofg = None
            else:
                ofg = ofg1.copy()

            for key, val in time_stats.iteritems():
                if len(val):
                    output('%10s: %7.2f [s]' % (key, val[-1]))

            it = it + 1

        output('status:               %d' % ret)
        output('initial value:        %.8e' % of0)
        output('current value:        %.8e' % of)
        output('iterations:           %d' % it)
        output('function evaluations: %d in %.2f [s]' %
               (nc_of[0], nm.sum(time_stats['of'])))
        output('gradient evaluations: %d in %.2f [s]' %
               (nc_ofg[0], nm.sum(time_stats['ofg'])))

        if self.log is not None:
            self.log(of, ofg_norm, alpha, it)

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

            else:
                self.log(finished=True)

        if status is not None:
            status['log'] = self.log
            status['status'] = status
            status['of0'] = of0
            status['of'] = of
            status['it'] = it
            status['nc_of'] = nc_of[0]
            status['nc_ofg'] = nc_ofg[0]
            status['time_stats'] = time_stats

        return xit
예제 #28
0
파일: shaper.py 프로젝트: uberstig/sfepy
def solve_navier_stokes(conf, options):
    opts = conf.options

    dpb = Problem.from_conf(conf, init_equations=False)
    equations = getattr(conf, '_'.join(('equations_direct', opts.problem)))
    dpb.set_equations(equations)

    ls_conf = dpb.get_solver_conf(opts.ls)
    nls_conf = dpb.get_solver_conf(opts.nls_direct)

    method = opts.direct_method
    if method == 'stationary':
        data = {}
        dpb.time_update(None)
        state_dp = dpb.solve(nls_conf=nls_conf)

    elif method == 'transient':
        ls = Solver.any_from_conf(ls_conf)
        ts_conf = dpb.get_solver_conf(opts.ts_direct)

        data = {'ts': Struct(dt=ts_conf.dt)}

        # Plug in mass term.
        mequations = {}
        for key, eq in equations.iteritems():
            if 'dw_div_grad' in eq:
                eq = '+'.join((ts_conf.mass_term, eq)).replace('++', '+')
            mequations[key] = eq

        if ts_conf.stokes_init:
            state_dp0 = solve_stokes(dpb, conf.equations_direct_stokes,
                                     nls_conf)
            dpb.set_equations(mequations)
        else:
            dpb.set_equations(mequations)
            state_dp0 = dpb.create_state()
            dpb.time_update(None)
            state_dp0.apply_ebc()

        from sfepy.base.log import Log

        log = Log.from_conf(Struct(is_plot=True), ([r'$||u||$'], [r'$||p||$']))

        output('Navier-Stokes...')
        ev = BasicEvaluator(dpb, ts=Struct(dt=ts_conf.dt))
        nls = Solver.any_from_conf(nls_conf, evaluator=ev, lin_solver=ls)

        n_step = ts_conf.n_step
        step = 0
        while 1:
            for ii in xrange(n_step):
                output(step)

                vec_u = state_dp0('w')
                vec_p = state_dp0('r')
                log(nm.linalg.norm(vec_u), nm.linalg.norm(vec_p))

                dpb.variables.set_data_from_state('w_0', state_dp0(), 'w')
                vec_dp = nls(state_dp0())

                step += 1
                state_dp = state_dp0.copy()
                state_dp.set_reduced(vec_dp)

                state_dp0 = state_dp

            if ts_conf.interactive:
                try:
                    n_step = int(raw_input('continue: '))
                    if n_step <= 0: break
                except:
                    break

        vec_u = state_dp('w')
        vec_p = state_dp('r')
        log(nm.linalg.norm(vec_u), nm.linalg.norm(vec_p), finished=True)

    else:
        raise 'unknown Navier-Stokes solution method (%s)!' % method

    return dpb, state_dp, data
예제 #29
0
class Oseen(NonlinearSolver):
    """
    The Oseen solver for Navier-Stokes equations.
    """
    name = 'nls.oseen'

    _parameters = [
        ('stabil_mat', 'str', None, True,
         'The name of stabilization material.'),
        ('adimensionalize', 'bool', False, False,
         'If True, adimensionalize the problem (not implemented!).'),
        ('check_navier_stokes_residual', 'bool', False, False,
         'If True, check the Navier-Stokes residual after the nonlinear loop.'
         ),
        ('i_max', 'int', 1, False, 'The maximum number of iterations.'),
        ('eps_a', 'float', 1e-10, False,
         'The absolute tolerance for the residual, i.e. :math:`||f(x^i)||`.'),
        ('eps_r', 'float', 1.0, False,
         """The relative tolerance for the residual, i.e. :math:`||f(x^i)|| /
            ||f(x^0)||`."""),
        ('macheps', 'float', nm.finfo(nm.float64).eps, False,
         'The float considered to be machine "zero".'),
        ('lin_red', 'float', 1.0, False,
         """The linear system solution error should be smaller than (`eps_a` *
            `lin_red`), otherwise a warning is printed."""),
        ('lin_precision', 'float or None', None, False,
         """If not None, the linear system solution tolerances are set in each
            nonlinear iteration relative to the current residual norm by the
            `lin_precision` factor. Ignored for direct linear solvers."""),
    ]

    def __init__(self, conf, context=None, **kwargs):
        NonlinearSolver.__init__(self, conf, context=context, **kwargs)

        conf = self.conf

        log = get_logging_conf(conf)
        conf.log = log = Struct(name='log_conf', **log)
        conf.is_any_log = (log.text is not None) or (log.plot is not None)

        conf.problem = context

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'], ['%.8e', '%.8e',
                                                       '%.8e']])

        else:
            self.log = None

    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
예제 #30
0
class Newton(NonlinearSolver):
    r"""
    Solves a nonlinear system :math:`f(x) = 0` using the Newton method with
    backtracking line-search, starting with an initial guess :math:`x^0`.

    For common configuration parameters, see :class:`Solver
    <sfepy.solvers.solvers.Solver>`.

    Parameters
    ----------
    i_max : int
        The maximum number of iterations.
    eps_a : float
        The absolute tolerance for the residual, i.e. :math:`||f(x^i)||`.
    eps_r : float
        The relative tolerance for the residual, i.e. :math:`||f(x^i)|| /
        ||f(x^0)||`.
    macheps : float
        The float considered to be machine "zero".
    lin_red : float
        The linear system solution error should be smaller than (`eps_a` *
        `lin_red`), otherwise a warning is printed.
    lin_precision : float or None
        If not None, the linear system solution tolerances are set in each
        nonlinear iteration relative to the current residual norm by the
        `lin_precision` factor. Ignored for direct linear solvers.
    ls_on : float
        Start the backtracking line-search by reducing the step, if
        :math:`||f(x^i)|| / ||f(x^{i-1})||` is larger than `ls_on`.
    ls_red : 0.0 < float < 1.0
        The step reduction factor in case of correct residual assembling.
    ls_red_warp : 0.0 < float < 1.0
        The step reduction factor in case of failed residual assembling
        (e.g. the "warp violation" error caused by a negative volume element
        resulting from too large deformations).
    ls_min : 0.0 < float < 1.0
        The minimum step reduction factor.
    give_up_warp : bool
        If True, abort on the "warp violation" error.
    check : 0, 1 or 2
        If >= 1, check the tangent matrix using finite differences. If 2, plot
        the resulting sparsity patterns.
    delta : float
        If `check >= 1`, the finite difference matrix is taken as :math:`A_{ij}
        = \frac{f_i(x_j + \delta) - f_i(x_j - \delta)}{2 \delta}`.
    is_plot : False
        If True, plot the solution and residual in each step.
    log : dict or None
        If not None, log the convergence according to the configuration in the
        following form::

            {'text' : 'log.txt', 'plot' : 'log.pdf'}

        Each of the dict items can be None.
    problem : 'nonlinear' or 'linear'
        Specifies if the problem is linear or non-linear.
    """
    name = 'nls.newton'

    @staticmethod
    def process_conf(conf, kwargs):
        """
        Missing items are set to default values for a linear problem.

        Example configuration, all items::

            solver_1 = {
                'name' : 'newton',
                'kind' : 'nls.newton',

                'i_max' : 2,
                'eps_a' : 1e-8,
                'eps_r' : 1e-2,
                'macheps' : 1e-16,
                'lin_red' : 1e-2, # Linear system error < (eps_a * lin_red).
                'lin_precision' : None,
                'ls_on' : 0.99999,
                'ls_red' : 0.1,
                'ls_red_warp' : 0.001,
                'ls_min' : 1e-5,
                'give_up_warp' : False,
                'check' : 0,
                'delta' : 1e-6,
                'is_plot' : False,
                'log' : None, # 'nonlinear' or 'linear' (ignore i_max)
                'problem' : 'nonlinear',
            }
        """
        get = make_get_conf(conf, kwargs)
        common = NonlinearSolver.process_conf(conf)

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        return Struct(i_max=get('i_max', 1),
                      eps_a=get('eps_a', 1e-10),
                      eps_r=get('eps_r', 1.0),
                      macheps=get('macheps', nm.finfo(nm.float64).eps),
                      lin_red=get('lin_red', 1.0),
                      lin_precision=get('lin_precision', None),
                      ls_red=get('ls_red', 0.1),
                      ls_red_warp=get('ls_red_warp', 0.001),
                      ls_on=get('ls_on', 0.99999),
                      ls_min=get('ls_min', 1e-5),
                      give_up_warp=get('give_up_warp', False),
                      check=get('check', 0),
                      delta=get('delta', 1e-6),
                      is_plot=get('is_plot', False),
                      problem=get('problem', 'nonlinear'),
                      log=log,
                      is_any_log=is_any_log) + common

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None

    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.problem == 'linear'` means a pre-assembled and possibly
          pre-solved matrix. This is mostly useful for linear time-dependent
          problems.
        """
        import sfepy.base.plotutils as plu
        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

        time_stats = {}

        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
        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:
                tt = time.clock()

                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['rezidual'] = time.clock() - tt
                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(  'rezidual 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

            tt = time.clock()
            if conf.problem == 'nonlinear':
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad( 'linear' )

            time_stats['matrix'] = time.clock() - tt

            if conf.check:
                tt = time.clock()
                wt = check_tangent_matrix( conf, vec_x, fun, fun_grad )
                time_stats['check'] = time.clock() - tt - 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...')

            tt = time.clock()
            vec_dx = lin_solver(vec_r, x0=vec_x,
                                eps_a=eps_a, eps_r=eps_r, mtx=mtx_a)
            time_stats['solve'] = time.clock() - tt

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

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

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

            vec_x -= vec_dx

            if conf.is_plot:
                plu.plt.ion()
                plu.plt.gcf().clear()
                plu.plt.subplot( 2, 2, 1 )
                plu.plt.plot( vec_x_last )
                plu.plt.ylabel( r'$x_{i-1}$' )
                plu.plt.subplot( 2, 2, 2 )
                plu.plt.plot( vec_r )
                plu.plt.ylabel( r'$r$' )
                plu.plt.subplot( 2, 2, 4 )
                plu.plt.plot( vec_dx )
                plu.plt.ylabel( r'$\_delta x$' )
                plu.plt.subplot( 2, 2, 3 )
                plu.plt.plot( vec_x )
                plu.plt.ylabel( r'$x_i$' )
                plu.plt.draw()
                plu.plt.ioff()
                pause()

            it += 1

        if status is not None:
            status['time_stats'] = time_stats
            status['err0'] = err0
            status['err'] = err
            status['n_iter'] = it
            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
예제 #31
0
def solve_navier_stokes(conf, options):
    opts = conf.options

    dpb = ProblemDefinition.from_conf(conf, init_equations=False)
    equations = getattr(conf, '_'.join(('equations_direct', opts.problem)))
    dpb.set_equations(equations)

    ls_conf = dpb.get_solver_conf( opts.ls )
    nls_conf = dpb.get_solver_conf(opts.nls_direct)

    method = opts.direct_method
    if method == 'stationary':
        data = {}
        dpb.time_update(None)
        vec_dp = dpb.solve(nls_conf=nls_conf)

    elif method == 'transient':
        ls = Solver.any_from_conf( ls_conf )
        ts_conf = dpb.get_solver_conf( opts.ts_direct )

        data = {'ts' : Struct( dt = ts_conf.dt )}

        # Plug in mass term.
        mequations = {}
        for key, eq in equations.iteritems():
            if 'dw_div_grad' in eq:
                eq = '+'.join( (ts_conf.mass_term, eq) ).replace( '++', '+')
            mequations[key] = eq

        if ts_conf.stokes_init:
            vec_dp0 = solve_stokes( dpb, conf.equations_direct_stokes, nls_conf )
            dpb.set_equations( mequations )
        else:
            dpb.set_equations( mequations )
            vec_dp0 = dpb.create_state_vector()
            dpb.time_update( None )
            dpb.apply_ebc( vec_dp0 )

        from sfepy.base.log import Log

        log = Log.from_conf( Struct( is_plot = True ),
                            ([r'$||u||$'], [r'$||p||$']) )

        output( 'Navier-Stokes...' )
        ev = BasicEvaluator( dpb, ts = Struct( dt = ts_conf.dt ) )
        nls = Solver.any_from_conf( nls_conf, evaluator = ev, lin_solver = ls )

        n_step = ts_conf.n_step
        step = 0
        while 1:
            for ii in xrange( n_step ):
                output( step )

                vec_u = dpb.variables.get_state_part_view( vec_dp0, 'w' )
                vec_p = dpb.variables.get_state_part_view( vec_dp0, 'r' )
                log( nm.linalg.norm( vec_u ), nm.linalg.norm( vec_p ) )

                dpb.variables.non_state_data_from_state( 'w_0', vec_dp0, 'w' )
                vec_dp = nls( vec_dp0 )

                step += 1
                vec_dp0 = vec_dp.copy()

            if ts_conf.interactive:
                try:
                    n_step = int( raw_input( 'continue: ' ) )
                    if n_step <= 0: break
                except:
                    break

        vec_u = dpb.variables.get_state_part_view( vec_dp, 'w' )
        vec_p = dpb.variables.get_state_part_view( vec_dp, 'r' )
        log( nm.linalg.norm( vec_u ), nm.linalg.norm( vec_p ), finished = True )

    else:
        raise 'unknown Navier-Stokes solution method (%s)!'  % method
    
    return dpb, vec_dp, data
예제 #32
0
class FMinSteepestDescent(OptimizationSolver):
    name = 'opt.fmin_sd'

    @staticmethod
    def process_conf(conf, kwargs):
        """
        Missing items are set to default values.

        Example configuration, all items::

            solver_0 = {
                'name'      : 'fmin_sd',
                'kind'      : 'opt.fmin_sd',

                'i_max'      : 10,
                'eps_rd'     : 1e-5, # Relative delta of objective function
                'eps_of'     : 1e-4,
                'eps_ofg'    : 1e-8,
                'norm'      : nm.Inf,
                'ls'        : True, # Linesearch.
                'ls_method'  : 'backtracking', # 'backtracking' or 'full'
                'ls0'       : 0.25,
                'ls_red'     : 0.5,
                'ls_red_warp' : 0.1,
                'ls_on'      : 0.99999,
                'ls_min'     : 1e-5,
                'check'     : 0,
                'delta'     : 1e-6,
                'output'    : None, # 'itc'
                'log'       : {'text' : 'output/log.txt',
                               'plot' : 'output/log.png'},
                'yscales'   : ['linear', 'log', 'log', 'linear'],
            }
        """
        get = make_get_conf(conf, kwargs)
        common = OptimizationSolver.process_conf(conf)

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        return Struct(i_max=get('i_max', 10),
                      eps_rd=get('eps_rd', 1e-5),
                      eps_of=get('eps_of', 1e-4),
                      eps_ofg=get('eps_ofg', 1e-8),
                      norm=get('norm', nm.Inf),
                      ls=get('ls', True),
                      ls_method=get('ls_method', 'backtracking'),
                      ls0=get('ls0', 0.25),
                      ls_red=get('ls_red', 0.5),
                      ls_red_warp=get('ls_red_warp', 0.1),
                      ls_on=get('ls_on', 0.99999),
                      ls_min=get('ls_min', 1e-5),
                      check=get('check', 0),
                      delta=get('delta', 1e-6),
                      output=get('output', None),
                      yscales=get('yscales',
                                  ['linear', 'log', 'log', 'linear']),
                      log=log,
                      is_any_log=is_any_log) + common

    ##
    # 17.10.2007, c
    def __init__(self, conf, **kwargs):
        OptimizationSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log(
                [[r'$||\Psi||$'], [r'$||\nabla \Psi||$'], [r'$\alpha$'],
                 ['iteration']],
                xlabels=['', '', 'all iterations', 'all iterations'],
                yscales=conf.yscales,
                is_plot=conf.log.plot is not None,
                log_filename=conf.log.text,
                formats=[['%.8e'], ['%.3e'], ['%.3e'], ['%d']])
        else:
            self.log = None

    ##
    # 19.04.2006, c
    # 20.04.2006
    # 21.04.2006
    # 26.04.2006
    # 06.06.2006
    # 07.06.2006
    # 04.09.2006
    # 21.03.2007
    # 17.10.2007, from fmin_sd()
    def __call__(self,
                 x0,
                 conf=None,
                 obj_fun=None,
                 obj_fun_grad=None,
                 status=None,
                 obj_args=None):
        #    def fmin_sd( conf, x0, fn_of, fn_ofg, args = () ):

        conf = get_default(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)

        if conf.output:
            globals()['output'] = conf.output

        output('entering optimization loop...')

        nc_of, tt_of, fn_of = wrap_function(obj_fun, obj_args)
        nc_ofg, tt_ofg, fn_ofg = wrap_function(obj_fun_grad, obj_args)

        time_stats = {'of': tt_of, 'ofg': tt_ofg, 'check': []}

        ofg = None

        it = 0
        xit = x0.copy()
        while 1:

            of = fn_of(xit)

            if it == 0:
                of0 = ofit0 = of_prev = of
                of_prev_prev = of + 5000.0

            if ofg is None:
                ofg = fn_ofg(xit)

            if conf.check:
                tt = time.clock()
                check_gradient(xit, ofg, fn_of, conf.delta, conf.check)
                time_stats['check'].append(time.clock() - tt)

            ofg_norm = nla.norm(ofg, conf.norm)

            ret = conv_test(conf, it, of, ofit0, ofg_norm)
            if ret >= 0:
                break
            ofit0 = of

            ##
            # Backtrack (on errors).
            alpha = conf.ls0
            can_ls = True
            while 1:
                xit2 = xit - alpha * ofg
                aux = fn_of(xit2)

                if self.log is not None:
                    self.log(of, ofg_norm, alpha, it)

                if aux is None:
                    alpha *= conf.ls_red_warp
                    can_ls = False
                    output('warp: reducing step (%f)' % alpha)
                elif conf.ls and conf.ls_method == 'backtracking':
                    if aux < of * conf.ls_on: break
                    alpha *= conf.ls_red
                    output('backtracking: reducing step (%f)' % alpha)
                else:
                    of_prev_prev = of_prev
                    of_prev = aux
                    break

                if alpha < conf.ls_min:
                    if aux is None:
                        raise RuntimeError, 'giving up...'
                    output('linesearch failed, continuing anyway')
                    break

            # These values are modified by the line search, even if it fails
            of_prev_bak = of_prev
            of_prev_prev_bak = of_prev_prev

            if conf.ls and can_ls and conf.ls_method == 'full':
                output('full linesearch...')
                alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                       linesearch.line_search(fn_of,fn_ofg,xit,
                                              -ofg,ofg,of_prev,of_prev_prev,
                                              c2=0.4)
                if alpha is None:  # line search failed -- use different one.
                    alpha, fc, gc, of_prev, of_prev_prev, ofg1 = \
                           sopt.line_search(fn_of,fn_ofg,xit,
                                            -ofg,ofg,of_prev_bak,
                                            of_prev_prev_bak)
                    if alpha is None or alpha == 0:
                        # This line search also failed to find a better solution.
                        ret = 3
                        break
                output(' -> alpha: %.8e' % alpha)
            else:
                if conf.ls_method == 'full':
                    output('full linesearch off (%s and %s)' %
                           (conf.ls, can_ls))
                ofg1 = None

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

            xit = xit - alpha * ofg
            if ofg1 is None:
                ofg = None
            else:
                ofg = ofg1.copy()

            for key, val in time_stats.iteritems():
                if len(val):
                    output('%10s: %7.2f [s]' % (key, val[-1]))

            it = it + 1

        output('status:               %d' % ret)
        output('initial value:        %.8e' % of0)
        output('current value:        %.8e' % of)
        output('iterations:           %d' % it)
        output( 'function evaluations: %d in %.2f [s]' \
              % (nc_of[0], nm.sum( time_stats['of'] ) ) )
        output( 'gradient evaluations: %d in %.2f [s]' \
              % (nc_ofg[0], nm.sum( time_stats['ofg'] ) ) )

        if self.log is not None:
            self.log(of, ofg_norm, alpha, it)

            if conf.log.plot is not None:
                self.log(save_figure=conf.log.plot, finished=True)
            else:
                self.log(finished=True)

        if status is not None:
            status['log'] = self.log
            status['status'] = status
            status['of0'] = of0
            status['of'] = of
            status['it'] = it
            status['nc_of'] = nc_of[0]
            status['nc_ofg'] = nc_ofg[0]
            status['time_stats'] = time_stats

        return xit
예제 #33
0
    def solve_eigen_problem_n( self ):
        opts = self.app_options
        pb = self.problem

        dim = pb.domain.mesh.dim

        pb.set_equations( pb.conf.equations )
        pb.select_bcs( ebc_names = ['ZeroSurface'] )

        output( 'assembling rhs...' )
        tt = time.clock()
        mtx_b = pb.evaluate(pb.conf.equations['rhs'], mode='weak',
                            auto_init=True, dw_mode='matrix')
        output( '...done in %.2f s' % (time.clock() - tt) )
        assert_( nm.alltrue( nm.isfinite( mtx_b.data ) ) )

        ## mtx_b.save( 'b.txt', format='%d %d %.12f\n' )

        aux = pb.create_evaluable(pb.conf.equations['lhs'], mode='weak',
                                  dw_mode='matrix')
        mtx_a_equations, mtx_a_variables = aux

        if self.options.plot:
            log_conf = {
                'is_plot' : True,
                'aggregate' : 1,
                'yscales' : ['linear', 'log'],
            }
        else:
            log_conf = {
                'is_plot' : False,
            }
        log =  Log.from_conf( log_conf, ([r'$|F(x)|$'], [r'$|F(x)-x|$']) )

        file_output = Output('', opts.log_filename, combined = True)

        eig_conf = pb.get_solver_conf( opts.eigen_solver )
        eig_solver = Solver.any_from_conf( eig_conf )

        # Just to get the shape. Assumes one element group only!!!
        v_hxc_qp = pb.evaluate('dq_state_in_volume_qp.i1.Omega(Psi)')
        v_hxc_qp.fill(0.0)
        self.qp_shape = v_hxc_qp.shape
        vec_v_hxc = self._interp_to_nodes(v_hxc_qp)

        self.norm_v_hxc0 = nla.norm(vec_v_hxc)
        self.itercount = 0
        aux = wrap_function(self.iterate,
                            (eig_solver,
                             mtx_a_equations, mtx_a_variables,
                             mtx_b, log, file_output))
        ncalls, times, nonlin_v, results = aux

        # Create and call the DFT solver.
        dft_conf = pb.get_solver_conf(opts.dft_solver)
        dft_status = {}
        dft_solver = Solver.any_from_conf(dft_conf,
                                          fun = nonlin_v,
                                          status = dft_status)
        v_hxc_qp = dft_solver(v_hxc_qp.ravel())

        v_hxc_qp = nm.array(v_hxc_qp, dtype=nm.float64)
        v_hxc_qp.shape = self.qp_shape
        eigs, mtx_s_phi, vec_n, vec_v_h, v_ion_qp, v_xc_qp, v_hxc_qp = results
        output( 'DFT iteration time [s]:', dft_status['time_stats'] )

        fun = pb.materials['mat_v'].function
        variable = self.problem.create_variables(['scalar'])['scalar']
        vec_v_ion = fun(None, variable.field.get_coor(),
                        mode='qp')['V_ion'].squeeze()

        vec_v_xc = self._interp_to_nodes(v_xc_qp)
        vec_v_hxc = self._interp_to_nodes(v_hxc_qp)
        vec_v_sum = self._interp_to_nodes(v_hxc_qp + v_ion_qp)

        coor = pb.domain.get_mesh_coors()
        r2 = norm_l2_along_axis(coor, squared=True)
        vec_nr2 = vec_n * r2

        pb.select_bcs( ebc_names = ['ZeroSurface'] )
        mtx_phi = self.make_full( mtx_s_phi )

        out = {}
        update_state_to_output(out, pb, vec_n, 'n')
        update_state_to_output(out, pb, vec_nr2, 'nr2')
        update_state_to_output(out, pb, vec_v_h, 'V_h')
        update_state_to_output(out, pb, vec_v_xc, 'V_xc')
        update_state_to_output(out, pb, vec_v_ion, 'V_ion')
        update_state_to_output(out, pb, vec_v_hxc, 'V_hxc')
        update_state_to_output(out, pb, vec_v_sum, 'V_sum')
        self.save_results(eigs, mtx_phi, out=out)

        if self.options.plot:
            log( save_figure = opts.iter_fig_name )
            pause()
            log(finished=True)

        return Struct( pb = pb, eigs = eigs, mtx_phi = mtx_phi,
                       vec_n = vec_n, vec_nr2 = vec_nr2,
                       vec_v_h = vec_v_h, vec_v_xc = vec_v_xc )
예제 #34
0
파일: oseen.py 프로젝트: LeiDai/sfepy
class Oseen(NonlinearSolver):
    name = 'nls.oseen'

    @staticmethod
    def process_conf(conf, kwargs):
        """
        Missing items are set to default values.

        Example configuration, all items::

            solver_1 = {
                'name' : 'oseen',
                'kind' : 'nls.oseen',

                'needs_problem_instance' : True,
                'stabil_mat' : 'stabil',

                'adimensionalize' : False,
                'check_navier_stokes_rezidual' : False,

                'i_max'      : 10,
                'eps_a'      : 1e-8,
                'eps_r'      : 1.0,
                'macheps'    : 1e-16,
                'lin_red'    : 1e-2, # Linear system error < (eps_a * lin_red).
                'log'        : {'text' : 'oseen_log.txt',
                                'plot' : 'oseen_log.png'},
            }
        """
        get = make_get_conf(conf, kwargs)
        common = NonlinearSolver.process_conf(conf)

        # Compulsory.
        needs_problem_instance = get('needs_problem_instance', True)
        if not needs_problem_instance:
            msg = 'set solver option "needs_problem_instance" to True!'
            raise ValueError(msg)

        stabil_mat = get('stabil_mat', None,
                         'missing "stabil_mat" in options!')

        # With defaults.
        adimensionalize = get('adimensionalize', False)
        if adimensionalize:
            raise NotImplementedError

        check = get('check_navier_stokes_rezidual', False)

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        return Struct(needs_problem_instance=needs_problem_instance,
                      stabil_mat=stabil_mat,
                      adimensionalize=adimensionalize,
                      check_navier_stokes_rezidual=check,
                      i_max=get('i_max', 1),
                      eps_a=get('eps_a', 1e-10),
                      eps_r=get('eps_r', 1.0),
                      macheps=get('macheps',
                                  nm.finfo(nm.float64).eps),
                      lin_red=get('lin_red', 1.0),
                      lin_precision=get('lin_precision', None),
                      log=log,
                      is_any_log=is_any_log) + common

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__(self, conf, **kwargs)

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration'],
                            [r'$\gamma$', r'$\max(\delta)$', r'$\max(\tau)$']],
                           xlabels=['', '', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration', 'stabilization'],
                           yscales=['log', 'linear', 'log'],
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d'], ['%.8e', '%.8e',
                                                       '%.8e']])

        else:
            self.log = None

    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, self.problem)

        if problem is None:
            msg = 'set solver option "needs_problem_instance" to True!'
            raise ValueError(msg)

        time_stats = {}

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

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

        print 'problem size:'
        print '    velocity: %s' % ii['us']
        print '    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)
            print '|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)
            print '|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()))
            print 'stabilization parameters:'
            print '                   gamma: %.12e' % max_pars[ns['gamma']]
            print '            max( delta ): %.12e' % max_pars[ns['delta']]
            print '              max( tau ): %.12e' % max_pars[ns['tau']]

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

            tt = time.clock()
            try:
                vec_r = fun(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['rezidual'] = time.clock() - tt
            if ok:
                err = nla.norm(vec_r)
                if it == 0:
                    err0 = err
                else:
                    err += nla.norm(vec_dx)
            else:  # Failure.
                output('rezidual 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

            tt = time.clock()
            try:
                mtx_a = fun_grad(vec_x)
            except ValueError:
                ok = False
            else:
                ok = True
            time_stats['matrix'] = time.clock() - tt
            if not ok:
                raise RuntimeError('giving up...')

            tt = time.clock()
            vec_dx = lin_solver(vec_r, x0=vec_x, mtx=mtx_a)
            time_stats['solve'] = time.clock() - tt

            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 time_stats.iteritems():
                output('%10s: %7.2f [s]' % kv)

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

        if conf.check_navier_stokes_rezidual:

            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:
                print 'Navier-Stokes rezidual computation failed!'
                err_ns = err_ns0 = None
            else:
                err_ns0 = nla.norm(vec_rns0)
                err_ns = nla.norm(vec_rns)
            print 'Navier-Stokes rezidual0: %.8e' % err_ns0
            print 'Navier-Stokes rezidual : %.8e' % err_ns
            print 'b - u: %.8e' % nla.norm(vec_b - vec_u)
            print 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
예제 #35
0
파일: nls.py 프로젝트: olivierverdier/sfepy
class Newton( NonlinearSolver ):
    name = 'nls.newton'

    def process_conf( conf ):
        """
        Missing items are set to default values for a linear problem.
        
        Example configuration, all items::
        
            solver_1 = {
                'name' : 'newton',
                'kind' : 'nls.newton',

                'i_max'      : 2,
                'eps_a'      : 1e-8,
                'eps_r'      : 1e-2,
                'macheps'   : 1e-16,
                'lin_red'    : 1e-2, # Linear system error < (eps_a * lin_red).
                'ls_red'     : 0.1,
                'ls_red_warp' : 0.001,
                'ls_on'      : 0.99999,
                'ls_min'     : 1e-5,
                'check'     : 0,
                'delta'     : 1e-6,
                'is_plot'    : False,
                'log'        : None,
                 # 'nonlinear' or 'linear' (ignore i_max)
                'problem'   : 'nonlinear',
            }
        """
        get = conf.get_default_attr

        i_max = get( 'i_max', 1 )
        eps_a = get( 'eps_a', 1e-10 )
        eps_r = get( 'eps_r', 1.0 )
        macheps = get( 'macheps', nm.finfo( nm.float64 ).eps )
        lin_red = get( 'lin_red', 1.0 )
        ls_red = get( 'ls_red', 0.1 )
        ls_red_warp = get( 'ls_red_warp', 0.001 )
        ls_on = get( 'ls_on', 0.99999 )
        ls_min = get( 'ls_min', 1e-5 )
        check = get( 'check', 0 )
        delta = get( 'delta', 1e-6)
        is_plot = get( 'is_plot', False )
        problem = get( 'problem', 'nonlinear' )

        log = get_logging_conf(conf)
        log = Struct(name='log_conf', **log)
        is_any_log = (log.text is not None) or (log.plot is not None)

        common = NonlinearSolver.process_conf( conf )
        return Struct( **locals() ) + common
    process_conf = staticmethod( process_conf )

    def __init__(self, conf, **kwargs):
        NonlinearSolver.__init__( self, conf, **kwargs )

        conf = self.conf
        if conf.is_any_log:
            self.log = Log([[r'$||r||$'], ['iteration']],
                           xlabels=['', 'all iterations'],
                           ylabels=[r'$||r||$', 'iteration'],
                           yscales=['log', 'linear'],
                           is_plot=conf.log.plot is not None,
                           log_filename=conf.log.text,
                           formats=[['%.8e'], ['%d']])

        else:
            self.log = None

    ##
    # c: 02.12.2005, r: 04.04.2008
    # 10.10.2007, from newton()
    def __call__( self, vec_x0, conf = None, fun = None, fun_grad = None,
                  lin_solver = None, status = None ):
        """setting conf.problem == 'linear' means 1 iteration and no rezidual
        check!
        """
        import sfepy.base.plotutils as plu
        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 )

        time_stats = {}

        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)

        err0 = -1.0
        err_last = -1.0
        it = 0
        while 1:

            ls = 1.0
            vec_dx0 = vec_dx;
            while 1:
                tt = time.clock()

                try:
                    vec_r = fun( vec_x )

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

                else:
                    ok = True

                time_stats['rezidual'] = time.clock() - tt
                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.
                    red = conf.ls_red_warp;
                    output(  'rezidual 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

            tt = time.clock()
            if conf.problem == 'nonlinear':
                mtx_a = fun_grad(vec_x)

            else:
                mtx_a = fun_grad( 'linear' )

            time_stats['matrix'] = time.clock() - tt

            if conf.check:
                tt = time.clock()
                wt = check_tangent_matrix( conf, vec_x, fun, fun_grad )
                time_stats['check'] = time.clock() - tt - wt

            tt = time.clock()
            vec_dx = lin_solver( vec_r, mtx = mtx_a )
            time_stats['solve'] = time.clock() - tt

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

            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 )

            vec_x -= vec_dx

            if conf.is_plot:
                plu.pylab.ion()
                plu.pylab.gcf().clear()
                plu.pylab.subplot( 2, 2, 1 )
                plu.pylab.plot( vec_x_last )
                plu.pylab.ylabel( r'$x_{i-1}$' )
                plu.pylab.subplot( 2, 2, 2 )
                plu.pylab.plot( vec_r )
                plu.pylab.ylabel( r'$r$' )
                plu.pylab.subplot( 2, 2, 4 )
                plu.pylab.plot( vec_dx )
                plu.pylab.ylabel( r'$\_delta x$' )
                plu.pylab.subplot( 2, 2, 3 )
                plu.pylab.plot( vec_x )
                plu.pylab.ylabel( r'$x_i$' )
                plu.pylab.draw()
                plu.pylab.ioff()
                pause()

            it += 1

        if status is not None:
            status['time_stats'] = time_stats
            status['err0'] = err0
            status['err'] = err
            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
예제 #36
0
def main():
    # Aluminium and epoxy.
    default_pars = '70e9,0.35,2.799e3, 3.8e9,0.27,1.142e3'
    default_solver_conf = ("kind='eig.scipy',method='eigsh',tol=1.0e-5,"
                           "maxiter=1000,which='LM',sigma=0.0")

    parser = ArgumentParser(description=__doc__,
                            formatter_class=RawDescriptionHelpFormatter)
    parser.add_argument('--pars', metavar='young1,poisson1,density1'
                        ',young2,poisson2,density2',
                        action='store', dest='pars',
                        default=default_pars, help=helps['pars'])
    parser.add_argument('--conf', metavar='filename',
                        action='store', dest='conf',
                        default=None, help=helps['conf'])
    parser.add_argument('--define-kwargs', metavar='dict-like',
                        action='store', dest='define_kwargs',
                        default=None, help=helps['define_kwargs'])
    parser.add_argument('--mesh-size', type=float, metavar='float',
                        action='store', dest='mesh_size',
                        default=None, help=helps['mesh_size'])
    parser.add_argument('--unit-multipliers',
                        metavar='c_time,c_length,c_mass',
                        action='store', dest='unit_multipliers',
                        default='1.0,1.0,1.0', help=helps['unit_multipliers'])
    parser.add_argument('--plane', action='store', dest='plane',
                        choices=['strain', 'stress'],
                        default='strain', help=helps['plane'])
    parser.add_argument('--wave-dir', metavar='float,float[,float]',
                        action='store', dest='wave_dir',
                        default='1.0,0.0,0.0', help=helps['wave_dir'])
    parser.add_argument('--mode', action='store', dest='mode',
                        choices=['omega', 'kappa'],
                        default='omega', help=helps['mode'])
    parser.add_argument('--stepper', action='store', dest='stepper',
                        choices=['linear', 'brillouin'],
                        default='linear', help=helps['stepper'])
    parser.add_argument('--range', metavar='start,stop,count',
                        action='store', dest='range',
                        default='0,6.4,33', help=helps['range'])
    parser.add_argument('--order', metavar='int', type=int,
                        action='store', dest='order',
                        default=1, help=helps['order'])
    parser.add_argument('--refine', metavar='int', type=int,
                        action='store', dest='refine',
                        default=0, help=helps['refine'])
    parser.add_argument('-n', '--n-eigs', metavar='int', type=int,
                        action='store', dest='n_eigs',
                        default=6, help=helps['n_eigs'])
    group = parser.add_mutually_exclusive_group()
    group.add_argument('--eigs-only',
                       action='store_true', dest='eigs_only',
                       default=False, help=helps['eigs_only'])
    group.add_argument('--post-process',
                       action='store_true', dest='post_process',
                       default=False, help=helps['post_process'])
    parser.add_argument('--solver-conf', metavar='dict-like',
                        action='store', dest='solver_conf',
                        default=default_solver_conf, help=helps['solver_conf'])
    parser.add_argument('--save-regions',
                        action='store_true', dest='save_regions',
                        default=False, help=helps['save_regions'])
    parser.add_argument('--save-materials',
                        action='store_true', dest='save_materials',
                        default=False, help=helps['save_materials'])
    parser.add_argument('--log-std-waves',
                        action='store_true', dest='log_std_waves',
                        default=False, help=helps['log_std_waves'])
    parser.add_argument('--no-legends',
                        action='store_false', dest='show_legends',
                        default=True, help=helps['no_legends'])
    parser.add_argument('--no-show',
                        action='store_false', dest='show',
                        default=True, help=helps['no_show'])
    parser.add_argument('--silent',
                        action='store_true', dest='silent',
                        default=False, help=helps['silent'])
    parser.add_argument('-c', '--clear',
                        action='store_true', dest='clear',
                        default=False, help=helps['clear'])
    parser.add_argument('-o', '--output-dir', metavar='path',
                        action='store', dest='output_dir',
                        default='output', help=helps['output_dir'])
    parser.add_argument('mesh_filename', default='',
                        help=helps['mesh_filename'])
    options = parser.parse_args()

    output_dir = options.output_dir

    output.set_output(filename=os.path.join(output_dir,'output_log.txt'),
                      combined=options.silent == False)

    if options.conf is not None:
        mod = import_file(options.conf)

    else:
        mod = sys.modules[__name__]

    apply_units = mod.apply_units
    define = mod.define
    set_wave_dir = mod.set_wave_dir
    setup_n_eigs = mod.setup_n_eigs
    build_evp_matrices = mod.build_evp_matrices
    save_materials = mod.save_materials
    get_std_wave_fun = mod.get_std_wave_fun
    get_stepper = mod.get_stepper
    process_evp_results = mod.process_evp_results

    options.pars = [float(ii) for ii in options.pars.split(',')]
    options.unit_multipliers = [float(ii)
                                for ii in options.unit_multipliers.split(',')]
    options.wave_dir = [float(ii)
                        for ii in options.wave_dir.split(',')]
    aux = options.range.split(',')
    options.range = [float(aux[0]), float(aux[1]), int(aux[2])]
    options.solver_conf = dict_from_string(options.solver_conf)
    options.define_kwargs = dict_from_string(options.define_kwargs)

    if options.clear:
        remove_files_patterns(output_dir,
                              ['*.h5', '*.vtk', '*.txt'],
                              ignores=['output_log.txt'],
                              verbose=True)

    filename = os.path.join(output_dir, 'options.txt')
    ensure_path(filename)
    save_options(filename, [('options', vars(options))],
                 quote_command_line=True)

    pars = apply_units(options.pars, options.unit_multipliers)
    output('material parameters with applied unit multipliers:')
    output(pars)

    if options.mode == 'omega':
        rng = copy(options.range)
        rng[:2] = apply_unit_multipliers(options.range[:2],
                                         ['wave_number', 'wave_number'],
                                         options.unit_multipliers)
        output('wave number range with applied unit multipliers:', rng)

    else:
        if options.stepper == 'brillouin':
            raise ValueError('Cannot use "brillouin" stepper in kappa mode!')

        rng = copy(options.range)
        rng[:2] = apply_unit_multipliers(options.range[:2],
                                         ['frequency', 'frequency'],
                                         options.unit_multipliers)
        output('frequency range with applied unit multipliers:', rng)

    pb, wdir, bzone, mtxs = assemble_matrices(define, mod, pars, set_wave_dir,
                                              options)
    dim = pb.domain.shape.dim

    if dim != 2:
        options.plane = 'strain'

    if options.save_regions:
        pb.save_regions_as_groups(os.path.join(output_dir, 'regions'))

    if options.save_materials:
        save_materials(output_dir, pb, options)

    conf = pb.solver_confs['eig']
    eig_solver = Solver.any_from_conf(conf)

    n_eigs, options.n_eigs = setup_n_eigs(options, pb, mtxs)

    get_color = lambda ii: plt.cm.viridis((float(ii) / (options.n_eigs - 1)))
    plot_kwargs = [{'color' : get_color(ii), 'ls' : '', 'marker' : 'o'}
                  for ii in range(options.n_eigs)]
    get_color_dim = lambda ii: plt.cm.viridis((float(ii) / (dim-1)))
    plot_kwargs_dim = [{'color' : get_color_dim(ii), 'ls' : '', 'marker' : 'o'}
                       for ii in range(dim)]

    log_names = []
    log_plot_kwargs = []
    if options.log_std_waves:
        std_wave_fun, log_names, log_plot_kwargs = get_std_wave_fun(
            pb, options)

    else:
        std_wave_fun = None

    stepper = get_stepper(rng, pb, options)

    if options.mode == 'omega':
        eigenshapes_filename = os.path.join(output_dir,
                                            'frequency-eigenshapes-%s.vtk'
                                            % stepper.suffix)

        if options.stepper == 'linear':
            log = Log([[r'$\lambda_{%d}$' % ii for ii in range(options.n_eigs)],
                   [r'$\omega_{%d}$'
                    % ii for ii in range(options.n_eigs)] + log_names],
                  plot_kwargs=[plot_kwargs, plot_kwargs + log_plot_kwargs],
                  formats=[['{:.5e}'] * options.n_eigs,
                           ['{:.5e}'] * (options.n_eigs + len(log_names))],
                  yscales=['linear', 'linear'],
                  xlabels=[r'$\kappa$', r'$\kappa$'],
                  ylabels=[r'eigenvalues $\lambda_i$',
                           r'frequencies $\omega_i$'],
                  show_legends=options.show_legends,
                  is_plot=options.show,
                  log_filename=os.path.join(output_dir, 'frequencies.txt'),
                  aggregate=1000, sleep=0.1)

        else:
            log = Log([[r'$\kappa_{%d}$'% ii for ii in range(dim)],
                       [r'$\omega_{%d}$'
                        % ii for ii in range(options.n_eigs)] + log_names],
                      plot_kwargs=[plot_kwargs_dim,
                                   plot_kwargs + log_plot_kwargs],
                      formats=[['{:.5e}'] * dim,
                               ['{:.5e}'] * (options.n_eigs + len(log_names))],
                      yscales=['linear', 'linear'],
                      xlabels=[r'', r''],
                      ylabels=[r'wave vector $\kappa$',
                               r'frequencies $\omega_i$'],
                      show_legends=options.show_legends,
                      is_plot=options.show,
                      log_filename=os.path.join(output_dir, 'frequencies.txt'),
                      aggregate=1000, sleep=0.1)

        for aux in stepper:
            if options.stepper == 'linear':
                iv, wmag = aux

            else:
                iv, wmag, wdir = aux

            output('step %d: wave vector %s' % (iv, wmag * wdir))

            if options.stepper == 'brillouin':
                pb, _, bzone, mtxs = assemble_matrices(
                    define, mod, pars, set_wave_dir, options, wdir=wdir)

            evp_mtxs = build_evp_matrices(mtxs, wmag, options.mode, pb)

            if options.eigs_only:
                eigs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
                                  eigenvectors=False)
                svecs = None

            else:
                eigs, svecs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
                                         eigenvectors=True)

            omegas, svecs, out = process_evp_results(
                eigs, svecs, wmag, wdir, bzone, pb, mtxs, options,
                std_wave_fun=std_wave_fun
            )
            if options.stepper == 'linear':
                log(*out, x=[wmag, wmag])

            else:
                log(*out, x=[iv, iv])

            save_eigenvectors(eigenshapes_filename % iv, svecs, wmag, wdir, pb)

            gc.collect()

        log(save_figure=os.path.join(output_dir, 'frequencies.png'))
        log(finished=True)

    else:
        eigenshapes_filename = os.path.join(output_dir,
                                            'wave-number-eigenshapes-%s.vtk'
                                            % stepper.suffix)

        log = Log([[r'$\kappa_{%d}$' % ii for ii in range(options.n_eigs)]
                   + log_names],
                  plot_kwargs=[plot_kwargs + log_plot_kwargs],
                  formats=[['{:.5e}'] * (options.n_eigs + len(log_names))],
                  yscales=['linear'],
                  xlabels=[r'$\omega$'],
                  ylabels=[r'wave numbers $\kappa_i$'],
                  show_legends=options.show_legends,
                  is_plot=options.show,
                  log_filename=os.path.join(output_dir, 'wave-numbers.txt'),
                  aggregate=1000, sleep=0.1)
        for io, omega in stepper:
            output('step %d: frequency %s' % (io, omega))

            evp_mtxs = build_evp_matrices(mtxs, omega, options.mode, pb)

            if options.eigs_only:
                eigs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
                                  eigenvectors=False)
                svecs = None

            else:
                eigs, svecs = eig_solver(*evp_mtxs, n_eigs=n_eigs,
                                         eigenvectors=True)

            kappas, svecs, out = process_evp_results(
                eigs, svecs, omega, wdir, bzone, pb, mtxs, options,
                std_wave_fun=std_wave_fun
            )
            log(*out, x=[omega])

            save_eigenvectors(eigenshapes_filename % io, svecs, kappas, wdir,
                              pb)

            gc.collect()

        log(save_figure=os.path.join(output_dir, 'wave-numbers.png'))
        log(finished=True)
예제 #37
0
파일: optimize.py 프로젝트: certik/sfepy
    def __call__(self, x0, conf=None, obj_fun=None, obj_fun_grad=None, status=None, obj_args=None):
        #    def fmin_sd( conf, x0, fn_of, fn_ofg, args = () ):

        conf = get_default(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)

        if conf.output:
            globals()["output"] = conf.output

        output("entering optimization loop...")

        nc_of, tt_of, fn_of = wrap_function(obj_fun, obj_args)
        nc_ofg, tt_ofg, fn_ofg = wrap_function(obj_fun_grad, obj_args)

        time_stats = {"of": tt_of, "ofg": tt_ofg, "check": []}

        if conf.log:
            log = Log.from_conf(conf, ([r"of"], [r"$||$ofg$||$"], [r"alpha"]))
        else:
            log = None

        ofg = None

        it = 0
        xit = x0.copy()
        while 1:

            of = fn_of(xit)

            if it == 0:
                of0 = ofit0 = of_prev = of
                of_prev_prev = of + 5000.0

            if ofg is None:
                #            ofg = 1
                ofg = fn_ofg(xit)

            if conf.check:
                tt = time.clock()
                check_gradient(xit, ofg, fn_of, conf.delta, conf.check)
                time_stats["check"].append(time.clock() - tt)

            ofg_norm = nla.norm(ofg, conf.norm)

            ret = conv_test(conf, it, of, ofit0, ofg_norm)
            if ret >= 0:
                break
            ofit0 = of

            ##
            # Backtrack (on errors).
            alpha = conf.ls0
            can_ls = True
            while 1:
                xit2 = xit - alpha * ofg
                aux = fn_of(xit2)
                if aux is None:
                    alpha *= conf.ls_red_warp
                    can_ls = False
                    output("warp: reducing step (%f)" % alpha)
                elif conf.ls and conf.ls_method == "backtracking":
                    if aux < of * conf.ls_on:
                        break
                    alpha *= conf.ls_red
                    output("backtracking: reducing step (%f)" % alpha)
                else:
                    of_prev_prev = of_prev
                    of_prev = aux
                    break

                if alpha < conf.ls_min:
                    if aux is None:
                        raise RuntimeError, "giving up..."
                    output("linesearch failed, continuing anyway")
                    break

            # These values are modified by the line search, even if it fails
            of_prev_bak = of_prev
            of_prev_prev_bak = of_prev_prev

            if conf.ls and can_ls and conf.ls_method == "full":
                output("full linesearch...")
                alpha, fc, gc, of_prev, of_prev_prev, ofg1 = linesearch.line_search(
                    fn_of, fn_ofg, xit, -ofg, ofg, of_prev, of_prev_prev, c2=0.4
                )
                if alpha is None:  # line search failed -- use different one.
                    alpha, fc, gc, of_prev, of_prev_prev, ofg1 = sopt.line_search(
                        fn_of, fn_ofg, xit, -ofg, ofg, of_prev_bak, of_prev_prev_bak
                    )
                    if alpha is None or alpha == 0:
                        # This line search also failed to find a better solution.
                        ret = 3
                        break
                output(" -> alpha: %.8e" % alpha)
            else:
                if conf.ls_method == "full":
                    output("full linesearch off (%s and %s)" % (conf.ls, can_ls))
                ofg1 = None

            if conf.log:
                log(of, ofg_norm, alpha)

            xit = xit - alpha * ofg
            if ofg1 is None:
                ofg = None
            else:
                ofg = ofg1.copy()

            for key, val in time_stats.iteritems():
                if len(val):
                    output("%10s: %7.2f [s]" % (key, val[-1]))

            it = it + 1

        output("status:               %d" % ret)
        output("initial value:        %.8e" % of0)
        output("current value:        %.8e" % of)
        output("iterations:           %d" % it)
        output("function evaluations: %d in %.2f [s]" % (nc_of[0], nm.sum(time_stats["of"])))
        output("gradient evaluations: %d in %.2f [s]" % (nc_ofg[0], nm.sum(time_stats["ofg"])))

        if conf.log:
            log(of, ofg_norm, alpha, finished=True)

        if status is not None:
            status["log"] = log
            status["status"] = status
            status["of0"] = of0
            status["of"] = of
            status["it"] = it
            status["nc_of"] = nc_of[0]
            status["nc_ofg"] = nc_ofg[0]
            status["time_stats"] = time_stats

        return xit