def assemble_matrices(define, mod, pars, set_wave_dir, options, wdir=None): """ Assemble the blocks of dispersion eigenvalue problem matrices. """ define_dict = define(filename_mesh=options.mesh_filename, pars=pars, approx_order=options.order, refinement_level=options.refine, solver_conf=options.solver_conf, plane=options.plane, post_process=options.post_process, **options.define_kwargs) conf = ProblemConf.from_dict(define_dict, mod) pb = Problem.from_conf(conf) pb.dispersion_options = options pb.set_output_dir(options.output_dir) dim = pb.domain.shape.dim # Set the normalized wave vector direction to the material(s). if wdir is None: wdir = nm.asarray(options.wave_dir[:dim], dtype=nm.float64) wdir = wdir / nm.linalg.norm(wdir) set_wave_dir(pb, wdir) 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() # Assemble the matrices. mtxs = {} for key, eq in pb.equations.iteritems(): mtxs[key] = mtx = pb.mtx_a.copy() mtx = eq.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx) mtx.eliminate_zeros() output_array_stats(mtx.data, 'nonzeros in %s' % key) output('symmetry checks:') output('%s - %s^T:' % (key, key), max_diff_csr(mtx, mtx.T)) output('%s - %s^H:' % (key, key), max_diff_csr(mtx, mtx.H)) return pb, wdir, bzone, mtxs
def assemble_matrices(define, mod, pars, set_wave_dir, options): """ Assemble the blocks of dispersion eigenvalue problem matrices. """ 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, post_process=options.post_process) conf = ProblemConf.from_dict(define_problem(), mod) pb = Problem.from_conf(conf) pb.dispersion_options = options pb.set_output_dir(options.output_dir) dim = pb.domain.shape.dim # Set the normalized wave vector direction to the material(s). wdir = nm.asarray(options.wave_dir[:dim], dtype=nm.float64) wdir = wdir / nm.linalg.norm(wdir) set_wave_dir(pb, wdir) 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() # Assemble the matrices. mtxs = {} for key, eq in pb.equations.iteritems(): mtxs[key] = mtx = pb.mtx_a.copy() mtx = eq.evaluate(mode='weak', dw_mode='matrix', asm_obj=mtx) mtx.eliminate_zeros() output_array_stats(mtx.data, 'nonzeros in %s' % key) output('symmetry checks:') output('%s - %s^T:' % (key, key), max_diff_csr(mtx, mtx.T)) output('%s - %s^H:' % (key, key), max_diff_csr(mtx, mtx.H)) return pb, wdir, bzone, mtxs
def build_evp_matrices(mtxs, val, mode, pb): """ Build the matrices of the dispersion eigenvalue problem. """ if mode == 'omega': mtx_a = mtxs['K'] + val**2 * mtxs['S'] + val * mtxs['R'] output('A - A^H:', max_diff_csr(mtx_a, mtx_a.H)) evp_mtxs = (mtx_a, mtxs['M']) else: evp_mtxs = (mtxs['S'], mtxs['R'], mtxs['K'] - val**2 * mtxs['M']) return evp_mtxs
def __call__(self, mtx_m, mtx_d, mtx_k, n_eigs=None, eigenvectors=None, status=None, conf=None): if conf.debug: ssym = status['matrix_info'] = {} ssym['|M - M^T|'] = max_diff_csr(mtx_m, mtx_m.T) ssym['|D - D^T|'] = max_diff_csr(mtx_d, mtx_d.T) ssym['|K - K^T|'] = max_diff_csr(mtx_k, mtx_k.T) ssym['|M - M^H|'] = max_diff_csr(mtx_m, mtx_m.H) ssym['|D - D^H|'] = max_diff_csr(mtx_d, mtx_d.H) ssym['|K - K^H|'] = max_diff_csr(mtx_k, mtx_k.H) if conf.method == 'companion': mtx_eye = -sps.eye(mtx_m.shape[0], dtype=mtx_m.dtype) mtx_a = sps.bmat([[mtx_d, mtx_k], [mtx_eye, None]]) mtx_b = sps.bmat([[-mtx_m, None], [None, mtx_eye]]) elif conf.method == 'cholesky': from sksparse.cholmod import cholesky factor = cholesky(mtx_m) 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() if conf.debug: ssym['|S - LL^T|'] = max_diff_csr(mtx_m, mtx_l * mtx_l.T) mtx_eye = sps.eye(mtx_l.shape[0], dtype=nm.float64) mtx_a = sps.bmat([[-mtx_k, None], [None, mtx_eye]]) mtx_b = sps.bmat([[mtx_d, mtx_l], [mtx_l.T, None]]) else: raise ValueError('unknown method! (%s)' % conf.method) if conf.debug: ssym['|A - A^T|'] = max_diff_csr(mtx_a, mtx_a.T) ssym['|A - A^H|'] = max_diff_csr(mtx_a, mtx_a.H) ssym['|B - B^T|'] = max_diff_csr(mtx_b, mtx_b.T) ssym['|B - B^H|'] = max_diff_csr(mtx_b, mtx_b.H) for key, val in sorted(ssym.items()): output('{}: {}'.format(key, val)) if conf.mode == 'normal': out = self.solver(mtx_a, mtx_b, n_eigs=n_eigs, eigenvectors=eigenvectors, status=status) if eigenvectors: eigs, vecs = out out = (eigs, vecs[:mtx_m.shape[0], :]) if conf.debug: res = mtx_a.dot(vecs) - eigs * mtx_b.dot(vecs) status['lin. error'] = nm.linalg.norm(res, nm.inf) else: out = self.solver(mtx_b, mtx_a, n_eigs=n_eigs, eigenvectors=eigenvectors, status=status) if eigenvectors: eigs, vecs = out out = (1.0 / eigs, vecs[:mtx_m.shape[0], :]) if conf.debug: res = (1.0 / eigs) * mtx_b.dot(vecs) - mtx_a.dot(vecs) status['lin. error'] = nm.linalg.norm(res, nm.inf) else: out = 1.0 / out if conf.debug and eigenvectors: eigs, vecs = out res = ((eigs**2 * (mtx_m.dot(vecs))) + (eigs * (mtx_d.dot(vecs))) + (mtx_k.dot(vecs))) status['error'] = nm.linalg.norm(res, nm.inf) return out