forked from jan/fdfd_tools
		
	Cleanup
This commit is contained in:
		
							parent
							
								
									0e47fdd5fb
								
							
						
					
					
						commit
						e8f836c908
					
				@ -73,7 +73,7 @@ This module contains functions for generating and solving the
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
'''
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from typing import List, Tuple, Callable, Dict
 | 
					from typing import Tuple, Callable
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import numpy
 | 
					import numpy
 | 
				
			||||||
from numpy import pi, real, trace
 | 
					from numpy import pi, real, trace
 | 
				
			||||||
@ -83,7 +83,6 @@ import scipy.optimize
 | 
				
			|||||||
from scipy.linalg import norm
 | 
					from scipy.linalg import norm
 | 
				
			||||||
import scipy.sparse.linalg as spalg
 | 
					import scipy.sparse.linalg as spalg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .eigensolvers import rayleigh_quotient_iteration
 | 
					 | 
				
			||||||
from . import field_t
 | 
					from . import field_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger = logging.getLogger(__name__)
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
@ -256,7 +255,7 @@ def hmn_2_hxyz(k0: numpy.ndarray,
 | 
				
			|||||||
    :return: Function for converting h_mn into H_xyz
 | 
					    :return: Function for converting h_mn into H_xyz
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    shape = epsilon[0].shape + (1,)
 | 
					    shape = epsilon[0].shape + (1,)
 | 
				
			||||||
    k_mag, m, n = generate_kmn(k0, G_matrix, shape)
 | 
					    _k_mag, m, n = generate_kmn(k0, G_matrix, shape)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def operator(h: numpy.ndarray):
 | 
					    def operator(h: numpy.ndarray):
 | 
				
			||||||
        hin_m, hin_n = [hi.reshape(shape) for hi in numpy.split(h, 2)]
 | 
					        hin_m, hin_n = [hi.reshape(shape) for hi in numpy.split(h, 2)]
 | 
				
			||||||
@ -379,7 +378,6 @@ def find_k(frequency: float,
 | 
				
			|||||||
    return res.x * direction, res.fun + frequency
 | 
					    return res.x * direction, res.fun + frequency
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def eigsolve(num_modes: int,
 | 
					def eigsolve(num_modes: int,
 | 
				
			||||||
             k0: numpy.ndarray,
 | 
					             k0: numpy.ndarray,
 | 
				
			||||||
             G_matrix: numpy.ndarray,
 | 
					             G_matrix: numpy.ndarray,
 | 
				
			||||||
@ -432,10 +430,8 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
        Z = y0
 | 
					        Z = y0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while True:
 | 
					    while True:
 | 
				
			||||||
 | 
					        Z *= num_modes / norm(Z)
 | 
				
			||||||
        ZtZ = Z.conj().T @ Z
 | 
					        ZtZ = Z.conj().T @ Z
 | 
				
			||||||
        Z_norm = numpy.sqrt(real(trace(ZtZ))) / num_modes
 | 
					 | 
				
			||||||
        Z /= Z_norm
 | 
					 | 
				
			||||||
        ZtZ /= Z_norm * Z_norm
 | 
					 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            U = numpy.linalg.inv(ZtZ)
 | 
					            U = numpy.linalg.inv(ZtZ)
 | 
				
			||||||
        except numpy.linalg.LinAlgError:
 | 
					        except numpy.linalg.LinAlgError:
 | 
				
			||||||
@ -449,7 +445,7 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
            continue
 | 
					            continue
 | 
				
			||||||
        break
 | 
					        break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for iter in range(max_iters):
 | 
					    for i in range(max_iters):
 | 
				
			||||||
        ZtZ = Z.conj().T @ Z
 | 
					        ZtZ = Z.conj().T @ Z
 | 
				
			||||||
        U = numpy.linalg.inv(ZtZ)
 | 
					        U = numpy.linalg.inv(ZtZ)
 | 
				
			||||||
        AZ = scipy_op @ Z
 | 
					        AZ = scipy_op @ Z
 | 
				
			||||||
@ -460,22 +456,22 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
        E = numpy.abs(E_signed)
 | 
					        E = numpy.abs(E_signed)
 | 
				
			||||||
        G = (AZU - Z @ U @ ZtAZU) * sgn
 | 
					        G = (AZU - Z @ U @ ZtAZU) * sgn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if iter > 0 and abs(E - prev_E) < tolerance * 0.5 * (E + prev_E + 1e-7):
 | 
					        if i > 0 and abs(E - prev_E) < tolerance * 0.5 * (E + prev_E + 1e-7):
 | 
				
			||||||
            logging.info('Optimization succeded: {} - 5e-8 < {} * {} / 2'.format(abs(E - prev_E), tolerance, E + prev_E))
 | 
					            logging.info('Optimization succeded: {} - 5e-8 < {} * {} / 2'.format(abs(E - prev_E), tolerance, E + prev_E))
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        KG = scipy_iop @ G
 | 
					        KG = scipy_iop @ G
 | 
				
			||||||
        traceGtKG = _rtrace_AtB(G, KG)
 | 
					        traceGtKG = _rtrace_AtB(G, KG)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if prev_traceGtKG == 0 or iter % reset_iters == 0:
 | 
					        if prev_traceGtKG == 0 or i % reset_iters == 0:
 | 
				
			||||||
            logger.info('CG reset')
 | 
					            logger.info('CG reset')
 | 
				
			||||||
            gamma = 0
 | 
					            gamma = 0
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            gamma = traceGtKG / prev_traceGtKG
 | 
					            gamma = traceGtKG / prev_traceGtKG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        D = gamma * d_scale * D + KG
 | 
					        D = gamma / d_scale * D + KG
 | 
				
			||||||
        d_scale = numpy.sqrt(_rtrace_AtB(D, D)) / num_modes
 | 
					        d_scale = num_modes / norm(D)
 | 
				
			||||||
        D /= d_scale
 | 
					        D *= d_scale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ZtAZ = Z.conj().T @ AZ
 | 
					        ZtAZ = Z.conj().T @ AZ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -486,22 +482,6 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
        symZtD = _symmetrize(Z.conj().T @ D)
 | 
					        symZtD = _symmetrize(Z.conj().T @ D)
 | 
				
			||||||
        symZtAD = _symmetrize(Z.conj().T @ AD)
 | 
					        symZtAD = _symmetrize(Z.conj().T @ AD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        '''
 | 
					 | 
				
			||||||
        U_sZtD = U @ symZtD
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dE = 2.0 * (_rtrace_AtB(U, symZtAD) -
 | 
					 | 
				
			||||||
                    _rtrace_AtB(ZtAZU, U_sZtD))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        d2E = 2 * (_rtrace_AtB(U, DtAD) -
 | 
					 | 
				
			||||||
                   _rtrace_AtB(ZtAZU, U @ (DtD - 4 * symZtD @ U_sZtD)) -
 | 
					 | 
				
			||||||
               4 * _rtrace_AtB(U, symZtAD @ U_sZtD))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Newton-Raphson to find a root of the first derivative:
 | 
					 | 
				
			||||||
        theta = -dE/d2E
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if d2E < 0 or abs(theta) >= pi:
 | 
					 | 
				
			||||||
            theta = -abs(prev_theta) * numpy.sign(dE)
 | 
					 | 
				
			||||||
        '''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def Qi_func(theta, memo=[None, None]):
 | 
					        def Qi_func(theta, memo=[None, None]):
 | 
				
			||||||
            if memo[0] == theta:
 | 
					            if memo[0] == theta:
 | 
				
			||||||
@ -549,12 +529,25 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            trace_deriv *= 2
 | 
					            trace_deriv *= 2
 | 
				
			||||||
            return trace_deriv * sgn
 | 
					            return trace_deriv * sgn
 | 
				
			||||||
        '''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        U_sZtD = U @ symZtD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dE = 2.0 * (_rtrace_AtB(U, symZtAD) -
 | 
				
			||||||
 | 
					                    _rtrace_AtB(ZtAZU, U_sZtD))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        d2E = 2 * (_rtrace_AtB(U, DtAD) -
 | 
				
			||||||
 | 
					                   _rtrace_AtB(ZtAZU, U @ (DtD - 4 * symZtD @ U_sZtD)) -
 | 
				
			||||||
 | 
					               4 * _rtrace_AtB(U, symZtAD @ U_sZtD))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Newton-Raphson to find a root of the first derivative:
 | 
				
			||||||
 | 
					        theta = -dE/d2E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if d2E < 0 or abs(theta) >= pi:
 | 
				
			||||||
 | 
					            theta = -abs(prev_theta) * numpy.sign(dE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # theta, new_E, new_dE = linmin(theta, E, dE, 0.1, min(tolerance, 1e-6), 1e-14, 0, -numpy.sign(dE) * K_PI, trace_func)
 | 
				
			||||||
 | 
					        theta, n, _, new_E, _, _new_dE = scipy.optimize.line_search(trace_func, trace_deriv, xk=theta, pk=numpy.ones((1,1)), gfk=dE, old_fval=E, c1=min(tolerance, 1e-6), c2=0.1, amax=pi)
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        theta, new_E, new_dE = linmin(theta, E, dE, 0.1, min(tolerance, 1e-6), 1e-14, 0, -numpy.sign(dE) * K_PI, trace_func)
 | 
					 | 
				
			||||||
        '''
 | 
					 | 
				
			||||||
        #theta, n, _, new_E, _, _new_dE = scipy.optimize.line_search(trace_func, trace_deriv, xk=theta, pk=numpy.ones((1,1)), gfk=dE, old_fval=E, c1=min(tolerance, 1e-6), c2=0.1, amax=pi)
 | 
					 | 
				
			||||||
        result = scipy.optimize.minimize_scalar(trace_func, bounds=(0, pi), tol=tolerance)
 | 
					        result = scipy.optimize.minimize_scalar(trace_func, bounds=(0, pi), tol=tolerance)
 | 
				
			||||||
        new_E = result.fun
 | 
					        new_E = result.fun
 | 
				
			||||||
        theta = result.x
 | 
					        theta = result.x
 | 
				
			||||||
@ -591,32 +584,33 @@ def eigsolve(num_modes: int,
 | 
				
			|||||||
    order = numpy.argsort(numpy.abs(eigvals))
 | 
					    order = numpy.argsort(numpy.abs(eigvals))
 | 
				
			||||||
    return eigvals[order], eigvecs.T[order]
 | 
					    return eigvals[order], eigvecs.T[order]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#def linmin(x_guess, f0, df0, x_max, f_tol=0.1, df_tol=min(tolerance, 1e-6), x_tol=1e-14, x_min=0, linmin_func):
 | 
					'''
 | 
				
			||||||
#    if df0 > 0:
 | 
					def linmin(x_guess, f0, df0, x_max, f_tol=0.1, df_tol=min(tolerance, 1e-6), x_tol=1e-14, x_min=0, linmin_func):
 | 
				
			||||||
#        x0, f0, df0 = linmin(-x_guess, f0, -df0, -x_max, f_tol, df_tol, x_tol, -x_min, lambda q, dq: -linmin_func(q, dq))
 | 
					    if df0 > 0:
 | 
				
			||||||
#        return -x0, f0, -df0
 | 
					        x0, f0, df0 = linmin(-x_guess, f0, -df0, -x_max, f_tol, df_tol, x_tol, -x_min, lambda q, dq: -linmin_func(q, dq))
 | 
				
			||||||
#    elif df0 == 0:
 | 
					        return -x0, f0, -df0
 | 
				
			||||||
#        return 0, f0, df0
 | 
					    elif df0 == 0:
 | 
				
			||||||
#    else:
 | 
					        return 0, f0, df0
 | 
				
			||||||
#        x = x_guess
 | 
					    else:
 | 
				
			||||||
#        fx = f0
 | 
					        x = x_guess
 | 
				
			||||||
#        dfx = df0
 | 
					        fx = f0
 | 
				
			||||||
 | 
					        dfx = df0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#        isave = numpy.zeros((2,), numpy.intc)
 | 
					        isave = numpy.zeros((2,), numpy.intc)
 | 
				
			||||||
#        dsave = numpy.zeros((13,), float)
 | 
					        dsave = numpy.zeros((13,), float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#        x, fx, dfx, task = minpack2.dsrch(x, fx, dfx, f_tol, df_tol, x_tol, task,
 | 
					        x, fx, dfx, task = minpack2.dsrch(x, fx, dfx, f_tol, df_tol, x_tol, task,
 | 
				
			||||||
#                                          x_min, x_max, isave, dsave)
 | 
					                                          x_min, x_max, isave, dsave)
 | 
				
			||||||
#        for i in range(int(1e6)):
 | 
					        for i in range(int(1e6)):
 | 
				
			||||||
#            if task != 'F':
 | 
					            if task != 'F':
 | 
				
			||||||
#                logging.info('search converged in {} iterations'.format(i))
 | 
					                logging.info('search converged in {} iterations'.format(i))
 | 
				
			||||||
#                break
 | 
					                break
 | 
				
			||||||
#            fx = f(x, dfx)
 | 
					            fx = f(x, dfx)
 | 
				
			||||||
#            x, fx, dfx, task = minpack2.dsrch(x, fx, dfx, f_tol, df_tol, x_tol, task,
 | 
					            x, fx, dfx, task = minpack2.dsrch(x, fx, dfx, f_tol, df_tol, x_tol, task,
 | 
				
			||||||
#                                              x_min, x_max, isave, dsave)
 | 
					                                              x_min, x_max, isave, dsave)
 | 
				
			||||||
 | 
					 | 
				
			||||||
#        return x, fx, dfx
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return x, fx, dfx
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _rtrace_AtB(A, B):
 | 
					def _rtrace_AtB(A, B):
 | 
				
			||||||
    return real(numpy.sum(A.conj() * B))
 | 
					    return real(numpy.sum(A.conj() * B))
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user