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 load_wavepacket(self, timestep, blockid=0, key=("q","p","Q","P","S")): r"""Load a wavepacket at a given timestep and return a fully configured instance. This method just calls some other :py:class:`IOManager` methods in the correct order. It is included only for convenience and is not particularly efficient. :param timestep: The timestep :math:`n` at which we load the wavepacket. :param key: Specify which parameters to save. All are independent. :type key: Tuple of valid identifier strings that are ``q``, ``p``, ``Q``, ``P``, ``S`` and ``adQ``. Default is ``("q", "p", "Q", "P", "S")``. :param blockid: The ID of the data block to operate on. :return: A :py:class:`HagedornWavepacket` instance. """ from BlockFactory import BlockFactory BF = BlockFactory() descr = self.load_wavepacket_description(blockid=blockid) HAWP = BF.create_wavepacket(descr) # Parameters and coefficients Pi = self.load_wavepacket_parameters(timestep=timestep, blockid=blockid, key=key) hashes, coeffs = self.load_wavepacket_coefficients(timestep=timestep, get_hashes=True, blockid=blockid) # Basis shapes Ks = [] for ahash in hashes: K_descr = self.load_wavepacket_basisshapes(the_hash=ahash, blockid=blockid) Ks.append(BF.create_basis_shape(K_descr)) # Configure the wavepacket HAWP.set_parameters(Pi, key=key) HAWP.set_basis_shapes(Ks) HAWP.set_coefficients(coeffs) return HAWP
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 prepare_simulation(self): r"""Set up a Fourier propagator for the simulation loop. Set the potential and initial values according to the configuration. :raise: :py:class:`ValueError` For invalid or missing input data. """ # The potential instance potential = BlockFactory().create_potential(self.parameters) # Compute the position space grid points grid = BlockFactory().create_grid(self.parameters) # Construct initial values I = Initializer(self.parameters) initialvalues = I.initialize_for_fourier(grid) # Transform the initial values to the canonical basis BT = BasisTransformationWF(potential) BT.set_grid(grid) BT.transform_to_canonical(initialvalues) # Finally create and initialize the propagator instance self.propagator = FourierPropagator(potential, initialvalues, self.parameters) # Write some initial values to disk slots = self._tm.compute_number_saves() self.IOManager.add_grid(self.parameters, blockid="global") self.IOManager.add_fourieroperators(self.parameters) self.IOManager.add_wavefunction(self.parameters, timeslots=slots) self.IOManager.save_grid(grid.get_nodes(flat=True), blockid="global") self.IOManager.save_fourieroperators(self.propagator.get_operators()) self.IOManager.save_wavefunction(initialvalues.get_values(), timestep=0)
def prepare_simulation(self): r"""Set up a Hagedorn propagator for the simulation loop. Set the potential and initial values according to the configuration. :raise ValueError: For invalid or missing input data. """ # The potential instance potential = BlockFactory().create_potential(self.parameters) # Project the initial values to the canonical basis BT = BasisTransformationHAWP(potential) # Finally create and initialize the propagator instace # TODO: Attach the "leading_component to the hawp as codata self.propagator = HagedornPropagatorInhomogeneous( self.parameters, potential) # Create suitable wavepackets for packet_descr in self.parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Transform to canonical basis BT.set_matrix_builder(packet.get_quadrature()) BT.transform_to_canonical(packet) # And hand over self.propagator.add_wavepacket((packet, )) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_inhomogwavepacket(self.parameters, timeslots=slots, blockid=bid) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_inhomogwavepacket_description( packet.get_description()) # Pi self.IOManager.save_inhomogwavepacket_parameters( packet.get_parameters(), timestep=0) # Basis shapes for shape in packet.get_basis_shape(): self.IOManager.save_inhomogwavepacket_basisshapes(shape) # Coefficients self.IOManager.save_inhomogwavepacket_coefficients( packet.get_coefficients(), packet.get_basis_shape(), timestep=0)
def compute_parameters(self): """Compute some further parameters from the given ones. """ # Perform the computation only if the basic values are available. # This is necessary to add flexibility and essentially read in *any* # parameter file with heavily incomplete value sets. (F.e. spawn configs) try: # The number of time steps we will perform. tm = TimeManager(self) self._params["nsteps"] = tm.compute_number_timesteps() except: pass if self._params.has_key("potential"): # Ugly hack. Should improve handling of potential libraries Potential = BlockFactory().create_potential(self) # Number of components of $\Psi$ self._params["ncomponents"] = Potential.get_number_components()
def prepare_simulation(self): r"""Set up a Hagedorn propagator for the simulation loop. Set the potential and initial values according to the configuration. :raise: :py:class:`ValueError` For invalid or missing input data. """ # The potential instance potential = BlockFactory().create_potential(self.parameters) # Project the initial values to the canonical basis BT = BasisTransformationHAWP(potential) # Finally create and initialize the propagator instance # TODO: Attach the "leading_component to the hawp as codata # TODO: Clean up this ugly if tree if self.parameters["propagator"] == "magnus_split": from MagnusPropagator import MagnusPropagator self.propagator = MagnusPropagator(self.parameters, potential) elif self.parameters["propagator"] == "semiclassical": from SemiclassicalPropagator import SemiclassicalPropagator self.propagator = SemiclassicalPropagator(self.parameters, potential) elif self.parameters["propagator"] == "hagedorn": from HagedornPropagator import HagedornPropagator self.propagator = HagedornPropagator(self.parameters, potential) else: raise NotImplementedError("Unknown propagator type: " + self.parameters["propagator"]) # Create suitable wavepackets chi = self.parameters["leading_component"] for packet_descr in self.parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Transform to canonical basis BT.set_matrix_builder(packet.get_innerproduct()) BT.transform_to_canonical(packet) # And hand over self.propagator.add_wavepacket((packet, chi)) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() key = ("q","p","Q","P","S","adQ") for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_wavepacket(self.parameters, timeslots=slots, blockid=bid, key=key) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_wavepacket_description(packet.get_description()) # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(key=key), timestep=0, key=key) # Basis shapes for shape in packet.get_basis_shapes(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shapes(), timestep=0)
def __init__(self, n): self.blockFactory = BlockFactory() self.grid = [] #add second, empty grid for i in range(n): self.grid.append([]) for j in range(n): self.grid[i].append(None) #create grid filled with blocks for i in range(n): self.grid.append([]) for j in range(n): cellPos = (j * (cellWidth + padding), (n + i) * (cellHeight + padding)) self.grid[n + i].append(self.blockFactory.build(cellPos)) self.n = n self.center = (n * (cellWidth + padding) / 2, n * (cellHeight + padding) + n * (cellHeight + padding) / 2) #cursor set to (0,0) on the grid self.cursor = Cursor(n, n, [n - 1, 0])
def load_wavepacket_inhomogeneous(iom, timestep, blockid=0): r"""Utility function to load an inhomogeneous wavepacket from an :py:class:`IOManager` instance. :param iom: The :py:class:`IOManager` instance from which to load data. :param timestep: Load the data corresponding to the given `timestep`. :param blockid: The `datablock` from which to read the data. Default is the block with `blockid=0`. Note: This function is a pure utility function and is not efficient. It is built for interactive use only and should not be use in scripts. """ if not iom.has_inhomogwavepacket(blockid=blockid): print("There is no (inhomogeneous) wavepacket to load in block "+str(blockid)) return BF = BlockFactory() wpd = iom.load_inhomogwavepacket_description(blockid=blockid) HAWP = BF.create_wavepacket(wpd) # Basis shapes BS_descr = iom.load_inhomogwavepacket_basisshapes(blockid=blockid) BS = {} for ahash, descr in BS_descr.iteritems(): BS[ahash] = BF.create_basis_shape(descr) KEY = ("q","p","Q","P","S","adQ") # Retrieve simulation data params = iom.load_inhomogwavepacket_parameters(timestep=timestep, blockid=blockid, key=KEY) hashes, coeffs = iom.load_inhomogwavepacket_coefficients(timestep=timestep, get_hashes=True, blockid=blockid) # Configure the wavepacket HAWP.set_parameters(params, key=KEY) HAWP.set_basis_shapes([ BS[int(ha)] for ha in hashes ]) HAWP.set_coefficients(coeffs) return HAWP
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. """ # The potential instance potential = BlockFactory().create_potential(self.parameters) # Compute the position space grid points grid = BlockFactory().create_grid(self.parameters) # Construct initial values I = Initializer(self.parameters) initialvalues = I.initialize_for_fourier(grid) # Transform the initial values to the canonical basis BT = BasisTransformationWF(potential) BT.set_grid(grid) BT.transform_to_canonical(initialvalues) # Finally create and initialize the propagator instace self.propagator = FourierPropagator(potential, initialvalues, self.parameters) # Write some initial values to disk slots = self._tm.compute_number_saves() self.IOManager.add_grid(self.parameters, blockid="global") self.IOManager.add_fourieroperators(self.parameters) self.IOManager.add_wavefunction(self.parameters, timeslots=slots) self.IOManager.save_grid(grid.get_nodes(flat=False), blockid="global") self.IOManager.save_fourieroperators(self.propagator.get_operators()) self.IOManager.save_wavefunction(initialvalues.get_values(), timestep=0)
def __init__(self, parameters, potential, packets=[]): r"""Initialize a new :py:class:`HagedornPropagator` instance. :param parameters: A :py:class:`ParameterProvider` instance containing at least the key ``dt`` for providing the timestep :math:`\tau`. :type parameters: A :py:class:`ParameterProvider` instance :param potential: The potential :math:`V(x)` the wavepacket :math:`\Psi` feels during the time propagation. :param packet: The initial homogeneous Hagedorn wavepacket :math:`\Psi` we propagate in time. :raises ValueError: If the number of components of :math:`\Psi` does not match the number of energy levels :math:`\lambda_i` of the potential. """ # The potential :math:`V(x)` the packet(s) feel. self._potential = potential # Number :math:`N` of components the wavepacket :math:`\Psi` has got. self._number_components = self._potential.get_number_components() self._dimension = self._potential.get_dimension() # A list of Hagedorn wavepackets :math:`\Psi` together with some codata # like the leading component :math:`\chi` which is the index of the eigenvalue # :math:`\lambda_\chi` of the potential :math:`V` that is responsible for # propagating the Hagedorn parameters. # TODO: We assume a list of (packet, leading_component) tuples here. Generalize tuples to dicts! # TODO: Do not use a list but better use a hashtable by packet IDs? self._packets = packets[:] # Keep a reference to the parameter provider instance self._parameters = parameters self._dt = self._parameters["dt"] # The relative mass scaling matrix M if self._parameters.has_key("mass_scaling"): self._M = atleast_2d(self._parameters["mass_scaling"]) assert self._M.shape == (self._dimension, self._dimension) self._Minv = inv(self._M) else: # No mass matrix given. Scale all masses equally self._M = eye(self._dimension) self._Minv = self._M # Decide about the matrix exponential algorithm to use self.__dict__["_matrix_exponential"] = BlockFactory().create_matrixexponential(parameters) # Precalculate the potential splittings needed self._prepare_potential()
def addBlock(self): ## create block bf = BlockFactory(self.height, self.width, self.wall, self.ground) bf.createBlocK() ## connect blocks lastBlockIndex = len(self.row) - 1 endingYPoint = self.row[lastBlockIndex].getEndingYPoint() if endingYPoint != bf.getStartingYPoint(): bf.connectBlockHorizontal(endingYPoint) ## add block to row self.row.append(bf)
def prepare_simulation(self): r"""Set up a Hagedorn propagator for the simulation loop. Set the potential and initial values according to the configuration. :raise ValueError: For invalid or missing input data. """ # The potential instance potential = BlockFactory().create_potential(self.parameters) # Project the initial values to the canonical basis BT = BasisTransformationHAWP(potential) # Finally create and initialize the propagator instace # TODO: Attach the "leading_component to the hawp as codata self.propagator = HagedornPropagator(self.parameters, potential) # Create suitable wavepackets chi = self.parameters["leading_component"] for packet_descr in self.parameters["initvals"]: packet = BlockFactory().create_wavepacket(packet_descr) # Transform to canonical basis BT.set_matrix_builder(packet.get_quadrature()) BT.transform_to_canonical(packet) # And hand over self.propagator.add_wavepacket((packet, chi)) # Add storage for each packet npackets = len(self.parameters["initvals"]) slots = self._tm.compute_number_saves() for i in xrange(npackets): bid = self.IOManager.create_block() self.IOManager.add_wavepacket(self.parameters, timeslots=slots, blockid=bid) # Write some initial values to disk for packet in self.propagator.get_wavepackets(): self.IOManager.save_wavepacket_description(packet.get_description()) # Pi self.IOManager.save_wavepacket_parameters(packet.get_parameters(), timestep=0) # Basis shapes for shape in packet.get_basis_shape(): self.IOManager.save_wavepacket_basisshapes(shape) # Coefficients self.IOManager.save_wavepacket_coefficients(packet.get_coefficients(), packet.get_basis_shape(), timestep=0)
moveLeft = [-blockSize,0] # The boardColor will be a solid black (for now) boardColor = (0,0,0,255) # Score is set to 0 at the beginning of the game score = 0 # Set the size of the display to the size we defined above, and store it as screen screen = pygame.display.set_mode(size) # The board will be the entire screen size (so no hold piece or scoreboard, for now) board = pygame.Surface(screen.get_size(),pygame.SRCALPHA) board.fill(boardColor) # Initialize a blockfactory (a custom class in the BlockFactory.py file) bFactory = BlockFactory(board, blockSize, boardColor) # Generate a mino (a custom class in the BlockFactory.py file) block, gameOver = bFactory.generateMino() # We are ready to start the game! # Here we grab the current time so that we can measure game time relative to it # This returns time in milliseconds dropTime = pygame.time.get_ticks() # Cannonical game loop, run forever until game over while 1: # Get current time currTime = pygame.time.get_ticks() # More than the drop speed time has passed since the last drop
from BaseBlock import BaseBlock from BlockArmor import BlockArmor from GridCell import GridCellContainer from BlockFactory import BlockFactory import pygame pygame.init() screen = pygame.display.set_mode((1280, 720)) center = (1280 / 2 - 25, 720 / 2 - 25) done = False clock = pygame.time.Clock() factory = BlockFactory() cell = factory.build(center) offset = (20, 20) scale = 1 while not done: events = pygame.event.get() for event in events: if event.type == pygame.QUIT: done = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_DELETE: cell = factory.build(center) scale -= .025 if scale <= 0:
def appendBlock(self): bf = BlockFactory(self.height, self.width, self.wall, self.ground) bf.createBlocK() self.row.append(bf)
class ColorGrid: # None = empty cell # 1 - 4 = color cell # (n) by (n) grid def __init__(self, n): self.blockFactory = BlockFactory() self.grid = [] #add second, empty grid for i in range(n): self.grid.append([]) for j in range(n): self.grid[i].append(None) #create grid filled with blocks for i in range(n): self.grid.append([]) for j in range(n): cellPos = (j * (cellWidth + padding), (n + i) * (cellHeight + padding)) self.grid[n + i].append(self.blockFactory.build(cellPos)) self.n = n self.center = (n * (cellWidth + padding) / 2, n * (cellHeight + padding) + n * (cellHeight + padding) / 2) #cursor set to (0,0) on the grid self.cursor = Cursor(n, n, [n - 1, 0]) def rotateClock(self): for i in range(3): self.rotateCounter() def rotateCounter(self): N = self.n for x in range(0, int(N / 2)): for y in range(x, N - x - 1): top = ((x + N), y) right = ((y + N), (N - 1 - x)) bottom = ((N - 1 - x + N), (N - 1 - y)) left = ((N - 1 - y + N), (x)) self.grid[top[0]][top[1]].rotate() self.grid[right[0]][right[1]].rotate() self.grid[bottom[0]][bottom[1]].rotate() self.grid[left[0]][left[1]].rotate() self.swapCells(top, left) self.swapCells(top, bottom) self.swapCells(top, right) self.rotateCursor(True) #coord - (row,col) def getCell(self, coord): return self.grid[coord[0]][coord[1]] #A / B = (row,col) of desired cells def swapCells(self, A, B): temp = self.grid[A[0]][A[1]] self.grid[A[0]][A[1]] = self.grid[B[0]][B[1]] self.grid[B[0]][B[1]] = temp cellA = self.grid[A[0]][A[1]] cellB = self.grid[B[0]][B[1]] if cellA != None: cellA.updatePosition( (A[1] * (cellWidth + padding), A[0] * (cellHeight + padding))) if cellB != None: cellB.updatePosition( (B[1] * (cellWidth + padding), B[0] * (cellHeight + padding))) def moveCursor(self, key): self.cursor.move(key) def rotateCursor(self, counter=True): currPos = self.cursor.getPosition() n = self.n xMin = min(currPos[1], n - currPos[1] - 1) yMin = min(currPos[0], n - currPos[0] - 1) layer = min(xMin, yMin) #top if currPos[0] - layer == 0: if counter == False: #top - > right self.cursor.setPosition((currPos[1], self.n - 1 - layer)) else: #top -> left self.cursor.setPosition((self.n - currPos[1] - 1, layer)) #bottom elif currPos[0] + layer == self.n - 1: if counter == False: #bottom -> left self.cursor.setPosition((currPos[1], layer)) else: #bottom -> right self.cursor.setPosition( (self.n - currPos[1] - 1, self.n - 1 - layer)) else: #left if currPos[1] - layer == 0: if counter == False: #left -> top self.cursor.setPosition((layer, self.n - currPos[0] - 1)) else: #left -> bottom self.cursor.setPosition((self.n - 1 - layer, currPos[0])) #right else: if counter == False: #right -> bottom self.cursor.setPosition( (self.n - 1 - layer, self.n - currPos[0] - 1)) else: #right -> top self.cursor.setPosition((layer, currPos[0])) def deleteBlock(self): self.grid[self.cursor.position[0] + self.n][self.cursor.position[1]] = None def getVerticalMatches(self, minMatchLength): matchSet = set([]) #check bottom -> top for col in range(self.n): matchStack = [] #only check the bottom grid (n/2) for row in range(self.n - 1, self.n * 2, 1): cell = self.grid[row][col] if cell != None: if len(matchStack) == 0 or cell.getColor() == self.grid[ matchStack[0][0]][matchStack[0][1]].getColor(): matchStack.append((row, col)) else: if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) matchStack = [(row, col)] else: if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) matchStack = [] if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) return matchSet def getHorizontalMatches(self, minMatchLength): matchSet = set([]) #check L -> R #only check the bottom grid (n/2) for rowIndex in range(self.n - 1, self.n * 2, 1): rowList = self.grid[rowIndex] matchStack = [] for cellIndex, cell in enumerate(rowList): if cell != None: if len(matchStack) == 0 or cell.getColor() == self.grid[ matchStack[0][0]][matchStack[0][1]].getColor(): matchStack.append((rowIndex, cellIndex)) else: if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) matchStack = [(rowIndex, cellIndex)] else: if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) matchStack = [] if len(matchStack) >= minMatchLength: for cell in matchStack: matchSet.add(cell) return matchSet def getMatches(self, minMatchLength): return self.getHorizontalMatches(minMatchLength).union( self.getVerticalMatches(minMatchLength)) def removeMatches(self, matchList): for matchCell in matchList: self.grid[matchCell[0]][matchCell[1]] = None def moveCellsDown(self): colList = [] for col in range(self.n): emptyStack = [] toMove = [] for row in range(self.n * 2 - 1, -1, -1): if self.grid[row][col] == None: emptyStack.append((row, col)) else: if self.grid[row][col].getIsMoveable( ) and len(emptyStack) > 0: toMove.append(((row, col), emptyStack.pop(0))) emptyStack.append((row, col)) if self.grid[row][col].getIsMoveable() == False: emptyStack = [] if len(toMove) > 0: colList.append(toMove) if len(colList) > 0: return colList return None def getEmptyCells(self): emptyCellList = [] for col in range(self.n): for row in range(self.n, self.n * 2, 1): if self.grid[row][col] == None: emptyCellList.append((row, col)) else: break return emptyCellList def spawnNewCells(self, emptyCells): for cell in emptyCells: self.grid[cell[0] - self.n][cell[1]] = self.blockFactory.build( (cell[1] * (cellWidth + padding), (cell[0] - self.n) * (cellHeight + padding))) def scaleCells(self, cellList, factor): for index in cellList: self.grid[index[0]][index[1]].scale(factor) def rotateCells(self, cellList, factor): for index in cellList: self.grid[index[0]][index[1]].rotateInPlace(factor) def rotateGrid(self, factor): #t = (self.center[0] - 30, self.n*60 + int(self.n/2)*60) t = (self.center[0] - 5, self.center[1] - 5) for row in self.grid: for cell in row: if cell != None: #cell.rotateInPlace(-factor) cell.rotateAroundPoint(t, factor) self.cursor.poly.rotateAroundPoint(t, factor) def draw(self, screen, position, drawCursor=True): for row in range(self.n * 2): for col in range(self.n): if self.grid[row][col] != None: self.grid[row][col].draw(screen, position) cursorX = self.cursor.position[1] * (cellWidth + padding) - ( abs(cellWidth - self.cursor.width)) / 2 cursorY = (self.cursor.position[0] + self.n) * ( cellHeight + padding) - (abs(cellHeight - self.cursor.height)) / 2 #print(position) if drawCursor: #self.cursor.draw(screen, (position[0] + cursorX, position[1] + cursorY)) self.cursor.draw(screen, position) def __str__(self): outStr = "" for i in range(len(self.grid)): for cell in self.grid[i]: cellStr = str(cell) if cell == None: cellStr = "0" for j in range(len(cellStr), 3): cellStr += " " outStr += cellStr + " " outStr += "\n" return outStr