def vary_omega1_size(problem): """Vary size of \Omega1. Saves also the regions into options['output_dir']. Input: problem: ProblemDefinition instance Return: a generator object: 1. creates new (modified) problem 2. yields the new (modified) problem and output container 3. use the output container for some logging 4. yields None (to signal next iteration to Application) """ from sfepy.fem import ProblemDefinition from sfepy.solvers.ts import get_print_info output.prefix = 'vary_omega1_size:' diameters = nm.linspace(0.1, 0.6, 7) + 0.001 ofn_trunk, output_format = problem.ofn_trunk, problem.output_format output_dir = problem.output_dir join = os.path.join conf = problem.conf cf = conf.get_raw('functions') n_digit, aux, d_format = get_print_info(len(diameters) + 1) for ii, diameter in enumerate(diameters): output('iteration %d: diameter %3.2f' % (ii, diameter)) cf['select_circ'] = (lambda coors, domain=None: select_circ( coors[:, 0], coors[:, 1], 0, diameter), ) conf.edit('functions', cf) problem = ProblemDefinition.from_conf(conf) problem.save_regions(join(output_dir, ('regions_' + d_format) % ii), ['Omega_1']) region = problem.domain.regions['Omega_1'] if not region.has_cells_if_can(): print region raise ValueError('region %s has no cells!' % region.name) ofn_trunk = ofn_trunk + '_' + (d_format % ii) problem.setup_output(output_filename_trunk=ofn_trunk, output_dir=output_dir, output_format=output_format) out = [] yield problem, out out_problem, state = out[-1] filename = join(output_dir, ('log_%s.txt' % d_format) % ii) fd = open(filename, 'w') log_item = '$r(\Omega_1)$: %f\n' % diameter fd.write(log_item) fd.write('solution:\n') nm.savetxt(fd, state()) fd.close() yield None
def vary_omega1_size( problem ): """Vary size of \Omega1. Saves also the regions into options['output_dir']. Input: problem: ProblemDefinition instance Return: a generator object: 1. creates new (modified) problem 2. yields the new (modified) problem and output container 3. use the output container for some logging 4. yields None (to signal next iteration to Application) """ from sfepy.fem import ProblemDefinition from sfepy.solvers.ts import get_print_info output.prefix = 'vary_omega1_size:' diameters = nm.linspace( 0.1, 0.6, 7 ) + 0.001 ofn_trunk, output_format = problem.ofn_trunk, problem.output_format output_dir = problem.output_dir join = os.path.join conf = problem.conf cf = conf.get_raw( 'functions' ) n_digit, aux, d_format = get_print_info( len( diameters ) + 1 ) for ii, diameter in enumerate( diameters ): output( 'iteration %d: diameter %3.2f' % (ii, diameter) ) cf['select_circ'] = (lambda coors, domain=None: select_circ(coors[:,0], coors[:,1], 0, diameter),) conf.edit('functions', cf) problem = ProblemDefinition.from_conf( conf ) problem.save_regions( join( output_dir, ('regions_' + d_format) % ii ), ['Omega_1'] ) region = problem.domain.regions['Omega_1'] if not region.has_cells_if_can(): print region raise ValueError( 'region %s has no cells!' % region.name ) ofn_trunk = ofn_trunk + '_' + (d_format % ii) problem.setup_output(output_filename_trunk=ofn_trunk, output_dir=output_dir, output_format=output_format) out = [] yield problem, out out_problem, state = out[-1] filename = join( output_dir, ('log_%s.txt' % d_format) % ii ) fd = open( filename, 'w' ) log_item = '$r(\Omega_1)$: %f\n' % diameter fd.write( log_item ) fd.write( 'solution:\n' ) nm.savetxt(fd, state()) fd.close() yield None
def from_conf( conf, options ): from sfepy.fem import ProblemDefinition problem = ProblemDefinition.from_conf(conf, init_equations=False) test = Test( problem = problem, conf = conf, options = options ) return test
def from_conf( conf, options ): from sfepy.fem import ProblemDefinition problem = ProblemDefinition.from_conf( conf ) test = Test( problem = problem, conf = conf, options = options ) return test
def main(): from sfepy.base.base import output from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import ProblemDefinition from sfepy.applications import solve_evolutionary output.prefix = 'therel:' required, other = get_standard_keywords() conf = ProblemConf.from_file(__file__, required, other) problem = ProblemDefinition.from_conf(conf, init_equations=False) # Setup output directory according to options above. problem.setup_default_output() # First solve the stationary electric conduction problem. problem.set_equations({'eq' : conf.equations['1']}) problem.time_update() state_el = problem.solve() problem.save_state(problem.get_output_name(suffix = 'el'), state_el) # Then solve the evolutionary heat conduction problem, using state_el. problem.set_equations({'eq' : conf.equations['2']}) phi_var = problem.get_variables()['phi_known'] phi_var.data_from_any(state_el()) solve_evolutionary(problem) output('results saved in %s' % problem.get_output_name(suffix = '*'))
def save_only( conf, save_names, problem = None ): """Save information available prior to setting equations and solving them.""" if problem is None: problem = ProblemDefinition.from_conf( conf, init_variables = False ) if save_names.regions is not None: problem.save_regions( save_names.regions ) if save_names.field_meshes is not None: problem.save_field_meshes( save_names.field_meshes ) if save_names.region_field_meshes is not None: problem.save_region_field_meshes( save_names.region_field_meshes ) if save_names.ebc is not None: if not hasattr( problem, 'variables' ): problem.set_variables( conf.variables ) try: ts = TimeStepper.from_conf( conf.ts ) ts.set_step( 0 ) except: ts = None try: problem.variables.equation_mapping( conf.ebcs, conf.epbcs, problem.domain.regions, ts, conf.funmod ) except Exception, e: output( 'cannot make equation mapping!' ) output( 'reason: %s' % e ) else: problem.save_ebc( save_names.ebc )
def main(): from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import ProblemDefinition from sfepy.base.plotutils import plt parser = OptionParser(usage=usage, version='%prog') parser.add_option('-n', '--no-plot', action="store_true", dest='no_plot', default=False, help=helps['no_plot']) options, args = parser.parse_args() required, other = get_standard_keywords() # Use this file as the input file. conf = ProblemConf.from_file( __file__, required, other ) # Create problem instance, but do not set equations. problem = ProblemDefinition.from_conf( conf, init_equations = False ) # Solve the problem. Output is ignored, results stored by using the # step_hook. u_t = solve_branch(problem, linear_tension) u_c = solve_branch(problem, linear_compression) # Get pressure load by calling linear_*() for each time step. ts = problem.get_timestepper() load_t = nm.array([linear_tension(ts, nm.array([[0.0]]), 'qp')['val'] for aux in ts.iter_from( 0 )], dtype=nm.float64).squeeze() load_c = nm.array([linear_compression(ts, nm.array([[0.0]]), 'qp')['val'] for aux in ts.iter_from( 0 )], dtype=nm.float64).squeeze() # Join the branches. displacements = {} for key in u_t.keys(): displacements[key] = nm.r_[u_c[key][::-1], u_t[key]] load = nm.r_[load_c[::-1], load_t] if plt is None: print 'matplotlib cannot be imported, printing raw data!' print displacements print load else: legend = [] for key, val in displacements.iteritems(): plt.plot( load, val ) legend.append( key ) plt.legend( legend, loc = 2 ) plt.xlabel( 'tension [kPa]' ) plt.ylabel( 'displacement [mm]' ) plt.grid( True ) plt.gcf().savefig( 'pressure_displacement.png' ) if not options.no_plot: plt.show()
def from_conf(conf, options): from sfepy.fem import ProblemDefinition problem = ProblemDefinition.from_conf(conf) problem.time_update() test = Test(problem=problem, conf=conf, options=options) return test
def solve_direct(conf, options, problem=None, step_hook=None, post_process_hook=None, post_process_hook_final=None, pre_process_hook=None, nls_status=None): """Generic (simple) problem solver.""" if problem is None: is_eqs = not options.solve_not problem = ProblemDefinition.from_conf(conf, init_equations=is_eqs) problem.setup_default_output(conf, options) if pre_process_hook is not None: # User pre_processing. pre_process_hook(problem) ofn_trunk = problem.ofn_trunk save_names = Struct( ebc = None, regions = None, regions_as_groups = None, field_meshes = None, region_field_meshes = None ) if options.save_ebc: save_names.ebc = ofn_trunk + '_ebc.vtk' if options.save_regions: save_names.regions = ofn_trunk + '_region' if options.save_regions_as_groups: save_names.regions_as_groups = ofn_trunk + '_regions' if options.save_field_meshes: save_names.field_meshes = ofn_trunk + '_field' is_extra_save = False for name, val in save_names.to_dict().iteritems(): if val is not None: is_extra_save = True break if is_extra_save: save_only( conf, save_names, problem=problem ) if options.solve_not: return None, None, None if hasattr( conf.options, 'ts' ): ## # Time-dependent problem. state = solve_evolutionary_op(problem, options, step_hook=step_hook, post_process_hook=post_process_hook, nls_status=nls_status) else: ## # Stationary problem. state = solve_stationary_op(problem, options, post_process_hook=post_process_hook, nls_status=nls_status) if post_process_hook_final is not None: # User postprocessing. post_process_hook_final(problem, state) return problem, state
def solve_stationary(conf, save_names=None, nls_status=None): problem = ProblemDefinition.from_conf( conf ) problem.time_update( None ) if save_names is not None: save_only( conf, save_names, problem = problem ) state = problem.solve( nls_status = nls_status ) return problem, state
def main(): from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import ProblemDefinition from sfepy.base.plotutils import pylab required, other = get_standard_keywords() # Use this file as the input file. conf = ProblemConf.from_file( __file__, required, other ) # Create problem instance, but do not set equations. problem = ProblemDefinition.from_conf( conf, init_equations = False ) options = Struct( output_filename_trunk = None ) # Solve the problem. Output is ignored, results stored by using the # step_hook. u_t = solve_branch( problem, options, linear_tension ) u_c = solve_branch( problem, options, linear_compression ) # Get pressure load by calling linear_*() for each time step. ts = problem.get_timestepper() load_t = nm.array( [linear_tension( ts, nm.array( [[0.0]] ) )['val'] for aux in ts.iter_from( 0 )], dtype = nm.float64 ).squeeze() load_c = nm.array( [linear_compression( ts, nm.array( [[0.0]] ) )['val'] for aux in ts.iter_from( 0 )], dtype = nm.float64 ).squeeze() # Join the branches. displacements = {} for key in u_t.keys(): displacements[key] = nm.r_[u_c[key][::-1], u_t[key]] load = nm.r_[load_c[::-1], load_t] if pylab is None: print 'pylab cannot be imported, printing raw data!' print displacements print load else: legend = [] for key, val in displacements.iteritems(): pylab.plot( load, val ) legend.append( key ) pylab.legend( legend, loc = 2 ) pylab.xlabel( 'tension [kPa]' ) pylab.ylabel( 'displacement [mm]' ) pylab.grid( True ) pylab.gcf().savefig( 'pressure_displacement.png' ) pylab.show()
def __init__(self, conf, options, output_prefix, init_equations=True, **kwargs): """`kwargs` are passed to ProblemDefinition.from_conf() Command-line options have precedence over conf.options.""" Application.__init__(self, conf, options, output_prefix) self.setup_options() is_eqs = init_equations if hasattr(options, "solve_not") and options.solve_not: is_eqs = False self.problem = ProblemDefinition.from_conf(conf, init_equations=is_eqs, **kwargs) self.setup_output_info(self.problem, self.options)
def vary_y3_size( problem ): """Vary size of Y3 inclusion.""" from sfepy.fem import ProblemDefinition from sfepy.solvers.ts import get_print_info default_printer.prefix = 'vary_y3_size:' y3_diameters = [0.2, 0.25, 0.3, 0.35, 0.4] if diameters_g is None: y3_diameters = nm.linspace( 0.15, 0.45, 16 ) else: y3_diameters = diameters_g # y3_diameters = [0.45] ofn_trunk, output_dir = problem.ofn_trunk, problem.output_dir join = os.path.join conf = problem.conf cr = conf.get_raw( 'regions' ) n_digit, aux, d_format = get_print_info( len( y3_diameters ) + 1 ) for ii, diameter in enumerate( y3_diameters ): output( 'iteration %d: diameter %3.2f' % (ii, diameter) ) opts = problem.conf.options cr['Y3'] = ('nodes by select_y3_circ( x, y, z, %.5f )' % diameter, {}) conf.edit( 'regions', cr ) problem = ProblemDefinition.from_conf( conf ) problem.save_regions( join( output_dir, ('regions_' + d_format) % ii ), ['Y2', 'Y3'] ) for region in problem.domain.regions: if not region.has_cells_if_can(): raise ValueError( 'region %s has no cells!' % region.name ) opts.plot_options['show'] = False opts.fig_name = join( output_dir, (('band_gaps_%s' % d_format) + '_y3_%03.2f' + fig_suffix) % (ii, diameter) ) problem.ofn_trunk = ofn_trunk + '_' + (d_format % ii) out = [] yield problem, out evp, bg = out[-1] filename = join( output_dir, ('band_gaps_%s.txt' % d_format) % ii ) log_item = '$r(Y_3)$: %f\n' % diameter save_log( filename, bg, log_item ) yield None
def solve_stationary( conf, data = None, save_names = None, nls_status = None ): if data is None: # Term-dependent data. data = {} problem = ProblemDefinition.from_conf( conf ) problem.time_update( None ) if save_names is not None: save_only( conf, save_names, problem = problem ) state = problem.solve( nls_status = nls_status ) return problem, state, data
def solve_direct( conf, options, problem = None, step_hook = None, post_process_hook = None ): """Generic (simple) problem solver.""" if problem is None: problem = ProblemDefinition.from_conf( conf ) if options.output_filename_trunk: ofn_trunk = options.output_filename_trunk problem.ofn_trunk = ofn_trunk if options.output_format: problem.output_format = options.output_format ofn_trunk = problem.ofn_trunk save_names = Struct( ebc = None, regions = None, field_meshes = None, region_field_meshes = None ) if options.save_ebc: save_names.ebc = ofn_trunk + '_ebc.vtk' if options.save_regions: save_names.regions = ofn_trunk + '_region' if options.save_field_meshes: save_names.field_meshes = ofn_trunk + '_field' if options.save_region_field_meshes: save_names.region_field_meshes = ofn_trunk + '_region_field' is_extra_save = False for name, val in save_names.to_dict().iteritems(): if val is not None: is_extra_save = True break if is_extra_save: save_only( conf, save_names ) if options.solve_not: return None, None, None if hasattr( conf.options, 'ts' ): ## # Time-dependent problem. out = solve_evolutionary_op( problem, options, post_process_hook = post_process_hook, step_hook = step_hook ) else: ## # Stationary problem. out = solve_stationary_op( problem, options, post_process_hook = post_process_hook ) state, data = out return problem, state, data
def __init__(self, conf, options, output_prefix, init_equations=True, **kwargs): """`kwargs` are passed to ProblemDefinition.from_conf() Command-line options have precedence over conf.options.""" Application.__init__( self, conf, options, output_prefix ) self.setup_options() is_eqs = init_equations if hasattr(options, 'solve_not') and options.solve_not: is_eqs = False self.problem = ProblemDefinition.from_conf(conf, init_equations=is_eqs, **kwargs) self.setup_output_info( self.problem, self.options )
def save_only( conf, save_names, problem = None ): """Save information available prior to setting equations and solving them.""" if problem is None: problem = ProblemDefinition.from_conf(conf, init_equations=False) if save_names.regions is not None: problem.save_regions( save_names.regions ) if save_names.regions_as_groups is not None: problem.save_regions_as_groups( save_names.regions_as_groups ) if save_names.field_meshes is not None: problem.save_field_meshes( save_names.field_meshes ) if save_names.ebc is not None: problem.save_ebc( save_names.ebc )
def vary_y3_size(problem): """Vary size of Y3 inclusion.""" from sfepy.fem import ProblemDefinition from sfepy.solvers.ts import get_print_info output.prefix = "vary_y3_size:" y3_diameters = [0.2, 0.25, 0.3, 0.35, 0.4] if diameters_g is None: y3_diameters = nm.linspace(0.15, 0.45, 16) else: y3_diameters = diameters_g # y3_diameters = [0.45] ofn_trunk, output_dir = problem.ofn_trunk, problem.output_dir join = os.path.join conf = problem.conf cr = conf.get_raw("regions") n_digit, aux, d_format = get_print_info(len(y3_diameters) + 1) for ii, diameter in enumerate(y3_diameters): output("iteration %d: diameter %3.2f" % (ii, diameter)) opts = problem.conf.options cr["Y3"] = ("nodes by select_y3_circ( x, y, z, %.5f )" % diameter, {}) conf.edit("regions", cr) problem = ProblemDefinition.from_conf(conf) problem.save_regions(join(output_dir, ("regions_" + d_format) % ii), ["Y2", "Y3"]) for region in problem.domain.regions: if not region.has_cells_if_can(): raise ValueError("region %s has no cells!" % region.name) opts.plot_options["show"] = False opts.fig_name = join(output_dir, (("band_gaps_%s" % d_format) + "_y3_%03.2f" + fig_suffix) % (ii, diameter)) problem.ofn_trunk = ofn_trunk + "_" + (d_format % ii) out = [] yield problem, out evp, bg = out[-1] filename = join(output_dir, ("band_gaps_%s.txt" % d_format) % ii) log_item = "$r(Y_3)$: %f\n" % diameter save_log(filename, bg, log_item) yield None
def __init__( self, conf, options, output_prefix, **kwargs ): """`kwargs` are passed to ProblemDefinition.from_conf() Command-line options have precedence over conf.options.""" Application.__init__( self, conf, options, output_prefix ) self.setup_options() if options.output_filename_trunk is None: ofn_trunk = op.join( self.app_options.output_dir, io.get_trunk( conf.filename_mesh ) ) options.output_filename_trunk = ofn_trunk else: ofn_trunk = options.output_filename_trunk self.problem = ProblemDefinition.from_conf( conf, **kwargs ) self.problem.ofn_trunk = ofn_trunk self.problem.output_dir = self.app_options.output_dir if hasattr( options, 'output_format' ): self.problem.output_format = options.output_format else: self.problem.output_format = self.app_options.output_format
def save_only(conf, save_names, problem=None): """ Save information available prior to setting equations and solving them. """ if problem is None: problem = ProblemDefinition.from_conf(conf, init_equations=False) if save_names.regions is not None: problem.save_regions(save_names.regions) if save_names.regions_as_groups is not None: problem.save_regions_as_groups(save_names.regions_as_groups) if save_names.field_meshes is not None: problem.save_field_meshes(save_names.field_meshes) if save_names.ebc is not None: problem.save_ebc(save_names.ebc, force=False) if save_names.ebc_nodes is not None: problem.save_ebc(save_names.ebc_nodes, force=True)
def eval_homogenized_coefs( self ): if self.cached_coefs is not None: return self.cached_coefs opts = self.app_options if opts.homogeneous: rtm = opts.region_to_material mat_region = rtm.keys()[0] mat_name = rtm[mat_region] self.problem.update_materials() mat = self.problem.materials[mat_name] coefs = mat.get_data( mat_region, 0, opts.tensor_names ) else: dc = opts.dispersion_conf dconf = ProblemConf.from_dict( dc['input'], dc['module'] ) dconf.materials = self.conf.materials dconf.fe = self.conf.fe dconf.regions.update( self.conf.regions ) dconf.options['output_dir'] = self.problem.output_dir volume = opts.volume(self.problem, 'Y') problem = ProblemDefinition.from_conf(dconf, init_equations=False) he = HomogenizationEngine( problem, self.options, volume = volume ) coefs = he() ## print coefs ## pause() output.prefix = self.output_prefix self.cached_coefs = coefs return coefs
def test_ebc(self): import numpy as nm from sfepy.fem import ProblemDefinition pb = ProblemDefinition.from_conf(self.test_conf) pb.time_update() vvs = pb.variables set = vvs.set_state_part make_full = vvs.make_full_vec svec_u = nm.ones((vvs.adi.n_dofs["u"],), dtype=nm.float64) svec_phi = nm.empty((vvs.adi.n_dofs["phi"],), dtype=nm.float64) svec_phi.fill(2.0) svec = vvs.create_stripped_state_vector() set(svec, svec_u, "u", stripped=True) set(svec, svec_phi, "phi", stripped=True) vec = make_full(svec) ii_u = vvs.di.indx["u"].start + vvs["u"].eq_map.eqi ii_phi = vvs.di.indx["phi"].start + vvs["phi"].eq_map.eqi ok_ebc = vvs.has_ebc(vec) ok_u = nm.all(vec[ii_u] == svec_u) ok_phi = nm.all(vec[ii_phi] == svec_phi) msg = "%s: %s" self.report(msg % ("ebc", ok_ebc)) self.report(msg % ("u", ok_u)) self.report(msg % ("phi", ok_phi)) ok = ok_ebc and ok_u and ok_phi return ok
def main(): import os from sfepy.base.base import spause, output from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import ProblemDefinition import sfepy.homogenization.coefs_base as cb parser = OptionParser(usage=usage, version='%prog') parser.add_option('-n', '--no-pauses', action="store_true", dest='no_pauses', default=False, help=help['no_pauses']) options, args = parser.parse_args() if options.no_pauses: def spause(*args): output(*args) nm.set_printoptions( precision = 3 ) spause( r""">>> First, this file will be read in place of an input (problem description) file. Press 'q' to quit the example, press any other key to continue...""" ) required, other = get_standard_keywords() required.remove( 'equations' ) # Use this file as the input file. conf = ProblemConf.from_file( __file__, required, other ) print conf.to_dict().keys() spause( r""">>> ...the read input as a dict (keys only for brevity). ['q'/other key to quit/continue...]""" ) spause( r""">>> Now the input will be used to create a ProblemDefinition instance. ['q'/other key to quit/continue...]""" ) problem = ProblemDefinition.from_conf(conf, init_equations=False) # The homogenization mini-apps need the output_dir. output_dir = os.path.join(os.path.split(__file__)[0], 'output') if not os.path.exists(output_dir): os.makedirs(output_dir) problem.output_dir = output_dir print problem spause( r""">>> ...the ProblemDefinition instance. ['q'/other key to quit/continue...]""" ) spause( r""">>> The homogenized elastic coefficient $E_{ijkl}$ is expressed using $\Pi$ operators, computed now. In fact, those operators are permuted coordinates of the mesh nodes. ['q'/other key to quit/continue...]""" ) req = conf.requirements['pis'] mini_app = cb.ShapeDimDim( 'pis', problem, req ) pis = mini_app() print pis spause( r""">>> ...the $\Pi$ operators. ['q'/other key to quit/continue...]""" ) spause( r""">>> Next, $E_{ijkl}$ needs so called steady state correctors $\bar{\omega}^{rs}$, computed now. ['q'/other key to quit/continue...]""" ) req = conf.requirements['corrs_rs'] save_name = req.get( 'save_name', '' ) name = os.path.join( output_dir, save_name ) mini_app = cb.CorrDimDim('steady rs correctors', problem, req) mini_app.setup_output(save_format='vtk', file_per_var=False) corrs_rs = mini_app( data = {'pis': pis} ) print corrs_rs spause( r""">>> ...the $\bar{\omega}^{rs}$ correctors. The results are saved in: %s.%s Try to display them with: python postproc.py %s.%s ['q'/other key to quit/continue...]""" % (2 * (name, problem.output_format)) ) spause( r""">>> Then the volume of the domain is needed. ['q'/other key to quit/continue...]""" ) volume = problem.evaluate('d_volume.i3.Y( uc )') print volume spause( r""">>> ...the volume. ['q'/other key to quit/continue...]""" ) spause( r""">>> Finally, $E_{ijkl}$ can be computed. ['q'/other key to quit/continue...]""" ) mini_app = cb.CoefSymSym('homogenized elastic tensor', problem, conf.coefs['E']) c_e = mini_app(volume, data={'pis': pis, 'corrs_rs' : corrs_rs}) print r""">>> The homogenized elastic coefficient $E_{ijkl}$, symmetric storage with rows, columns in 11, 22, 12 ordering:""" print c_e
def __init__(self, conf, problem, **kwargs): from sfepy.fem.state import State from sfepy.fem import ProblemDefinition from sfepy.base.conf import ProblemConf, get_standard_keywords from scipy.spatial import cKDTree as KDTree ScipyDirect.__init__(self, conf, **kwargs) # init subproblems pb_vars = problem.get_variables() # get "master" DofInfo and last index pb_adi_indx = problem.equations.variables.adi.indx self.adi_indx = pb_adi_indx.copy() last_indx = -1 for ii in self.adi_indx.itervalues(): last_indx = nm.max([last_indx, ii.stop]) # coupling variables self.cvars_to_pb = {} for jj in conf.coupling_variables: self.cvars_to_pb[jj] = [None, None] if jj in pb_vars.names: if pb_vars[jj].dual_var_name is not None: self.cvars_to_pb[jj][0] = -1 else: self.cvars_to_pb[jj][1] = -1 # init subproblems self.subpb = [] required, other = get_standard_keywords() master_prefix = output.get_output_prefix() for ii, ifname in enumerate(conf.others): sub_prefix = master_prefix[:-1] + '-sub%d:' % (ii + 1) output.set_output_prefix(sub_prefix) confi = ProblemConf.from_file(ifname, required, other, define_args=kwargs) pbi = ProblemDefinition.from_conf(confi, init_equations=True) sti = State(pbi.equations.variables) pbi.equations.set_data(None, ignore_unknown=True) pbi.time_update() pbi.update_materials() sti.apply_ebc() pbi_vars = pbi.get_variables() output.set_output_prefix(master_prefix) self.subpb.append([pbi, sti, None]) # append "slave" DofInfo for jj in pbi_vars.names: if not (pbi_vars[jj].is_state()): continue didx = pbi.equations.variables.adi.indx[jj] ndof = didx.stop - didx.start if jj in self.adi_indx: if ndof != \ (self.adi_indx[jj].stop - self.adi_indx[jj].start): raise ValueError('DOFs do not match!') else: self.adi_indx.update( {jj: slice(last_indx, last_indx + ndof, None)}) last_indx += ndof for jj in conf.coupling_variables: if jj in pbi_vars.names: if pbi_vars[jj].dual_var_name is not None: self.cvars_to_pb[jj][0] = ii else: self.cvars_to_pb[jj][1] = ii self.subpb.append([problem, None, None]) self.cvars_to_pb_map = {} for varname, pbs in self.cvars_to_pb.iteritems(): # match field nodes coors = [] for ii in pbs: pbi = self.subpb[ii][0] pbi_vars = pbi.get_variables() fcoors = pbi_vars[varname].field.coors dc = nm.abs(nm.max(fcoors, axis=0)\ - nm.min(fcoors, axis=0)) ax = nm.where(dc > 1e-9)[0] coors.append(fcoors[:, ax]) if len(coors[0]) != len(coors[1]): raise ValueError('number of nodes does not match!') kdtree = KDTree(coors[0]) map_12 = kdtree.query(coors[1])[1] pbi1 = self.subpb[pbs[0]][0] pbi1_vars = pbi1.get_variables() eq_map_1 = pbi1_vars[varname].eq_map pbi2 = self.subpb[pbs[1]][0] pbi2_vars = pbi2.get_variables() eq_map_2 = pbi2_vars[varname].eq_map dpn = eq_map_2.dpn nnd = map_12.shape[0] map_12_nd = nm.zeros((nnd * dpn, ), dtype=nm.int32) if dpn > 1: for ii in range(dpn): map_12_nd[ii::dpn] = map_12 * dpn + ii else: map_12_nd = map_12 idx = nm.where(eq_map_2.eq >= 0)[0] self.cvars_to_pb_map[varname] = eq_map_1.eq[map_12[idx]]
def generate_probes(filename_input, filename_results, options, conf=None, problem=None, probes=None, labels=None, probe_hooks=None): """ Generate probe figures and data files. """ if conf is None: required, other = get_standard_keywords() conf = ProblemConf.from_file(filename_input, required, other) opts = conf.options if options.auto_dir: output_dir = opts.get_('output_dir', '.') filename_results = os.path.join(output_dir, filename_results) output('results in: %s' % filename_results) io = MeshIO.any_from_filename(filename_results) step = options.step if options.step >= 0 else io.read_last_step() all_data = io.read_data(step) output('loaded:', all_data.keys()) output('from step:', step) if options.only_names is None: data = all_data else: data = {} for key, val in all_data.iteritems(): if key in options.only_names: data[key] = val if problem is None: problem = ProblemDefinition.from_conf(conf, init_equations=False, init_solvers=False) if probes is None: gen_probes = conf.get_function(conf.options.gen_probes) probes, labels = gen_probes(problem) if probe_hooks is None: probe_hooks = {None : conf.get_function(conf.options.probe_hook)} if options.output_filename_trunk is None: options.output_filename_trunk = problem.ofn_trunk filename_template = options.output_filename_trunk \ + ('_%%d.%s' % options.output_format) if options.same_dir: filename_template = os.path.join(os.path.dirname(filename_results), filename_template) output_dir = os.path.dirname(filename_results) for ip, probe in enumerate(probes): output(ip, probe.name) probe.set_options(close_limit=options.close_limit) for key, probe_hook in probe_hooks.iteritems(): out = probe_hook(data, probe, labels[ip], problem) if out is None: continue if isinstance(out, tuple): fig, results = out else: fig = out if key is not None: filename = filename_template % (key, ip) else: filename = filename_template % ip if fig is not None: if isinstance(fig, dict): for fig_name, fig_fig in fig.iteritems(): fig_filename = edit_filename(filename, suffix='_' + fig_name) fig_fig.savefig(fig_filename) output('figure ->', os.path.normpath(fig_filename)) else: fig.savefig(filename) output('figure ->', os.path.normpath(filename)) if results is not None: txt_filename = edit_filename(filename, new_ext='.txt') write_results(txt_filename, probe, results) output('data ->', os.path.normpath(txt_filename))
def generate_probes(filename_input, filename_results, options, conf=None, problem=None, probes=None, labels=None, probe_hooks=None): """Generate probe figures and data files.""" if conf is None: required, other = get_standard_keywords() conf = ProblemConf.from_file( filename_input, required, other ) opts = conf.options if options.auto_dir: output_dir = get_default_attr( opts, 'output_dir', '.' ) filename_results = os.path.join(output_dir, filename_results) output('results in: %s' % filename_results) io = MeshIO.any_from_filename(filename_results) all_data = io.read_data(options.step) output('loaded:', all_data.keys()) if options.only_names is None: data = all_data else: data = {} for key, val in all_data.iteritems(): if key in options.only_names: data[key] = val if problem is None: problem = ProblemDefinition.from_conf(conf, init_equations=False, init_solvers=False) if probes is None: gen_probes = getattr(conf.funmod, conf.options.gen_probes) probes, labels = gen_probes(problem) if probe_hooks is None: probe_hooks = {None : getattr(conf.funmod, conf.options.probe_hook)} if options.output_filename_trunk is None: options.output_filename_trunk = problem.ofn_trunk filename_template = options.output_filename_trunk \ + ('_%%d.%s' % options.output_format) if options.same_dir: filename_template = os.path.join(os.path.dirname(filename_results), filename_template) output_dir = os.path.dirname(filename_results) edit_pname = re.compile('[^a-zA-Z0-9-_.\[\]]').sub for ip, probe in enumerate(probes): output(ip, probe.name) for key, probe_hook in probe_hooks.iteritems(): out = probe_hook(data, probe, labels[ip], problem) if out is None: continue if isinstance(out, tuple): fig, results = out else: fig = out if key is not None: filename = filename_template % (key, ip) else: filename = filename_template % ip if fig is not None: fig.savefig(filename) output('figure ->', os.path.normpath(filename)) if results is not None: aux = os.path.splitext(filename)[0] txt_filename = aux + '.txt' fd = open(txt_filename, 'w') fd.write('\n'.join(probe.report()) + '\n') for key, res in results.iteritems(): pars, vals = res fd.write('\n# %s\n' % key) if vals.ndim == 1: aux = nm.hstack((pars[:,None], vals[:,None])) else: aux = nm.hstack((pars[:,None], vals)) nm.savetxt(fd, aux) fd.close() output('data ->', os.path.normpath(txt_filename))
def __init__(self, conf, problem, **kwargs): from sfepy.fem.state import State from sfepy.fem import ProblemDefinition from sfepy.base.conf import ProblemConf, get_standard_keywords from scipy.spatial import cKDTree as KDTree ScipyDirect.__init__(self, conf, **kwargs) # init subproblems pb_vars = problem.get_variables() # get "master" DofInfo and last index pb_adi_indx = problem.equations.variables.adi.indx self.adi_indx = pb_adi_indx.copy() last_indx = -1 for ii in self.adi_indx.itervalues(): last_indx = nm.max([last_indx, ii.stop]) # coupling variables self.cvars_to_pb = {} for jj in conf.coupling_variables: self.cvars_to_pb[jj] = [None, None] if jj in pb_vars.names: if pb_vars[jj].dual_var_name is not None: self.cvars_to_pb[jj][0] = -1 else: self.cvars_to_pb[jj][1] = -1 # init subproblems self.subpb = [] required, other = get_standard_keywords() master_prefix = output.get_output_prefix() for ii, ifname in enumerate(conf.others): sub_prefix = master_prefix[:-1] + "-sub%d:" % (ii + 1) output.set_output_prefix(sub_prefix) confi = ProblemConf.from_file(ifname, required, other, define_args=kwargs) pbi = ProblemDefinition.from_conf(confi, init_equations=True) sti = State(pbi.equations.variables) pbi.equations.set_data(None, ignore_unknown=True) pbi.time_update() pbi.update_materials() sti.apply_ebc() pbi_vars = pbi.get_variables() output.set_output_prefix(master_prefix) self.subpb.append([pbi, sti, None]) # append "slave" DofInfo for jj in pbi_vars.names: if not (pbi_vars[jj].is_state()): continue didx = pbi.equations.variables.adi.indx[jj] ndof = didx.stop - didx.start if jj in self.adi_indx: if ndof != (self.adi_indx[jj].stop - self.adi_indx[jj].start): raise ValueError("DOFs do not match!") else: self.adi_indx.update({jj: slice(last_indx, last_indx + ndof, None)}) last_indx += ndof for jj in conf.coupling_variables: if jj in pbi_vars.names: if pbi_vars[jj].dual_var_name is not None: self.cvars_to_pb[jj][0] = ii else: self.cvars_to_pb[jj][1] = ii self.subpb.append([problem, None, None]) self.cvars_to_pb_map = {} for varname, pbs in self.cvars_to_pb.iteritems(): # match field nodes coors = [] for ii in pbs: pbi = self.subpb[ii][0] pbi_vars = pbi.get_variables() fcoors = pbi_vars[varname].field.coors dc = nm.abs(nm.max(fcoors, axis=0) - nm.min(fcoors, axis=0)) ax = nm.where(dc > 1e-9)[0] coors.append(fcoors[:, ax]) if len(coors[0]) != len(coors[1]): raise ValueError("number of nodes does not match!") kdtree = KDTree(coors[0]) map_12 = kdtree.query(coors[1])[1] pbi1 = self.subpb[pbs[0]][0] pbi1_vars = pbi1.get_variables() eq_map_1 = pbi1_vars[varname].eq_map pbi2 = self.subpb[pbs[1]][0] pbi2_vars = pbi2.get_variables() eq_map_2 = pbi2_vars[varname].eq_map dpn = eq_map_2.dpn nnd = map_12.shape[0] map_12_nd = nm.zeros((nnd * dpn,), dtype=nm.int32) if dpn > 1: for ii in range(dpn): map_12_nd[ii::dpn] = map_12 * dpn + ii else: map_12_nd = map_12 idx = nm.where(eq_map_2.eq >= 0)[0] self.cvars_to_pb_map[varname] = eq_map_1.eq[map_12[idx]]
def main(): import os from sfepy.base.base import spause, output from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import ProblemDefinition import sfepy.homogenization.coefs_base as cb parser = OptionParser(usage=usage, version='%prog') parser.add_option('-n', '--no-pauses', action="store_true", dest='no_pauses', default=False, help=help['no_pauses']) options, args = parser.parse_args() if options.no_pauses: def spause(*args): output(*args) nm.set_printoptions(precision=3) spause(r""">>> First, this file will be read in place of an input (problem description) file. Press 'q' to quit the example, press any other key to continue...""") required, other = get_standard_keywords() required.remove('equations') # Use this file as the input file. conf = ProblemConf.from_file(__file__, required, other) print conf.to_dict().keys() spause(r""">>> ...the read input as a dict (keys only for brevity). ['q'/other key to quit/continue...]""") spause(r""">>> Now the input will be used to create a ProblemDefinition instance. ['q'/other key to quit/continue...]""") problem = ProblemDefinition.from_conf(conf, init_equations=False) # The homogenization mini-apps need the output_dir. output_dir = os.path.join(os.path.split(__file__)[0], 'output') if not os.path.exists(output_dir): os.makedirs(output_dir) problem.output_dir = output_dir print problem spause(r""">>> ...the ProblemDefinition instance. ['q'/other key to quit/continue...]""") spause(r""">>> The homogenized elastic coefficient $E_{ijkl}$ is expressed using $\Pi$ operators, computed now. In fact, those operators are permuted coordinates of the mesh nodes. ['q'/other key to quit/continue...]""") req = conf.requirements['pis'] mini_app = cb.ShapeDimDim('pis', problem, req) pis = mini_app() print pis spause(r""">>> ...the $\Pi$ operators. ['q'/other key to quit/continue...]""") spause(r""">>> Next, $E_{ijkl}$ needs so called steady state correctors $\bar{\omega}^{rs}$, computed now. ['q'/other key to quit/continue...]""") req = conf.requirements['corrs_rs'] save_name = req.get('save_name', '') name = os.path.join(output_dir, save_name) mini_app = cb.CorrDimDim('steady rs correctors', problem, req) mini_app.setup_output(save_format='vtk', file_per_var=False) corrs_rs = mini_app(data={'pis': pis}) print corrs_rs spause(r""">>> ...the $\bar{\omega}^{rs}$ correctors. The results are saved in: %s.%s Try to display them with: python postproc.py %s.%s ['q'/other key to quit/continue...]""" % (2 * (name, problem.output_format))) spause(r""">>> Then the volume of the domain is needed. ['q'/other key to quit/continue...]""") volume = problem.evaluate('d_volume.i3.Y( uc )') print volume spause(r""">>> ...the volume. ['q'/other key to quit/continue...]""") spause(r""">>> Finally, $E_{ijkl}$ can be computed. ['q'/other key to quit/continue...]""") mini_app = cb.CoefSymSym('homogenized elastic tensor', problem, conf.coefs['E']) c_e = mini_app(volume, data={'pis': pis, 'corrs_rs': corrs_rs}) print r""">>> The homogenized elastic coefficient $E_{ijkl}$, symmetric storage with rows, columns in 11, 22, 12 ordering:""" print c_e
def solve_eigen_problem1( conf, options ): pb = ProblemDefinition.from_conf( conf ) dim = pb.domain.mesh.dim pb.time_update() dummy = pb.create_state_vector() output( 'assembling lhs...' ) tt = time.clock() mtx_a = eval_term_op( dummy, conf.equations['lhs'], pb, dw_mode = 'matrix', tangent_matrix = pb.mtx_a ) output( '...done in %.2f s' % (time.clock() - tt) ) 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' ) print 'computing resonance frequencies...' eig = Solver.any_from_conf( pb.get_solver_conf( conf.options.eigen_solver ) ) eigs, mtx_s_phi = eig( mtx_a, mtx_b, conf.options.n_eigs ) from sfepy.fem.mesh import Mesh bounding_box = Mesh.from_file("tmp/mesh.vtk").get_bounding_box() # this assumes a box (3D), or a square (2D): a = bounding_box[1][0] - bounding_box[0][0] E_exact = None if options.hydrogen or options.boron: if options.hydrogen: Z = 1 elif options.boron: Z = 5 if options.dim == 2: E_exact = [-float(Z)**2/2/(n-0.5)**2/4 for n in [1]+[2]*3+[3]*5 +\ [4]*8 + [5]*15] elif options.dim == 3: E_exact = [-float(Z)**2/2/n**2 for n in [1]+[2]*2**2+[3]*3**2 ] if options.well: if options.dim == 2: E_exact = [pi**2/(2*a**2)*x for x in [2, 5, 5, 8, 10, 10, 13, 13, 17, 17, 18, 20, 20 ] ] elif options.dim == 3: E_exact = [pi**2/(2*a**2)*x for x in [3, 6, 6, 6, 9, 9, 9, 11, 11, 11, 12, 14, 14, 14, 14, 14, 14, 17, 17, 17] ] if options.oscillator: if options.dim == 2: E_exact = [1] + [2]*2 + [3]*3 + [4]*4 + [5]*5 + [6]*6 elif options.dim == 3: E_exact = [float(1)/2+x for x in [1]+[2]*3+[3]*6+[4]*10 ] if E_exact is not None: print "a=%f" % a print "Energies:" print "n exact FEM error" for i, e in enumerate(eigs): from numpy import NaN if i < len(E_exact): exact = E_exact[i] err = 100*abs((exact - e)/exact) else: exact = NaN err = NaN print "%d: %.8f %.8f %5.2f%%" % (i, exact, e, err) else: print eigs ## import sfepy.base.plotutils as plu ## plu.spy( mtx_b, eps = 1e-12 ) ## plu.pylab.show() ## pause() 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] 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 )
def main(): from sfepy.base.base import spause from sfepy.base.conf import ProblemConf, get_standard_keywords from sfepy.fem import eval_term_op, ProblemDefinition from sfepy.homogenization.utils import create_pis from sfepy.homogenization.coefs import CorrectorsRS, ElasticCoef nm.set_printoptions( precision = 3 ) spause( r""">>> First, this file will be read in place of an input (problem description) file. Press 'q' to quit the example, press any other key to continue...""" ) required, other = get_standard_keywords() required.remove( 'equations' ) # Use this file as the input file. conf = ProblemConf.from_file( __file__, required, other ) print conf.to_dict().keys() spause( r""">>> ...the read input as a dict (keys only for brevity). ['q'/other key to quit/continue...]""" ) spause( r""">>> Now the input will be used to create a ProblemDefinition instance. ['q'/other key to quit/continue...]""" ) problem = ProblemDefinition.from_conf( conf, init_variables = False, init_equations = False ) print problem spause( r""">>> ...the ProblemDefinition instance. ['q'/other key to quit/continue...]""" ) spause( r""">>> The homogenized elastic coefficient $E_{ijkl}$ is expressed using $\Pi$ operators, computed now. In fact, those operators are permuted coordinates of the mesh nodes. ['q'/other key to quit/continue...]""" ) req = conf.requirements['pis'] pis = create_pis( problem, req['variables'][0] ) print pis spause( r""">>> ...the $\Pi$ operators. ['q'/other key to quit/continue...]""" ) spause( r""">>> Next, $E_{ijkl}$ needs so called steady state correctors $\bar{\omega}^{rs}$, computed now. The results will be saved in: %s_*.vtk ['q'/other key to quit/continue...]""" % problem.ofn_trunk ) save_hook = make_save_hook( problem.ofn_trunk + '_rs_%d%d' ) req = conf.requirements['corrs_rs'] solve_corrs = CorrectorsRS( 'steady rs correctors', problem, req ) corrs_rs = solve_corrs( data = pis, save_hook = save_hook ) print corrs_rs spause( r""">>> ...the $\bar{\omega}^{rs}$ correctors. ['q'/other key to quit/continue...]""" ) spause( r""">>> Then the volume of the domain is needed. ['q'/other key to quit/continue...]""" ) volume = eval_term_op( None, 'd_volume.i3.Y( uc )', problem ) print volume spause( r""">>> ...the volume. ['q'/other key to quit/continue...]""" ) spause( r""">>> Finally, $E_{ijkl}$ can be computed. ['q'/other key to quit/continue...]""" ) get_coef = ElasticCoef( 'homogenized elastic tensor', problem, conf.coefs['E'] ) c_e = get_coef( volume, data = {'pis': pis, 'corrs' : corrs_rs} ) print r""">>> The homogenized elastic coefficient $E_{ijkl}$, symmetric storage with rows, columns in 11, 22, 12 ordering:""" print c_e
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 )