Example #1
0
    def calcHitRate(self, cases, pdf, wind_dict):
        

    def plotContourMaps(self, cases, pdf, wind_dict):
        refinement_length = wind_dict['SHMParams']['domainSize']['refinement_length']
        xi = linspace(-refinement_length,refinement_length,wind_dict['sampleParams']['Nx'])
        yi = xi
        xmesh, ymesh = meshgrid(xi, yi)
        hs = wind_dict['sampleParams']['hSample']
        avgV = zeros((len(hs), len(xi), len(yi)))
        fig_n = 1
        plt = self._r.plot
        for i, case in enumerate(cases):
            lastTime = genfromtxt(path.join(case.name,'PyFoamState.CurrentTime'))
            for hi, h in enumerate(hs):
                data = genfromtxt(path.join(case.name,'surfaces/'+str(int(lastTime))+'/U_agl_'+str(h)+'.raw'))
                # after a long trial and error - matplotlib griddata is shaky and crashes on some grids. scipy.interpolate works on every grid i tested so far
                vi = sc.griddata((data[:,0].ravel(),data[:,1].ravel()), (data[:,3].ravel()**2+data[:,4].ravel()**2)**0.5, (xmesh,ymesh))
                plt.figure(fig_n); fig_n += 1
                plt.title(case.name+'\n at height '+str(h)+' meter agl')
                CS = plt.contourf(xi, yi, vi, 400,cmap=plt.cm.jet,linewidths=0)
                plt.colorbar(CS)
                pdf.savefig()
                # assuming the windDir weights are normalized
                #import pdb; pdb.set_trace()
                avgV[hi, :, :] += vi * wind_dict["caseTypes"]["windRose"]["windDir"][i][0]
        for hi, h in enumerate(hs):
            plt.figure(fig_n); fig_n += 1
            plt.title('average wind velocity at height ' + str(h) + ' meter agl')
            CS = plt.contourf(xi, yi, avgV[hi, :, :], 400, cmap=plt.cm.jet, linewidths=0)
            plt.colorbar(CS)
            pdf.savefig()

    def run_windpyfoam(self, dict):
        """
        Mesh: creating the write snappyHexMeshDict file
        use the right snappyHexMeshDict_XXX.template file with wind_dict
        but --> already at this stage i have to work in a loop according to the
        amount of cases i am asked to solve. each case will be cloned from the
        template case, and then the procedure of
        if doing grid convergance with a single
        foreach dir in {winddirs, grid}:
            1. creating snappyHexMeshDict and blockMeshdict according to flow direction and other parameters
            2. creating the blockMesh
            3. decomposing the domain
            4. creating the snappyHexMesh - running in parallel (sfoam.py or not - depending on user input)
            5. decomposing the created mesh
            6. running pyFoamRunner.py through sfoam (or not - depending on user input)

        After all cases stop running
        7. if exist (usually) - reading real measurements
        8. creating sampleDict according to measurement locations and user input
            (which asks for wind speed contour map at certain height above ground)
        9. sampling (command is "sample")
        10. using the results to calculate the following metrics
            1. for a specific grid size and multiple directions and weights for
            each direction - the power density and average wind speed averaged over
            the direction at specific heights above ground level
            2. for a specific direction and different grid cell sizes - the grid
            error according to some known grid convergence algorithm
            3. a "hit rate" which shows the aggreement of the simulated wind speeds
            and turbulence to the measurements
        """
        if not os.path.exists(dict):
            self._r.error("missing %s file" % dict)
            raise SystemExit
        try:
            wind_dict = ParsedParameterFile(dict)
        except Exception, e:
            self._r.error("failed to parse windPyFoam parameter file:")
            self._r.error(str(e))
            raise SystemExit
        wind_dict['runs'] = self.run_directory('runs')

        # starting the pdf file for accumilating graphical results
        pdf = PdfPages('results.pdf')

        # running the grid convergence routine - for 1 specific direction
        gen = []
        if wind_dict["caseTypes"]["gridConvergence"]:
            gen = self.grid_convergance_params_generator(wind_dict)
        gen = itertools.chain(gen,
                self.wind_rose_params_generator(wind_dict))
        cases = []
        names = []
        for params in gen:
            self._r.debug(params['name'])
            work = self.create_case(wind_dict, params)
            names.append('wind%s' % int(180 / pi * params['phi']))
            cases.append(work)
        # TODO: customizable runArg
        self._r.status('RUNNING CASES')
        runArg = read_dict_string(wind_dict, 'runArg')
        self._r.status(runArg)
        assert(runArg in ['runner', 'plotRunner', 'sfoam'])
        runCases(names=names,
                 n=wind_dict['procnr'], runArg=runArg,
                 cases=[case.name for case in cases])
