diff --git a/src/Mod/Ship/CMakeLists.txt b/src/Mod/Ship/CMakeLists.txt index 5f0314abd..432c91576 100644 --- a/src/Mod/Ship/CMakeLists.txt +++ b/src/Mod/Ship/CMakeLists.txt @@ -145,9 +145,11 @@ SET(SimRun_SRCS simRun/Simulation.py simRun/TaskPanel.py simRun/TaskPanel.ui + simRun/clSim/__init__.py + simRun/clSim/initialization.py + simRun/clSim/Utils.py simRun/Sim/__init__.py simRun/Sim/initialization.py - simRun/Sim/Utils.py ) SOURCE_GROUP("simrun" FILES ${SimRun_SRCS}) diff --git a/src/Mod/Ship/Makefile.am b/src/Mod/Ship/Makefile.am index 084e9a877..f2477550b 100644 --- a/src/Mod/Ship/Makefile.am +++ b/src/Mod/Ship/Makefile.am @@ -98,10 +98,11 @@ nobase_data_DATA = \ simRun/Simulation.py \ simRun/TaskPanel.py \ simRun/TaskPanel.ui \ + simRun/clSim/__init__.py \ + simRun/clSim/initialization.py \ + simRun/clSim/Utils.py \ simRun/Sim/__init__.py \ simRun/Sim/initialization.py - simRun/Sim/Utils.py - CLEANFILES = $(BUILT_SOURCES) diff --git a/src/Mod/Ship/simRun/Sim/Utils.py~ b/src/Mod/Ship/simRun/Sim/Utils.py~ deleted file mode 100644 index 7c37bfab2..000000000 --- a/src/Mod/Ship/simRun/Sim/Utils.py~ +++ /dev/null @@ -1,58 +0,0 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2011, 2012 * -#* Jose Luis Cercos Pita * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** - -# FreeCAD -from shipUtils import Paths - -# pyOpenCL -import pyopencl as cl -import numpy as np - -# Standard -import math - -def loadProgram(context, file): - """ Loads a file and comnpile it. - @param context OpenCL context where apply. - @param file File to load and compile. - @return Ready to use OpenCL program. - """ - f = open(file, 'r') - str = "".join(f.readlines()) - print(str) - return cl.Program(context, str).build() - -def clPath(): - """ Gets the OpenCL kernels path - @return OpenCL kernels path - """ - path = Paths.modulePath() + "/OpenCL" - return path - -def globalSize(n): - """ Compute global size from amount of data. - @param n Amount of data. - @return global size. - """ - localSize = 256.0 - return int(math.ceil(n/localSize)*localSize) diff --git a/src/Mod/Ship/simRun/Sim/__init__.py b/src/Mod/Ship/simRun/Sim/__init__.py index 2fcb8e495..f5acc886b 100644 --- a/src/Mod/Ship/simRun/Sim/__init__.py +++ b/src/Mod/Ship/simRun/Sim/__init__.py @@ -21,4 +21,4 @@ #* * #*************************************************************************** -import initialization, Utils \ No newline at end of file +import initialization diff --git a/src/Mod/Ship/simRun/Sim/initialization.py b/src/Mod/Ship/simRun/Sim/initialization.py index 90bdf5bfa..1c443ca85 100644 --- a/src/Mod/Ship/simRun/Sim/initialization.py +++ b/src/Mod/Ship/simRun/Sim/initialization.py @@ -21,65 +21,62 @@ #* * #*************************************************************************** -# Simulation stuff -from Utils import * - -# pyOpenCL -import pyopencl as cl +# numpy import numpy as np +grav=9.81 + class perform: - def __init__(self, context, queue, FSmesh, waves): + def __init__(self, FSmesh, waves, context=None, queue=None): """ Constructor, includes program loading. - @param context OpenCL context where apply. - @param queue OpenCL command queue. @param FSmesh Initial free surface mesh. @param waves Considered simulation waves (A,T,phi,heading). + @param context OpenCL context where apply. Only for compatibility, + must be None. + @param queue OpenCL command queue. Only for compatibility, + must be None. """ self.context = context self.queue = queue - self.program = loadProgram(context, clPath() + "/simInit.cl") self.loadData(FSmesh, waves) self.execute() def loadData(self, FSmesh, waves): - """ Convert data to numpy format, and create OpenCL - buffers. + """ Convert data to numpy format. @param FSmesh Initial free surface mesh. @param waves Considered simulation waves (A,T,phi,heading). """ - mf = cl.mem_flags nx = len(FSmesh) ny = len(FSmesh[0]) nW = len(waves) # Mesh data - p = np.ndarray((nx*ny, 4), dtype=np.float32) - n = np.ndarray((nx*ny, 4), dtype=np.float32) - a = np.ndarray((nx*ny, 1), dtype=np.float32) + p = np.ndarray((nx,ny, 3), dtype=np.float32) + v = np.ndarray((nx,ny, 3), dtype=np.float32) + f = np.ndarray((nx,ny, 3), dtype=np.float32) + n = np.ndarray((nx,ny, 3), dtype=np.float32) + a = np.ndarray((nx,ny, 1), dtype=np.float32) + phi = np.ndarray((nx,ny, 1), dtype=np.float32) + Phi = np.ndarray((nx,ny, 1), dtype=np.float32) for i in range(0, nx): for j in range(0, ny): - id = i*ny + j pos = FSmesh[i][j].pos normal = FSmesh[i][j].normal area = FSmesh[i][j].area - p[id,0] = pos.x - p[id,1] = pos.y - p[id,2] = pos.z - p[id,3] = 1. - n[id,0] = normal.x - n[id,1] = normal.y - n[id,2] = normal.z - n[id,3] = 0. - a[id,0] = area - p_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=p) - n_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=n) - a_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=a) - v_cl = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny*4 * np.dtype('float32').itemsize) - f_cl = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny*4 * np.dtype('float32').itemsize) - phi = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny * np.dtype('float32').itemsize) - Phi = cl.Buffer(self.context, mf.READ_WRITE, size = nx*ny * np.dtype('float32').itemsize) - self.fs = {'Nx':nx, 'Ny':ny, 'pos':p_cl, 'vel':v_cl, 'acc':f_cl, \ - 'normal':n_cl, 'area':a_cl, 'velPot':phi, 'accPot':Phi} + p[i,j,0] = pos.x + p[i,j,1] = pos.y + p[i,j,2] = pos.z + v[i,j,0] = 0. + v[i,j,1] = 0. + v[i,j,2] = 0. + f[i,j,0] = 0. + f[i,j,1] = 0. + f[i,j,2] = 0. + n[i,j,0] = normal.x + n[i,j,1] = normal.y + n[i,j,2] = normal.z + a[i,j] = area + self.fs = {'Nx':nx, 'Ny':ny, 'pos':p, 'vel':v, 'acc':f, \ + 'normal':n, 'area':a, 'velPot':phi, 'accPot':Phi} # Waves data w = np.ndarray((nW, 4), dtype=np.float32) for i in range(0,nW): @@ -87,27 +84,31 @@ class perform: w[i,1] = waves[i][1] w[i,2] = waves[i][2] w[i,3] = waves[i][3] - w_cl = cl.Buffer(self.context, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=w) - self.waves = {'N':nW, 'data':w_cl} - # Ensure that all data has been written - self.queue.finish() + self.waves = {'N':nW, 'data':w} def execute(self): """ Compute initial conditions. """ - # Global size computation - N = np.ndarray((2, 1), dtype=np.uint32) - N[0] = self.fs['Nx'] - N[1] = self.fs['Ny'] - n = np.uint32(self.waves['N']) - gSize = (globalSize(N[0]),globalSize(N[1]),) - # Kernel arguments - kernelargs = (self.fs['pos'], - self.fs['vel'], - self.fs['acc'], - self.waves['data'], - self.fs['velPot'], - self.fs['accPot'], - N, n) - # Kernel launch - self.program.FS(self.queue, gSize, None, *(kernelargs)) - self.queue.finish() + nx = self.fs['Nx'] + ny = self.fs['Ny'] + for i in range(0,nx): + for j in range(0,ny): + for w in self.waves['data']: + A = w[0] + T = w[1] + phase = w[2] + heading = np.pi*w[3]/180.0 + wl = 0.5 * grav / np.pi * T*T + k = 2.0*np.pi/wl + frec = 2.0*np.pi/T + pos = self.fs['pos'][i,j] + l = pos[0]*np.cos(heading) + pos[1]*np.sin(heading) + amp = A*np.sin(k*l + phase) + self.fs['pos'][i,j][2] = self.fs['pos'][i,j][2] + amp + amp = frec*A*np.cos(k*l + phase) + self.fs['vel'][i,j][2] = self.fs['vel'][i,j][2] - amp + amp = frec*frec*A*np.sin(k*l + phase) + self.fs['acc'][i,j][2] = self.fs['acc'][i,j][2] - amp + amp = grav/frec*A*np.sin(k*l + phase) + self.fs['velPot'][i,j] = self.fs['velPot'][i,j] + amp + amp = grav*A*np.cos(k*l + phase) + self.fs['accPot'][i,j] = self.fs['accPot'][i,j] + amp diff --git a/src/Mod/Ship/simRun/Simulation.py b/src/Mod/Ship/simRun/Simulation.py index 6ffd9fe0c..a06f6b0d2 100644 --- a/src/Mod/Ship/simRun/Simulation.py +++ b/src/Mod/Ship/simRun/Simulation.py @@ -34,9 +34,6 @@ import FreeCAD,FreeCADGui from FreeCAD import Base, Vector import Part -# Simulation stuff -from Sim import initialization - # Ship design module from shipUtils import Paths, Translator, Math @@ -65,8 +62,12 @@ class FreeCADShipSimulation(threading.Thread): self.active = False # Build OpenCL context and command queue self.device = device - self.context = cl.Context(devices=[self.device]) - self.queue = cl.CommandQueue(self.context) + if self.device == None: # Can't use OpenCL + self.context = None + self.queue = None + else: + self.context = cl.Context(devices=[self.device]) + self.queue = cl.CommandQueue(self.context) # Storage data self.endTime = endTime self.output = output @@ -77,10 +78,14 @@ class FreeCADShipSimulation(threading.Thread): """ Runs the simulation. """ self.active = True - # Perform work here + # Simulation stuff + if self.device == None: + from Sim import initialization + else: + from clSim import initialization msg = Translator.translate("\t[Sim]: Initializating OpenCL...\n") FreeCAD.Console.PrintMessage(msg) - init = initialization.perform(self.context,self.queue,self.FSmesh,self.waves) + init = initialization.perform(self.FSmesh,self.waves,self.context,self.queue) msg = Translator.translate("\t[Sim]: Iterating (outputs will be noticed)...\n") FreeCAD.Console.PrintMessage(msg) while self.active: diff --git a/src/Mod/Ship/simRun/Simulation.py~ b/src/Mod/Ship/simRun/Simulation.py~ deleted file mode 100644 index 03a443779..000000000 --- a/src/Mod/Ship/simRun/Simulation.py~ +++ /dev/null @@ -1,107 +0,0 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2011, 2012 * -#* Jose Luis Cercos Pita * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** - -import time -from math import * -import threading - -# pyOpenCL -import pyopencl as cl -import numpy as np - -# FreeCAD -import FreeCAD,FreeCADGui -from FreeCAD import Base, Vector -import Part - -# Simulation stuff -from Sim import initialization - -# Ship design module -from shipUtils import Paths, Translator, Math - -class Singleton(type): - def __init__(cls, name, bases, dct): - cls.__instance = None - type.__init__(cls, name, bases, dct) - - def __call__(cls, *args, **kw): - if cls.__instance is None: - cls.__instance = type.__call__(cls, *args,**kw) - return cls.__instance - -class FreeCADShipSimulation(threading.Thread): - __metaclass__ = Singleton - def __init__ (self, device, endTime, output, FSmesh, waves): - """ Thread constructor. - @param device Device to use. - @param endTime Maximum simulation time. - @param output [Rate,Type] Output rate, Type=0 if FPS, 1 if IPF. - @param FSmesh Free surface mesh faces. - @param waves Waves parameters (A,T,phi,heading) - """ - threading.Thread.__init__(self) - # Setup as stopped - self.active = False - # Build OpenCL context and command queue - self.device = device - self.context = cl.Context(devices=[self.device]) - self.queue = cl.CommandQueue(self.context) - # Storage data - self.endTime = endTime - self.output = output - self.FSmesh = FSmesh - self.waves = waves - - def run(self): - """ Runs the simulation. - """ - self.active = True - # Perform work here - msg = Translator.translate("\t[Sim]: Initializating OpenCL...\n") - FreeCAD.Console.PrintMessage(msg) - init = initialization.perform(self.context,self.queue,self.FSmesh,self.waves) - msg = Translator.translate("\t[Sim]: Iterating (outputs will be noticed)...\n") - FreeCAD.Console.PrintMessage(msg) - while self.active: - print("Im thread, Im running...") - time.sleep(1) - # ... - print("Im thread, step done!") - msg = Translator.translate("\t[Sim]: Output performed!\n") - FreeCAD.Console.PrintMessage(msg) - # Set thread as stopped (and prepare it to restarting) - self.active = False - threading.Event().set() - threading.Thread.__init__(self) - - def stop(self): - """ Call to stop execution. - """ - self.active = False - - def isRunning(self): - """ Report thread state - @return True if thread is running, False otherwise. - """ - return self.active diff --git a/src/Mod/Ship/simRun/TaskPanel.py b/src/Mod/Ship/simRun/TaskPanel.py index 2e41ff15a..d2c34b8b7 100644 --- a/src/Mod/Ship/simRun/TaskPanel.py +++ b/src/Mod/Ship/simRun/TaskPanel.py @@ -1,203 +1,204 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2011, 2012 * -#* Jose Luis Cercos Pita * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with this program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** - -# FreeCAD modules -import FreeCAD as App -import FreeCADGui as Gui -# Qt library -from PyQt4 import QtGui,QtCore -# pyOpenCL -import pyopencl as cl -# Module -import SimInstance -from shipUtils import Paths, Translator -from Simulation import FreeCADShipSimulation as Sim - -import time - -class TaskPanel: - def __init__(self): - self.ui = Paths.modulePath() + "/simRun/TaskPanel.ui" - self.sim = False - - def accept(self): - msg = Translator.translate("Building data...\n") - App.Console.PrintMessage(msg) - # Get GUI data - endTime = self.form.time.value() - output = [] - output.append(self.form.output.value()) - output.append(self.form.outputType.currentIndex()) - devId = self.form.device.currentIndex() - # Get OpenCL device - count = 0 - platforms = cl.get_platforms() - for p in platforms: - devs = p.get_devices() - for d in devs: - if count == devId: - device = d - count = count + 1 - # Get free surfaces data - FSMesh = SimInstance.FSMesh(self.sim) - wData = self.sim.Waves - wDir = self.sim.Waves_Dir - waves = [] - for i in range(0,len(wData)): - waves.append([wData[i].x, wData[i].y, wData[i].z, wDir[i]]) - msg = Translator.translate("Launching simulation...\n") - App.Console.PrintMessage(msg) - # Build simulation thread - simulator = Sim(device, endTime, output, FSMesh, waves) - simulator.start() - msg = Translator.translate("Done!\n") - App.Console.PrintMessage(msg) - return True - - def reject(self): - return True - - def clicked(self, index): - pass - - def open(self): - pass - - def needsFullSpace(self): - return True - - def isAllowedAlterSelection(self): - return False - - def isAllowedAlterView(self): - return True - - def isAllowedAlterDocument(self): - return False - - def helpRequested(self): - pass - - def setupUi(self): - mw = self.getMainWindow() - form = mw.findChild(QtGui.QWidget, "TaskPanel") - form.time = form.findChild(QtGui.QDoubleSpinBox, "SimTime") - form.output = form.findChild(QtGui.QDoubleSpinBox, "Output") - form.outputType = form.findChild(QtGui.QComboBox, "OutputType") - form.device = form.findChild(QtGui.QComboBox, "Device") - self.form = form - # Initial values - if self.initValues(): - return True - self.retranslateUi() - # Connect Signals and Slots - # QtCore.QObject.connect(form.time, QtCore.SIGNAL("valueChanged(double)"), self.onData) - - def getMainWindow(self): - "returns the main window" - # using QtGui.qApp.activeWindow() isn't very reliable because if another - # widget than the mainwindow is active (e.g. a dialog) the wrong widget is - # returned - toplevel = QtGui.qApp.topLevelWidgets() - for i in toplevel: - if i.metaObject().className() == "Gui::MainWindow": - return i - raise Exception("No main window found") - - def initValues(self): - """ Set initial values for fields - """ - # Get objects - selObjs = Gui.Selection.getSelection() - if not selObjs: - msg = Translator.translate("Ship simulation instance must be selected (no object selected)\n") - App.Console.PrintError(msg) - return True - for i in range(0,len(selObjs)): - obj = selObjs[i] - # Test if is a ship instance - props = obj.PropertiesList - try: - props.index("IsShipSimulation") - except ValueError: - continue - if obj.IsShipSimulation: - # Test if another ship already selected - if self.sim: - msg = Translator.translate("More than one ship simulation selected (extra simulations will be neglected)\n") - App.Console.PrintWarning(msg) - break - self.sim = obj - # Test if any valid ship was selected - if not self.sim: - msg = Translator.translate("Ship simulation instance must be selected (no valid simulation found at selected objects)\n") - App.Console.PrintError(msg) - return True - # Get the list of devices - devices = [] - platforms = cl.get_platforms() - for p in platforms: - devs = p.get_devices() - for d in devs: - devices.append([p,d]) - dname = d.get_info(cl.device_info.NAME) - pname = p.get_info(cl.platform_info.NAME) - self.form.device.addItem(dname + " (" + pname + ")") - if not len(devices): - msg = Translator.translate("This tool requires an active OpenCL context to work\n") - App.Console.PrintError(msg) - return True - msg = Translator.translate("Ready to work\n") - App.Console.PrintMessage(msg) - return False - - def retranslateUi(self): - """ Set user interface locale strings. - """ - self.form.setWindowTitle(Translator.translate("Run the simulation")) - self.form.findChild(QtGui.QLabel, "SimTimeLabel").setText(Translator.translate("Simulation time")) - self.form.findChild(QtGui.QLabel, "OutputLabel").setText(Translator.translate("Output")) - self.form.findChild(QtGui.QLabel, "DeviceLabel").setText(Translator.translate("OpenCL device")) - -def createTask(): - panel = TaskPanel() - Gui.Control.showDialog(panel) - if panel.setupUi(): - Gui.Control.closeDialog(panel) - return None - return panel - -def stopSimulation(): - try: - simulator = Sim() - if not simulator.isRunning(): - msg = Translator.translate("Simulation already stopped\n") - App.Console.PrintWarning(msg) - return - except: - msg = Translator.translate("Any active simulation to stop!\n") - App.Console.PrintError(msg) - return - simulator.stop() - msg = Translator.translate("Simulation will stop at the end of actual iteration\n") - App.Console.PrintMessage(msg) +#*************************************************************************** +#* * +#* Copyright (c) 2011, 2012 * +#* Jose Luis Cercos Pita * +#* * +#* This program is free software; you can redistribute it and/or modify * +#* it under the terms of the GNU Lesser General Public License (LGPL) * +#* as published by the Free Software Foundation; either version 2 of * +#* the License, or (at your option) any later version. * +#* for detail see the LICENCE text file. * +#* * +#* This program is distributed in the hope that it will be useful, * +#* but WITHOUT ANY WARRANTY; without even the implied warranty of * +#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +#* GNU Library General Public License for more details. * +#* * +#* You should have received a copy of the GNU Library General Public * +#* License along with this program; if not, write to the Free Software * +#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +#* USA * +#* * +#*************************************************************************** + +# FreeCAD modules +import FreeCAD as App +import FreeCADGui as Gui +# Qt library +from PyQt4 import QtGui,QtCore +# pyOpenCL +import pyopencl as cl +# Module +import SimInstance +from shipUtils import Paths, Translator +from Simulation import FreeCADShipSimulation as Sim + +import time + +class TaskPanel: + def __init__(self): + self.ui = Paths.modulePath() + "/simRun/TaskPanel.ui" + self.sim = False + + def accept(self): + msg = Translator.translate("Building data...\n") + App.Console.PrintMessage(msg) + # Get GUI data + endTime = self.form.time.value() + output = [] + output.append(self.form.output.value()) + output.append(self.form.outputType.currentIndex()) + devId = self.form.device.currentIndex() - 1 # First is not OpenCL + # Get OpenCL device + device = None + count = 0 + platforms = cl.get_platforms() + for p in platforms: + devs = p.get_devices() + for d in devs: + if count == devId: + device = d + count = count + 1 + # Get free surfaces data + FSMesh = SimInstance.FSMesh(self.sim) + wData = self.sim.Waves + wDir = self.sim.Waves_Dir + waves = [] + for i in range(0,len(wData)): + waves.append([wData[i].x, wData[i].y, wData[i].z, wDir[i]]) + msg = Translator.translate("Launching simulation...\n") + App.Console.PrintMessage(msg) + # Build simulation thread + simulator = Sim(device, endTime, output, FSMesh, waves) + simulator.start() + msg = Translator.translate("Done!\n") + App.Console.PrintMessage(msg) + return True + + def reject(self): + return True + + def clicked(self, index): + pass + + def open(self): + pass + + def needsFullSpace(self): + return True + + def isAllowedAlterSelection(self): + return False + + def isAllowedAlterView(self): + return True + + def isAllowedAlterDocument(self): + return False + + def helpRequested(self): + pass + + def setupUi(self): + mw = self.getMainWindow() + form = mw.findChild(QtGui.QWidget, "TaskPanel") + form.time = form.findChild(QtGui.QDoubleSpinBox, "SimTime") + form.output = form.findChild(QtGui.QDoubleSpinBox, "Output") + form.outputType = form.findChild(QtGui.QComboBox, "OutputType") + form.device = form.findChild(QtGui.QComboBox, "Device") + self.form = form + # Initial values + if self.initValues(): + return True + self.retranslateUi() + # Connect Signals and Slots + # QtCore.QObject.connect(form.time, QtCore.SIGNAL("valueChanged(double)"), self.onData) + + def getMainWindow(self): + "returns the main window" + # using QtGui.qApp.activeWindow() isn't very reliable because if another + # widget than the mainwindow is active (e.g. a dialog) the wrong widget is + # returned + toplevel = QtGui.qApp.topLevelWidgets() + for i in toplevel: + if i.metaObject().className() == "Gui::MainWindow": + return i + raise Exception("No main window found") + + def initValues(self): + """ Set initial values for fields + """ + # Get objects + selObjs = Gui.Selection.getSelection() + if not selObjs: + msg = Translator.translate("Ship simulation instance must be selected (no object selected)\n") + App.Console.PrintError(msg) + return True + for i in range(0,len(selObjs)): + obj = selObjs[i] + # Test if is a ship instance + props = obj.PropertiesList + try: + props.index("IsShipSimulation") + except ValueError: + continue + if obj.IsShipSimulation: + # Test if another ship already selected + if self.sim: + msg = Translator.translate("More than one ship simulation selected (extra simulations will be neglected)\n") + App.Console.PrintWarning(msg) + break + self.sim = obj + # Test if any valid ship was selected + if not self.sim: + msg = Translator.translate("Ship simulation instance must be selected (no valid simulation found at selected objects)\n") + App.Console.PrintError(msg) + return True + # Get the list of devices + self.form.device.addItem("CPU based version (No OpenCL)") + devices = [] + platforms = cl.get_platforms() + for p in platforms: + devs = p.get_devices() + for d in devs: + devices.append([p,d]) + dname = d.get_info(cl.device_info.NAME) + pname = p.get_info(cl.platform_info.NAME) + self.form.device.addItem(dname + " (" + pname + ")") + if not len(devices): + msg = Translator.translate("Can't find OpenCL devices\n") + App.Console.PrintWarning(msg) + msg = Translator.translate("Ready to work\n") + App.Console.PrintMessage(msg) + return False + + def retranslateUi(self): + """ Set user interface locale strings. + """ + self.form.setWindowTitle(Translator.translate("Run the simulation")) + self.form.findChild(QtGui.QLabel, "SimTimeLabel").setText(Translator.translate("Simulation time")) + self.form.findChild(QtGui.QLabel, "OutputLabel").setText(Translator.translate("Output")) + self.form.findChild(QtGui.QLabel, "DeviceLabel").setText(Translator.translate("OpenCL device")) + +def createTask(): + panel = TaskPanel() + Gui.Control.showDialog(panel) + if panel.setupUi(): + Gui.Control.closeDialog(panel) + return None + return panel + +def stopSimulation(): + try: + simulator = Sim() + if not simulator.isRunning(): + msg = Translator.translate("Simulation already stopped\n") + App.Console.PrintWarning(msg) + return + except: + msg = Translator.translate("Any active simulation to stop!\n") + App.Console.PrintError(msg) + return + simulator.stop() + msg = Translator.translate("Simulation will stop at the end of actual iteration\n") + App.Console.PrintMessage(msg) diff --git a/src/Mod/Ship/simRun/Sim/Utils.py b/src/Mod/Ship/simRun/clSim/Utils.py similarity index 100% rename from src/Mod/Ship/simRun/Sim/Utils.py rename to src/Mod/Ship/simRun/clSim/Utils.py diff --git a/src/Mod/Ship/simRun/Sim/__init__.py~ b/src/Mod/Ship/simRun/clSim/__init__.py similarity index 68% rename from src/Mod/Ship/simRun/Sim/__init__.py~ rename to src/Mod/Ship/simRun/clSim/__init__.py index 30db4bcdb..2fcb8e495 100644 --- a/src/Mod/Ship/simRun/Sim/__init__.py~ +++ b/src/Mod/Ship/simRun/clSim/__init__.py @@ -21,37 +21,4 @@ #* * #*************************************************************************** -# FreeCAD -from shipUtils import Paths - -# pyOpenCL -import pyopencl as cl -import numpy as np - -# Standard -import math - -def loadProgram(context, file): - """ Loads a file and comnpile it. - @param context OpenCL context where apply. - @param file File to load and compile. - @return Ready to use OpenCL program. - """ - f = open(file, 'r') - str = "".join(f.readlines()) - return cl.Program(context, str).build() - -def clPath(): - """ Gets the OpenCL kernels path - @return OpenCL kernels path - """ - path = Paths.modulePath() + "/OpenCL" - return path - -def globalSize(n): - """ Compute global size from amount of data. - @param n Amount of data. - @return global size. - """ - localSize = 256 - return int(math.ceil(n/localSize)) +import initialization, Utils \ No newline at end of file diff --git a/src/Mod/Ship/simRun/Sim/initialization.py~ b/src/Mod/Ship/simRun/clSim/initialization.py similarity index 96% rename from src/Mod/Ship/simRun/Sim/initialization.py~ rename to src/Mod/Ship/simRun/clSim/initialization.py index 63cc9f3aa..5e4f30417 100644 --- a/src/Mod/Ship/simRun/Sim/initialization.py~ +++ b/src/Mod/Ship/simRun/clSim/initialization.py @@ -29,12 +29,12 @@ import pyopencl as cl import numpy as np class perform: - def __init__(self, context, queue, FSmesh, waves): + def __init__(self, FSmesh, waves, context, queue): """ Constructor, includes program loading. - @param context OpenCL context where apply. - @param queue OpenCL command queue. @param FSmesh Initial free surface mesh. @param waves Considered simulation waves (A,T,phi,heading). + @param context OpenCL context where apply. + @param queue OpenCL command queue. """ self.context = context self.queue = queue @@ -100,7 +100,6 @@ class perform: N[1] = self.fs['Ny'] n = np.uint32(self.waves['N']) gSize = (globalSize(N[0]),globalSize(N[1]),) - print(gSize) # Kernel arguments kernelargs = (self.fs['pos'], self.fs['vel'], @@ -108,10 +107,7 @@ class perform: self.waves['data'], self.fs['velPot'], self.fs['accPot'], - N, n) - print('Launching...') + N, n) # Kernel launch self.program.FS(self.queue, gSize, None, *(kernelargs)) - print('Waiting...') self.queue.finish() - print('OK!')