def initialize_for_fourier(self, grid): # NOTE: This code is only temporary until we get the # more versatile initial value specifications. # TODO: Make a specification of the IV setup in configurations Psi = [] for packet_descr in self._parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Evaluate the X = grid.get_nodes(flat=True) values = packet.evaluate_at(X, prefactor=True) # Reshape values into hypercubic shape values = [ val.reshape(grid.get_number_nodes()) for val in values ] Psi.append( values ) # TODO: Maybe sum up immediately instead of at the end to reduce memory usage Psi = reduce(lambda x,y: x+y, Psi) # Pack the values in a WaveFunction instance WF = WaveFunction(self._parameters) WF.set_grid(grid) WF.set_values(Psi) return WF
def __init__(self, wf_params): self.l, self.N = wf_params[:2] self.wf = WaveFunction(wf_params) eta = self.wf.eta self.eta_add = np.add.outer(eta, eta) self.conj_eta_add = np.add.outer(eta.conj(), eta) self.eta_mult = np.multiply.outer(eta, eta) self.conj_eta_mult = np.multiply.outer(eta.conj(), eta) self.N_cos_ij = np.multiply.outer(self.wf.N_cos, self.wf.N_cos)
def __init__(self, system_params, wf_params, potential_params, r): system = NuclearSystem(wf_params, system_params, potential_params) system.calculate_energy() self.bound_energy = system.energies[0] wf = WaveFunction(wf_params) radial_wavefunctions = r * np.matmul(system.C.transpose(), wf.phi(r)) self.bound_wavefunction = np.abs(radial_wavefunctions[0, :]) k = np.sqrt(-2 * self.bound_energy * system.mass / system.const1) eta = system.mass * system.z1 * system.z2 * system.const2 / k / system.const1 self.whitw_ = np.array( [whitw(-eta, wf.l + 0.5, 2 * k * r_i) for r_i in r], dtype=float)
def initialize_for_fourier(self, grid): # NOTE: This code is only temporary until we get the # more versatile initial value specifications. # TODO: Make a specification of the IV setup in configurations Psi = [] for packet_descr in self._parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Evaluate the X = grid.get_nodes(flat=True) values = packet.evaluate_at(X, prefactor=True) # Reshape values into hypercubic shape values = [val.reshape(grid.get_number_nodes()) for val in values] Psi.append(values) # TODO: Maybe sum up immediately instead of at the end to reduce memory usage Psi = reduce(lambda x, y: x + y, Psi) # Pack the values in a WaveFunction instance WF = WaveFunction(self._parameters) WF.set_grid(grid) WF.set_values(Psi) return WF
class MatrixElements: def __init__(self, wf_params): self.l, self.N = wf_params[:2] self.wf = WaveFunction(wf_params) eta = self.wf.eta self.eta_add = np.add.outer(eta, eta) self.conj_eta_add = np.add.outer(eta.conj(), eta) self.eta_mult = np.multiply.outer(eta, eta) self.conj_eta_mult = np.multiply.outer(eta.conj(), eta) self.N_cos_ij = np.multiply.outer(self.wf.N_cos, self.wf.N_cos) def overlap_matrix(self): AL = np.power(1 / self.eta_add, self.l + 1.5) BL = np.power(1 / self.conj_eta_add, self.l + 1.5) return self.calc_mat_elems(AL, BL) * gamma(self.l + 1.5) / 2 def kinetic_pot(self, const1, mass): AH0 = np.divide(self.eta_mult, np.power(self.eta_add, self.l + 2.5)) BH0 = np.divide(self.conj_eta_mult, np.power(self.conj_eta_add, self.l + 2.5)) return self.calc_mat_elems( AH0, BH0) * const1 / mass * (self.l + 1.5) * gamma(self.l + 1.5) def nuclear_pot(self, potential_params): V0, Vso, S, J, R0, Rso, a0, aso = potential_params LS = J * (J + 1) - self.l * (self.l + 1) - S * (S + 1) r_step = 0.1 r = np.arange(1e-6, 15, r_step) V1 = V0 * self.woods_saxon(a0, R0, r) V2 = 2 * Vso * LS / aso * np.exp( (r - Rso) / aso) * np.power(self.woods_saxon(aso, Rso, r), 2) / r return np.einsum("ir, r, jr -> ij", self.wf.phi(r), (V1 + V2) * r**2, self.wf.phi(r)) * r_step def coulomb_pot(self, z1, z2, const2, Rc): Vc_0_Rc = self.V_coul_from_0_to_Rc(Rc) Vc_Rc_Inf = self.V_coul_from_Rc_to_Inf(Rc) return z1 * z2 * const2 * (Vc_0_Rc + Vc_Rc_Inf) def V_coul_from_0_to_Rc(self, Rc): AVc = 3 * self.integral_0_b(Rc, 2 * self.l + 2, self.eta_add) - \ 1 / Rc**2 * self.integral_0_b(Rc, 2 * self.l + 4, self.eta_add) BVc = 3 * self.integral_0_b(Rc, 2 * self.l + 2, self.conj_eta_add) - \ 1 / Rc**2 * self.integral_0_b(Rc, 2 * self.l + 4, self.conj_eta_add) return self.calc_mat_elems(AVc, BVc) / 2 / Rc def V_coul_from_Rc_to_Inf(self, Rc): # $\int_b^\Inf = \int_0^\Inf - \int_0^b$ AVc = np.power(1 / self.eta_add, self.l + 1) * factorial(self.l) / 2 - \ self.integral_0_b(Rc, 2 * self.l + 1, self.eta_add) BVc = np.power(1 / self.conj_eta_add, self.l + 1) * factorial(self.l) / 2 - \ self.integral_0_b(Rc, 2 * self.l + 1, self.conj_eta_add) return self.calc_mat_elems(AVc, BVc) def calc_mat_elems(self, A, B): return (A + A.conj() + B + B.conj()).real * self.N_cos_ij / 4 @staticmethod def woods_saxon(a, R, r): return 1 / (1 + np.exp((r - R) / a)) @staticmethod def integral_0_b(b, n, a): if n == 0: return 0.5 * np.sqrt(np.pi / a) * erf(np.sqrt(a) * b) if n == 1: return (1 - np.exp(-a * b**2)) / 2 / a return (n - 1) / 2 / a * MatrixElements.integral_0_b( b, n - 2, a) - b**(n - 1) / 2 / a * np.exp(-a * b**2)
def prepare_simulation(self): r""" Set up a Fourier propagator for the simulation loop. Set the potential and initial values according to the configuration. :raise ValueError: For invalid or missing input data. """ # Compute the position space grid points nodes = self.parameters["f"] * sp.pi * sp.arange(-1, 1, 2.0/self.parameters["ngn"], dtype=np.complexfloating) # The potential instance potential = PF().create_potential(self.parameters) # Check for enough initial values if not self.parameters.has_key("initial_values"): if len(self.parameters["parameters"]) < potential.get_number_components(): raise ValueError("Too few initial states given. Parameters are missing.") if len(self.parameters["coefficients"]) < potential.get_number_components(): raise ValueError("Too few initial states given. Coefficients are missing.") # Calculate the initial values sampled from a hagedorn wave packet d = dict([("ncomponents", 1), ("basis_size", self.parameters["basis_size"]), ("eps", self.parameters["eps"])]) # Initial values given in the "fourier" specific format if self.parameters.has_key("initial_values"): initialvalues = [ np.zeros(nodes.shape, dtype=np.complexfloating) for i in xrange(self.parameters["ncomponents"]) ] for level, params, coeffs in self.parameters["initial_values"]: hwp = HagedornWavepacket(d) hwp.set_parameters(params) for index, value in coeffs: hwp.set_coefficient(0, index, value) iv = hwp.evaluate_at(nodes, component=0, prefactor=True) initialvalues[level] = initialvalues[level] + iv # Initial value read in compatibility mode to the packet algorithms else: # See if we have a list of parameter tuples or just a single 5-tuple # This is for compatibility with the inhomogeneous case. try: # We have a list of parameter tuples this is ok for the loop below len(self.parameters["parameters"][0]) parameters = self.parameters["parameters"] except TypeError: # We have just a single 5-tuple of parameters, we need to replicate for looping parameters = [ self.parameters["parameters"] for i in xrange(self.parameters["ncomponents"]) ] initialvalues = [] for level, item in enumerate(parameters): hwp = HagedornWavepacket(d) hwp.set_parameters(item) # Set the coefficients of the basis functions for index, value in self.parameters["coefficients"][level]: hwp.set_coefficient(0, index, value) iv = hwp.evaluate_at(nodes, component=0, prefactor=True) initialvalues.append(iv) # Project the initial values to the canonical basis initialvalues = potential.project_to_canonical(nodes, initialvalues) # Store the initial values in a WaveFunction object IV = WaveFunction(self.parameters) IV.set_grid(nodes) IV.set_values(initialvalues) # Finally create and initialize the propagator instace self.propagator = FourierPropagator(potential, IV, self.parameters) # Which data do we want to save tm = self.parameters.get_timemanager() slots = tm.compute_number_saves() print(tm) self.IOManager.add_grid(self.parameters, blockid="global") self.IOManager.add_fourieroperators(self.parameters) self.IOManager.add_wavefunction(self.parameters, timeslots=slots) # Write some initial values to disk self.IOManager.save_grid(nodes, blockid="global") self.IOManager.save_fourieroperators(self.propagator.get_operators()) self.IOManager.save_wavefunction(IV.get_values(), timestep=0)