Example #2
0
class Solver(object):
    def __init__(self, reporter, plots):
        self._r = reporter
        self._plots = plots
        self._fig_n = 1

    def initial_wind_rose_axes(self):
        fig = self.newFigure(figsize=(8, 8),
                             dpi=80,
                             facecolor='w',
                             edgecolor='w')
        rect = [0.1, 0.1, 0.8, 0.8]
        ax = WindroseAxes(fig, rect, axisbg='w')
        fig.add_axes(ax)
        return ax

    def initial_wind_rose_legend(self, ax):
        plt = self._r.plot
        l = ax.legend(axespad=-0.10)
        plt.setp(l.get_texts(), fontsize=8)

    def create_block_mesh_dict(self, work, wind_dict, params):
        phi = params['phi']
        cell_size = params["cell_size"]
        SHM = wind_dict["SHMParams"]
        Href = SHM["domainSize"]["domZ"]
        domainSize = SHM["domainSize"]
        lup, ldown, d = domainSize["fXup"], domainSize["fXdown"], domainSize[
            "fY"]
        x0, y0 = (SHM["centerOfDomain"]["x0"], SHM["centerOfDomain"]["y0"])
        sin_phi = sin(phi)
        cos_phi = cos(phi)
        x1 = x0 - (lup * sin_phi + d / 2 * cos_phi)
        y1 = y0 - (lup * cos_phi - d / 2 * sin_phi)
        x2 = x0 - (lup * sin_phi - d / 2 * cos_phi)
        y2 = y0 - (lup * cos_phi + d / 2 * sin_phi)
        x3 = x0 + (ldown * sin_phi + d / 2 * cos_phi)
        y3 = y0 + (ldown * cos_phi - d / 2 * sin_phi)
        x4 = x0 + (ldown * sin_phi - d / 2 * cos_phi)
        y4 = y0 + (ldown * cos_phi + d / 2 * sin_phi)
        n = floor(d / cell_size)
        m = floor((lup + ldown) / cell_size)
        q = floor((Href - domainSize["z_min"]) / cell_size)
        if n == 0 or m == 0 or q == 0:
            self._r.error("invalid input to block mesh dict:\n" + (
                "d = %(d)f, l = %(l)f, Href = %(Href)f, cell = %(cell)f, cell_size = %(cell_size)f"
                % locals()) + ("n = %(n)f, m = %(m)f, q = %(q)f" % locals()))
        assert (n > 0 and m > 0 and q > 0)
        bmName = path.join(work.constantDir(), "polyMesh/blockMeshDict")
        template = TemplateFile(bmName + ".template")
        template.writeToFile(
            bmName, {
                'X0': x1,
                'X1': x2,
                'X2': x3,
                'X3': x4,
                'Y0': y1,
                'Y1': y2,
                'Y2': y3,
                'Y3': y4,
                'Z0': Href,
                'n': int(n),
                'm': int(m),
                'q': int(q),
                'z_min': domainSize["z_min"]
            })

    def create_SHM_dict(self, work, wind_dict, params):
        self._r.status("calculating SHM parameters")
        phi = params['phi']
        SHM = wind_dict["SHMParams"]
        domainSize = SHM['domainSize']
        a = domainSize['refinement_length']
        H = domainSize['typical_height']
        Href = SHM["domainSize"]["domZ"]
        cell_size = params['cell_size']  # blockMesh cell size
        z_cell = cell_size
        zz = SHM["pointInDomain"]["zz"]
        x0, y0 = (SHM["centerOfDomain"]["x0"], SHM["centerOfDomain"]["x0"])
        i = params['i']
        z0 = wind_dict["caseTypes"]["windRose"]["windDir"][i][2]
        # calculating refinement box positions
        l1, l2, h1, h2 = 2 * a, 1.3 * a, 4 * H, 2 * H  # refinement rules - Martinez 2011
        sp = sin(phi)
        cp = cos(phi)

        #enlarging to take acount of the rotation angle
        def calc_box(l, h):
            tx1, ty1, tz1 = x0 - l * (sp + cp), y0 - l * (
                cp - sp), domainSize["z_min"]
            tx2, ty2, tz2 = x0 + l * (sp + cp), y0 + l * (cp - sp), h
            return (min(tx1, tx2), min(ty1, ty2), min(tz1, tz2), max(tx1, tx2),
                    max(ty1, ty2), max(tz1, tz2))

        (refBox1_minx, refBox1_miny, refBox1_minz, refBox1_maxx, refBox1_maxy,
         refBox1_maxz) = calc_box(l1, h1)
        (refBox2_minx, refBox2_miny, refBox2_minz, refBox2_maxx, refBox2_maxy,
         refBox2_maxz) = calc_box(l2, h2)
        assert (refBox1_minx < refBox1_maxx)
        assert (refBox1_miny < refBox1_maxy)
        assert (refBox1_minz < refBox1_maxz)
        assert (refBox2_minx < refBox2_maxx)
        assert (refBox2_miny < refBox2_maxy)
        assert (refBox2_minz < refBox2_maxz)

        # changing snappyHexMeshDict - with parsedParameterFile

        # case 1 - an stl file describing a rectangular domain larger then the blockMesh control volume
        if SHM["rectanguleDomainSTL"]:
            shutil.copyfile(path.join(work.systemDir(), "snappyHexMeshDict_rectanguleDomain"), \
                        path.join(work.systemDir(), "snappyHexMeshDict"))
        # case 2 - an stl file describing a single hill, with edges at z_min
        else:
            shutil.copyfile(path.join(work.systemDir(), "snappyHexMeshDict_singleHill"), \
                        path.join(work.systemDir(), "snappyHexMeshDict"))

        # changes that apply to both cases
        SHMDict = ParsedParameterFile(
            path.join(work.systemDir(), "snappyHexMeshDict"))
        # changing refinement boxes around center reigon
        SHMDict["geometry"]["refinementBox1"]["min"] = \
            "("+str(refBox1_minx)+" "+str(refBox1_miny)+" "+str(refBox1_minz)+")"
        SHMDict["geometry"]["refinementBox1"]["max"] = \
            "("+str(refBox1_maxx)+" "+str(refBox1_maxy)+" "+str(refBox1_maxz)+")"
        SHMDict["geometry"]["refinementBox2"]["min"] = \
            "("+str(refBox2_minx)+" "+str(refBox2_miny)+" "+str(refBox2_minz)+")"
        SHMDict["geometry"]["refinementBox2"]["max"] = \
            "("+str(refBox2_maxx)+" "+str(refBox2_maxy)+" "+str(refBox2_maxz)+")"
        # changing inlet refinement reigon - crude correction to SHM layer fault at domain edges
        lup, ldown, d = domainSize["fXup"], domainSize["fXdown"], domainSize[
            "fY"]
        x1 = x0 - (lup * sp + d / 2 * cp)
        y1 = y0 + (lup * cp - d / 2 * sp)
        x3 = x0 - ((lup - cell_size) * sp + d / 2 * cp)
        y3 = y0 - ((lup - cell_size) * cp - d / 2 * sp)

        SHMDict["geometry"]["upwindbox1"]["min"] = \
            "("+str(min(x1,x3))+" "+str(min(y1,y3))+" "+str(domainSize["z_min"])+")"
        SHMDict["geometry"]["upwindbox1"]["max"] = \
            "("+str(max(x1,x3))+" "+str(max(y1,y3))+" "+str(domainSize["z_min"]+cell_size/3)+")"
        """x1 = x0 + (ldown * sp + d / 2 * cp)
        y1 = y0 + (ldown * cp - d / 2 * sp)
        x3 = x0 + ((ldown - cell_size) * sp - d / 2 * cp)
        y3 = y0 + ((ldown - cell_size) * cp + d / 2 * sp)

        SHMDict["geometry"]["refinementOutlet"]["min"] = \
            "("+str(min(x1,x3))+" "+str(min(y1,y3))+" "+str(domainSize["z_min"])+")"
        SHMDict["geometry"]["refinementOutlet"]["max"] = \
            "("+str(max(x1,x3))+" "+str(max(y1,y3))+" "+str(domainSize["z_min"]+cell_size)+")"
        """
        # changing location in mesh
        SHMDict["castellatedMeshControls"]["locationInMesh"] = "(" + str(
            x0) + " " + str(y0) + " " + str(zz) + ")"
        levelRef = SHM["cellSize"]["levelRef"]
        SHMDict["castellatedMeshControls"]["refinementSurfaces"]["terrain"]["level"] = \
            "("+str(levelRef)+" "+str(levelRef)+")"
        SHMDict["castellatedMeshControls"]["refinementRegions"]["upwindbox1"]["levels"] =  \
            "(("+str(1.0)+" "+str(min(levelRef * 2,4))+"))"

        SHMDict["castellatedMeshControls"]["refinementRegions"]["refinementBox1"]["levels"] =  \
            "(("+str(1.0)+" "+str(int(round(levelRef/2)))+"))"
        SHMDict["castellatedMeshControls"]["refinementRegions"]["refinementBox2"]["levels"] =  \
            "(("+str(1.0)+" "+str(levelRef)+"))"

        r = SHM["cellSize"]["r"]
        SHMDict["addLayersControls"]["expansionRatio"] = r
        fLayerRatio = SHM["cellSize"]["fLayerRatio"]
        SHMDict["addLayersControls"]["finalLayerThickness"] = fLayerRatio
        # calculating finalLayerRatio for getting
        zp_z0 = SHM["cellSize"]["zp_z0"]
        firstLayerSize = 2 * zp_z0 * z0
        L = min(
            log(fLayerRatio / firstLayerSize * z_cell / 2**levelRef) / log(r) +
            1, 12)
        SHMDict["addLayersControls"]["layers"]["terrain_solid"][
            "nSurfaceLayers"] = int(round(L))

        # changes that apply only to case 2
        if not (SHM["rectanguleDomainSTL"]):
            SHMDict["geometry"]["groundSurface"]["pointAndNormalDict"]["basePoint"] = \
                "( 0 0 "+str(domainSize["z_min"])+")"
            SHMDict["castellatedMeshControls"]["refinementRegions"]["groundSurface"]["levels"] = \
                "(("+str(h2/2)+" "+str(levelRef)+") ("+str(h1/2)+" "+str(int(round(levelRef/2)))+"))"
            SHMDict["addLayersControls"]["layers"]["ground"][
                "nSurfaceLayers"] = int(round(L))
        SHMDict.writeFile()

    def create_boundary_conditions_dict(self, work, wind_dict, params):
        #--------------------------------------------------------------------------------------
        # changing inlet profile - - - - according to Martinez 2010
        #--------------------------------------------------------------------------------------
        phi = params['phi']
        i = params['i']
        SHM = wind_dict['SHMParams']
        kEpsParams = wind_dict['kEpsParams']
        k = kEpsParams['k']  # von karman constant
        z0 = wind_dict["caseTypes"]["windRose"]["windDir"][i][
            2]  # TODO: calculated per wind direction using roughness2foam
        us = wind_dict["caseTypes"]["windRose"]["windDir"][i][4]
        Href = SHM['domainSize']['domZ']
        TKE = us**2 * wind_dict["caseTypes"]["windRose"]["windDir"][i][3]
        Cmu = us / TKE**2
        # change inlet profile
        z_min = wind_dict['SHMParams']['domainSize']['z_min']
        Uref = Utop = us / k * log((Href - z_min) / z0)
        # 1: changing ABLConditions
        bmName = path.join(work.initialDir(), "include", "ABLConditions")
        template = TemplateFile(bmName + ".template")
        template.writeToFile(
            bmName, {
                'us': us,
                'Uref': Uref,
                'Href': Href,
                'z0': z0,
                'xDirection': sin(phi),
                'yDirection': cos(phi)
            })
        # 2: changing initialConditions
        bmName = path.join(work.initialDir(), "include", "initialConditions")
        template = TemplateFile(bmName + ".template")
        template.writeToFile(bmName, {'TKE': TKE})
        # 3: changing initial and boundary conditions for z0
        # changing z0 in nut, inside nutkAtmRoughWallFunction - for rectanguleDomainSTL = 0 for both terrain and ground patches
        nutFile = ParsedParameterFile(path.join(work.initialDir(), "nut"))
        if SHM["rectanguleDomainSTL"]:
            nutFile["boundaryField"]["ground"]["z0"].setUniform(z0)
            nutFile["boundaryField"]["terrain_.*"]["z0"].setUniform(z0)
        else:
            nutFile["boundaryField"]["ground"]["z0"].setUniform(
                SHM["ground_z0"])
            nutFile["boundaryField"]["terrain_.*"]["z0"].setUniform(
                SHM["terrain_z0"])
        nutFile.writeFile()
        # 3: changing transport properties
        transportFile = ParsedParameterFile(
            path.join(work.constantDir(), 'transportProperties'))
        transportFile['nu'] = "nu [0 2 -1 0 0 0 0] " + str(
            wind_dict['simParams']['nu'])
        transportFile.writeFile()

    def create_case(self, wind_dict, params):
        """
        0. cloning case
        1. creating snappyHexMeshDict and blockMeshdict according to flow direction and other parameters
        2. creating the blockMesh
        3. change the boundary conditions
        4. decomposing the domain
        5. creating the snappyHexMesh - running in parallel (sfoam.py or not - depending on user input)
        6. decomposing the created mesh
        """
        #--------------------------------------------------------------------------------------
        # cloning case
        #--------------------------------------------------------------------------------------
        target = params['case_dir']
        target = os.path.realpath(target)
        if not os.path.exists(target):
            makedirs(target)
        template = read_dict_string(wind_dict, 'template')
        self._r.debug("template = %r, target = %r" % (template, target))
        orig = SolutionDirectory(template, archive=None, paraviewLink=False)
        work = orig.cloneCase(target)

        #--
        # creating dictionaries
        #--
        if wind_dict['procnr'] > multiprocessing.cpu_count():
            self._r.warn(
                'wind_dict contains a higher processor number then the machine has'
            )
            wind_dict['procnr'] = min(wind_dict['procnr'],
                                      multiprocessing.cpu_count())
        phi = params['wind_dir'] * pi / 180
        params['phi'] = phi  # - pi/180 * 90
        self._r.status('creating block mesh dictionary')
        self.create_block_mesh_dict(work, wind_dict, params)
        self._r.status('creating snappy hex mesh dictionary')
        self.create_SHM_dict(work, wind_dict, params)
        self._r.status('creating boundary conditions dictionary')
        self.create_boundary_conditions_dict(work, wind_dict, params)
        self._r.status('running block mesh')
        self.run_block_mesh(work)
        self._r.status('running decompose')
        self.run_decompose(work, wind_dict)
        self._r.status('running snappy hex mesh')
        self.run_SHM(work, wind_dict)
        self._r.status('running second decompose')
        self.run_decompose(work, wind_dict)
        return work

    def run_decompose(self, work, wind_dict):
        if wind_dict['procnr'] < 2:
            self._r.status('skipped decompose')
            return
        ClearCase(args=work.name + '  --processors-remove')
        Decomposer(args=[work.name, wind_dict['procnr']])

    def run_block_mesh(self, work):
        blockRun = BasicRunner(argv=["blockMesh", '-case', work.name],
                               silent=True,
                               server=False,
                               logname="blockMesh")
        self._r.status("Running blockMesh")
        blockRun.start()
        if not blockRun.runOK():
            self._r.error("there was an error with blockMesh")

    def mpirun(self, procnr, argv, output_file):
        # TODO: use Popen and supply stdout for continous output monitor (web)
        assert (type(procnr) is int)
        args = ' '.join(argv)
        os.system('mpirun -np %(procnr)s %(args)s | tee %(output_file)s' %
                  locals())

    def run_SHM(self, work, wind_dict):
        if wind_dict["procnr"] > 1:
            self._r.status("Running SHM parallel")
            decomposeDict = ParsedParameterFile(
                path.join(work.systemDir(), "decomposeParDict"))
            decomposeDict["method"] = "ptscotch"
            decomposeDict.writeFile()
            self.mpirun(
                procnr=wind_dict['procnrSnappy'],
                argv=['snappyHexMesh', '-overwrite', '-case', work.name],
                output_file=path.join(work.name, 'SHM.log'))
            print 'running clearCase'
            ClearCase(args=work.name + '  --processors-remove')
        else:
            SHMrun = BasicRunner(
                argv=["snappyHexMesh", '-overwrite', '-case', work.name],
                server=False,
                logname="SHM")
            self._r.status("Running SHM uniprocessor")
            SHMrun.start()

    def makedirs(self, d):
        self._r.debug('creating %r' % d)
        os.makedirs(d)

    def grid_convergance_params_generator(self, wind_dict):
        """
        yields names of case directories
        """
        grid_convergence = wind_dict["caseTypes"]["gridConvergenceParams"]
        gridRange = grid_convergence['gridRange']
        template = read_dict_string(wind_dict, 'template')
        wind_dir = grid_convergence['windDir']
        for i, cell_size in enumerate(gridRange):
            case_dir = os.path.join(
                wind_dict['runs'],
                '%(template)s_grid_%(cell_size)s' % locals())
            yield dict(case_dir=case_dir,
                       wind_dir=wind_dir,
                       cell_size=cell_size,
                       name='grid_convergence %d: cell_size=%d, wind_dir=%d' %
                       (i, cell_size, wind_dir))

    def wind_rose_params_generator(self, wind_dict):
        """
        yields names of case directories
        one for each direction from wind rose
        """
        windRose = wind_dict['caseTypes']["windRose"]
        template = read_dict_string(wind_dict, 'template')
        cell_size = windRose['blockMeshCellSize']
        for i, (_weight, wind_dir, _z0, _TKE_us2,
                _us) in enumerate(windRose['windDir']):
            case_dir = os.path.join(
                wind_dict['runs'], '%(template)s_rose_%(wind_dir)s' % locals())
            yield dict(case_dir=case_dir,
                       i=i,
                       wind_dir=wind_dir,
                       cell_size=cell_size,
                       name='wind_rose %d: cell_size=%d, wind_dir=%d' %
                       (i, cell_size, wind_dir))

    def run_directory(self, prefix):
        now = datetime.now()
        pristine = now.strftime(prefix + '_%Y%m%d_%H%M%S')
        if os.path.exists(pristine):
            if os.path.exists(pristine + '_1'):
                last = max([
                    try_int(x.rsplit('_', 1)[0]) for x in glob(pristine + '_*')
                ])
                d = pristine + '_%d' % (last + 1)
            else:
                d = pristine + '_1'
        else:
            d = pristine
        return d

    def reconstructCases(self, cases):
        for case in cases:
            Runner(args=["reconstructPar", "-latestTime", "-case", case])

    def sampleDictionaries(self, cases, work, wind_dict):
        # TODO - at the moment for 90 degrees phi only and in line instead of in a function
        for case in cases:
            self._r.status('preparing Sample file for case ' + case.name)
            sampleFile = ParsedParameterFile(
                path.join(case.systemDir(), "sampleDict"))
            del sampleFile.content['sets'][:]
            if len(wind_dict["Measurements"]) > 0:
                self._r.status("creating sample locations for measurements")
                for metMast in wind_dict["Measurements"]:
                    self._r.status("adding met mast " + metMast)
                    # creating sub directory entry
                    sampleFile.content['sets'].append(metMast)
                    # creating another fictional sub directory entry - so that i can run it over in a second
                    sampleFile.content['sets'].append([metMast])
                    sampleFile['sets'][len(sampleFile['sets'])-1] = \
                    {'type':'uniform', 'axis':'z',\
                    'start':'('+str(wind_dict["Measurements"][metMast]["x"])+" "\
                               +str(wind_dict["Measurements"][metMast]["y"])+" "\
                               +str(wind_dict["Measurements"][metMast]["gl"])+")",\
                    'end':  '('+str(wind_dict["Measurements"][metMast]["x"])+" "\
                               +str(wind_dict["Measurements"][metMast]["y"])+" "\
                               +str(wind_dict["Measurements"][metMast]["gl"]+\
                                    wind_dict["Measurements"][metMast]["h"])+")",\
                    'nPoints':wind_dict['sampleParams']['nPoints']}
            if len(wind_dict['sampleParams']['metMasts']) > 0:
                self._r.status("creating sample locations for sampleParams")
                for metMast in wind_dict['sampleParams']['metMasts']:
                    # creating sub directory entry
                    sampleFile.content['sets'].append(metMast)
                    # creating another fictional sub directory entry - so that i can run it over in a second
                    sampleFile.content['sets'].append([metMast])
                    sampleFile['sets'][len(sampleFile['sets'])-1] = \
                    {'type':'uniform', 'axis':'z',\
                    'start':'('+str(wind_dict["sampleParams"]["metMasts"][metMast]["x"])+" "\
                               +str(wind_dict["sampleParams"]["metMasts"][metMast]["y"])+" "\
                               +str(wind_dict["sampleParams"]["metMasts"][metMast]["gl"])+")",\
                    'end':  '('+str(wind_dict["sampleParams"]["metMasts"][metMast]["x"])+" "\
                               +str(wind_dict["sampleParams"]["metMasts"][metMast]["y"])+" "\
                               +str(wind_dict["sampleParams"]["metMasts"][metMast]["gl"]+\
                                    wind_dict["sampleParams"]["metMasts"][metMast]["h"])+")",\
                    'nPoints':wind_dict['sampleParams']['nPoints']}

            del sampleFile.content['surfaces'][:]
            for i, h in enumerate(wind_dict['sampleParams']['hSample']):
                self._r.status('preparing sampling surface at ' + str(h) +
                               ' meters agl')
                translateSTL.stl_shift_z_filenames(
                    path.join(case.name, 'constant/triSurface/terrain.stl'),
                    path.join(
                        case.name,
                        'constant/triSurface/terrain_agl_' + str(h) + '.stl'),
                    h)
                # creating sub directory entry
                sampleFile.content['surfaces'].append('agl_' + str(h))
                # creating another fictional sub directory entry - so that i can run it over in a second
                sampleFile.content['surfaces'].append(['agl_' + str(h)])
                sampleFile['surfaces'][len(sampleFile['surfaces']) - 1] = {
                    'type': 'sampledTriSurfaceMesh',
                    'surface': 'terrain_agl_' + str(h) + '.stl',
                    'source': 'cells'
                }
            sampleFile.writeFile()
            self._r.status('Sampling case ' + case.name)
            Runner(args=["sample", "-latestTime", "-case", case.name])

    def writeMetMastLocations(self,
                              case):  # will replace the following 4 lines
        print 'TODO writeMetMastLocations'

    def calcHitRate(self, cases, pdf, wind_dict):
        print "TODO calcHitRate"

    def newFigure(self, *args, **kw):
        fig = plt.figure(self._fig_n, *args, **kw)
        self._fig_n += 1
        return fig

    def save_svg(self, fig_name, f):
        if self._plots != 'svg':
            return
        filename = fig_name + '.svg'
        f.savefig(filename)
        self._r.status('PLOT %s' % filename)

    def plotContourMaps(self, cases, pdf, wind_dict):
        refinement_length = wind_dict['SHMParams']['domainSize'][
            'refinement_length']
        xi = linspace(-refinement_length, refinement_length,
                      wind_dict['sampleParams']['Nx'])
        yi = xi
        xmesh, ymesh = meshgrid(xi, yi)
        hs = wind_dict['sampleParams']['hSample']
        avgV = zeros((len(hs), len(xi), len(yi)))
        plt = self._r.plot
        for i, case in enumerate(cases):
            lastTime = genfromtxt(
                path.join(case.name, 'PyFoamState.CurrentTime'))
            for hi, h in enumerate(hs):
                data = genfromtxt(
                    path.join(
                        case.name, 'surfaces/' + str(int(lastTime)) +
                        '/U_agl_' + str(h) + '.raw'))
                # after a long trial and error - matplotlib griddata is shaky and crashes on some grids. scipy.interpolate works on every grid i tested so far
                vi = sc.griddata(
                    (data[:, 0].ravel(), data[:, 1].ravel()),
                    (data[:, 3].ravel()**2 + data[:, 4].ravel()**2)**0.5,
                    (xmesh, ymesh))
                ax = self.newFigure()
                plt.title(case.name + '\n at height ' + str(h) + ' meter agl')
                CS = plt.contourf(xi,
                                  yi,
                                  vi,
                                  400,
                                  cmap=plt.cm.jet,
                                  linewidths=0)
                plt.colorbar(CS)
                pdf.savefig()
                self.save_svg(os.path.join(case.name, 'contour'), ax.figure)
                # assuming the windDir weights are normalized
                #import pdb; pdb.set_trace()
                avgV[hi, :, :] += vi * wind_dict["caseTypes"]["windRose"][
                    "windDir"][i][0]
        for hi, h in enumerate(hs):
            ax = self.newFigure()
            plt.title('average wind velocity at height ' + str(h) +
                      ' meter agl')
            CS = plt.contourf(xi,
                              yi,
                              avgV[hi, :, :],
                              400,
                              cmap=plt.cm.jet,
                              linewidths=0)
            plt.colorbar(CS)
            pdf.savefig()
            self.save_svg('average_wind_velocity_h_%s' % str(h), ax.figure)

    def plot_initial_wind_rose(self, wind_dict, params):
        #windrose like a stacked histogram with normed (displayed in percent) results
        ax = self.initial_wind_rose_axes()
        weight = [
            x[0] for x in wind_dict['caseTypes']['windRose']['windDir'][:]
        ]
        wd = [x[1] for x in wind_dict['caseTypes']['windRose']['windDir'][:]]
        ws = [x[-1] for x in wind_dict['caseTypes']['windRose']['windDir'][:]]
        (wd, ws) = hist_to_time(weight, (wd, ws))
        ax.bar(wd, ws, normed=True, opening=0.8, edgecolor='white')
        self.initial_wind_rose_legend(ax)
        # TODO: add save_svg to windrose
        #self.save_svg('initial_wind_rose_axes', ax.figure)

    def run_windpyfoam(self, dict):
        """
        Mesh: creating the write snappyHexMeshDict file
        use the right snappyHexMeshDict_XXX.template file with wind_dict
        but --> already at this stage i have to work in a loop according to the
        amount of cases i am asked to solve. each case will be cloned from the
        template case, and then the procedure of
        if doing grid convergance with a single
        foreach dir in {winddirs, grid}:
            1. creating snappyHexMeshDict and blockMeshdict according to flow direction and other parameters
            2. creating the blockMesh
            3. decomposing the domain
            4. creating the snappyHexMesh - running in parallel (sfoam.py or not - depending on user input)
            5. decomposing the created mesh
            6. running pyFoamRunner.py through sfoam (or not - depending on user input)

        After all cases stop running
        7. if exist (usually) - reading real measurements
        8. creating sampleDict according to measurement locations and user input
            (which asks for wind speed contour map at certain height above ground)
        9. sampling (command is "sample")
        10. using the results to calculate the following metrics
            1. for a specific grid size and multiple directions and weights for
            each direction - the power density and average wind speed averaged over
            the direction at specific heights above ground level
            2. for a specific direction and different grid cell sizes - the grid
            error according to some known grid convergence algorithm
            3. a "hit rate" which shows the aggreement of the simulated wind speeds
            and turbulence to the measurements
        """
        if not os.path.exists(dict):
            self._r.error("missing %s file" % dict)
            raise SystemExit
        try:
            wind_dict = ParsedParameterFile(dict)
        except Exception, e:
            self._r.error("failed to parse windPyFoam parameter file:")
            self._r.error(str(e))
            raise SystemExit
        wind_dict['runs'] = self.run_directory('runs')

        # starting the pdf file for accumilating graphical results
        pdf = PdfPages('results.pdf')

        # preparing the grid, bc and ic for all cases
        gen = []
        if wind_dict["caseTypes"]["gridConvergence"]:
            gen = self.grid_convergance_params_generator(wind_dict)
        gen = itertools.chain(gen, self.wind_rose_params_generator(wind_dict))
        cases = []
        names = []

        for params in gen:
            self._r.debug(params['name'])
            work = self.create_case(wind_dict, params)
            names.append('wind%s' % int(180 / pi * params['phi']))
            cases.append(work)

        # plotting initial wind rose
        pdf2 = PdfPages('initialWindRose.pdf')
        self.plot_initial_wind_rose(wind_dict, params)
        pdf2.savefig()
        pdf2.close()
        os.system('xdg-open initialWindRose.pdf')

        self._r.status('RUNNING CASES')
        runArg = read_dict_string(wind_dict, 'runArg')
        self._r.status(runArg)
        assert (runArg in ['Runner', 'plotRunner', 'sfoam'])
        runCases(names=names,
                 n=wind_dict['procnr'],
                 runArg=runArg,
                 cases=[case.name for case in cases])
    # z0 = Davenport -1
    z0 = Davenport(z0Orig, -1)
    z0_minus = z0
    logger.info("----------------------------------")
    logger.info("changes z0 to " + str(z0) + " [m]")
    logger.info("preparing crude runs:")
    logger.info("initial guess of us is: " + str((100 * us // 1) * 0.01))
    prepareCase_2dHill(template0, targetDir, target0, hillName, AR, rC, x, Ls,
                       L, L1, H, x0C, z0, us, yM, h, "Crude")

    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # #    running crude cases	# # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

    runCases(case_dir=target)

    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # #    preparing fine cases	# # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

    prepareCase_2dHill(template0, targetDir, target0, hillName, AR, r, x, Ls,
                       L, L1, H, x0, z0, us, yM, h, "mapFields")

    prepareCase_2dHill(template0, targetDir, target0, hillName, AR, r, x, Ls,
                       L, L1, H, x0, z0, us, yM, h, "mapFields")
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # #    running fine cases	# # # # # # # # # # # # # # # # # #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	# z0 = Davenport -1
	z0 = Davenport(z0Orig,-1)
	z0_minus = z0
	logger.info("----------------------------------")
	logger.info("changes z0 to " + str(z0) + " [m]")
	logger.info("preparing crude runs:")
	logger.info("initial guess of us is: " + str((100*us//1)*0.01))
	prepareCase_2dHill(template0, targetDir, target0, hillName, AR, rC, x, Ls, L, L1, H, x0C, z0, us, yM, h, "Crude")
	
		
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # #    running crude cases	# # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	
	runCases(case_dir=target)
		
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # #    preparing fine cases	# # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	
	prepareCase_2dHill(template0, targetDir, target0, hillName, AR, r, x, Ls, L, L1, H, x0, z0, us, yM, h, "mapFields")
	
	prepareCase_2dHill(template0, targetDir, target0, hillName, AR, r, x, Ls, L, L1, H, x0, z0, us, yM, h, "mapFields")
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # #    running fine cases	# # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	

	# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
	# # # # # # # # # # # # # #  		3	 	# # # # # # # # # # # # # # # #