diff --git a/README.md b/README.md index ce9539b..b863a83 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ # GeoGen Adrien Crovato -ULiege, 2018-2019 +ULiege, 2018-2020 [![Run Status](https://api.shippable.com/projects/5c98c1405142dd0007ecd6c0/badge?branch=master)]() ## Features and limitations ### What is GeoGen? -GeoGen is a python code that generates an aerodynamic geometry which can then be meshed in gmsh and used in CFD solvers. +GeoGen is a python code that generates an aerodynamic geometry which can then be meshed using gmsh and used in CFD solvers. +GeoGen v2 and up is compatible with python 3, while previous versions are compatible with python 2. ### What can GeoGen do? GeoGen currently supports the following configurations: @@ -18,44 +19,47 @@ GeoGen currently supports the following configurations: - [ ] Generic fuselage - [ ] Horizontal tail - [ ] Multibody (e.g. several isolated wings) -GeoGen was primarly designed to be used with [SU2](https://github.com/su2code/SU2) and [waves](https://github.com/ulgltas/waves), but any solver interfaced with [gmsh](http://gmsh.info/) can be used! -### Cite us! -If you use this work, please acknowledge the authors: -```text -"GeoGen - a python/gmsh automated geometry generator for CFD solvers" by Adrien Crovato, University of Liege -``` + +GeoGen was primarly designed to be used with [SU2](https://github.com/su2code/SU2) and [waves](https://gitlab.uliege.be/am-dept/waves), but any solver interfaced with [gmsh](http://gmsh.info/) can be used! ## Usage The script is run through the command line: ```sh -python geoGen.py -m path/to/config/file <-o path/to/output/file> +python geoGen.py path/to/config/file.py <-o path/to/output/file.geo> ``` -Note that the extensions (.py and .geo) are automatically handled by the code and should to be provided in the path. -If no output file is provided, a workspace directory will be created and the geometry will be stored inside as grid.geo. +If no output file is provided, a workspace directory will be created and the geometry will be stored inside as `grid.geo`. The geometry is generated from a python file containing a dictionary of parameters. Examples are given in [config](config/) and the main options are summurized hereunder. + **Parameters** + Wing definition: - - airfPath: relative path to the airfoils directory - - airfName: array (size: nP+1) of names of file containing airfoil (Selig formatted) coordinates - - span: array (size: nP) of span for each planform of the wing - - taper: array (size: nP)) of taper of each planform of the wing - - sweep: array (size: nP) of leading edge sweep of each planform of the wing - - dihedral: array (size: nP) of dihedral angle of each planform of the wing - - twist: array (size: nP+1) of twist angle of each airfoil of the wing - - rootChord: root chord (scalar) of the wing - - offset: array of x and z offset (size: 2) applied to the leading edge of the root section - - coWingtip: boolean, True for cutoof wingtip, Fasle for rounded wingtip (not supported yet) + - `airfPath`: relative path to the airfoils directory + - `airfName`: array (size: nP+1) of names of file containing airfoil (Selig formatted) coordinates + - `span`: array (size: nP) of span for each planform of the wing + - `taper`: array (size: nP)) of taper of each planform of the wing + - `sweep`: array (size: nP) of leading edge sweep of each planform of the wing + - `dihedral`: array (size: nP) of dihedral angle of each planform of the wing + - `twist`: array (size: nP+1) of twist angle of each airfoil of the wing + - `rootChord`: root chord (scalar) of the wing + - `offset`: array of x and z offset (size: 2) applied to the leading edge of the root section + - `coWingtip`: boolean, True for cutoof wingtip, Fasle for rounded wingtip (not supported yet) + + Domain definition: - - domType: string, box for box-shaped domain or shpere for shperical-shaped domain + - `domType`: string, box for box-shaped domain or shpere for shperical-shaped domain + + if domain type is shpere, typical for Euler equations: - - rSphere: radius of the sphere (scalar) + - `rSphere`: radius of the sphere (scalar) + + if domain type is a box (a wake will then be defined), typically for potential equations: - - xoBox: x-coordinate (scalar) of the origin of the box - - xfBox: x-coordinate (scalar) of the end of the box - - yfBox: y-coordinate (scalar) of the end of the box - - zoBox: z-coordinate (scalar) of the origin of the box - - zfBox: z-coordinate (scalar) of the end of the box - - nSlope: number (scalar) of airfoil geometrical points counted from TE used to compute wake slope + - `xoBox`: x-coordinate (scalar) of the origin of the box + - `xfBox`: x-coordinate (scalar) of the end of the box + - `yfBox`: y-coordinate (scalar) of the end of the box + - `zoBox`: z-coordinate (scalar) of the origin of the box + - `zfBox`: z-coordinate (scalar) of the end of the box + - `nSlope`: number (scalar) of airfoil geometrical points counted from TE used to compute wake slope diff --git a/domain.py b/domain.py index ae96c0c..b4fa243 100644 --- a/domain.py +++ b/domain.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' diff --git a/geoGen.py b/geoGen.py index 83fe363..bbe9751 100755 --- a/geoGen.py +++ b/geoGen.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' -Copyright 2019 University of Liege +Copyright 2020 University of Liege Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -49,7 +49,7 @@ def main(_module, _output): # Switch to workspace and write createWdir() - outFile = _output + '.geo' + outFile = _output # misc writeHeader(outFile, _module) wing.writeInfo(outFile) @@ -86,7 +86,7 @@ def main(_module, _output): printInfo(outFile) # eof - print '' + print('') def getConfig(_module): # Get prarmeters from config file @@ -103,7 +103,7 @@ def createWdir(): import os wdir = os.path.join(os.getcwd(), 'workspace') if not os.path.isdir(wdir): - print "creating", wdir + print("creating", wdir) os.makedirs(wdir) os.chdir(wdir) @@ -137,22 +137,22 @@ def printInfo(fname): """Print info """ import os - print '*' * 79 - print '* geoGen' - print '* Adrien Crovato' - print '* ULiege, 2018-2019' - print '* Distributed under Apache license 2.0' - print '*' * 79 - print os.path.abspath(os.path.join(os.getcwd(), fname)), 'has been successfully written!' - print 'Visual file check in gmsh recommended before further use!' - print '*' * 79 + print('*' * 79) + print('* geoGen') + print('* Adrien Crovato') + print('* ULiege, 2018-2020') + print('* Distributed under Apache license 2.0') + print('*' * 79) + print(os.path.abspath(os.path.join(os.getcwd(), fname)), 'has been successfully written!') + print('Visual file check in gmsh recommended before further use!') + print('*' * 79) if __name__ == "__main__": # Arguments parser import argparse parser = argparse.ArgumentParser() - parser.add_argument('-m', dest='mod', help='input config module (w/o .py)') - parser.add_argument('-o', dest='out', help='output geo file (w/o .geo)', default='grid') + parser.add_argument('file', help='input config .py file') + parser.add_argument('-o', dest='out', help='output .geo file', default='grid.geo') args = parser.parse_args() - main(args.mod, args.out) + main(args.file[:-3], args.out) diff --git a/shippable.yml b/shippable.yml index 453ab0a..3d1a77e 100644 --- a/shippable.yml +++ b/shippable.yml @@ -2,7 +2,7 @@ dist: xenial sudo: required language: python python: - - "2.7" + - "3.5" branches: only: @@ -10,19 +10,20 @@ branches: - ci_shippable before_install: + - sudo apt-get update # python - - sudo apt-get install -qq python-dev python-numpy + - sudo apt-get install -qq python3-dev python3-numpy # add dist-package to pythonpath (for numpy) - - export PYTHONPATH="${PYTHONPATH}:/usr/lib/python2.7/dist-packages" + - export PYTHONPATH="${PYTHONPATH}:/usr/lib/python3/dist-packages" # gmsh - wget http://gmsh.info/bin/Linux/gmsh-4.2.2-Linux64.tgz - tar -xzvf gmsh-4.2.2-Linux64.tgz - sudo ln -s $PWD/gmsh-4.2.2-Linux64/bin/gmsh /usr/bin/gmsh script: - - python geoGen.py -m config/onera -o onera + - python geoGen.py config/onera.py -o onera.geo - gmsh -3 workspace/onera.geo -o workspace/onera.msh - - python geoGen.py -m config/rae -o rae + - python geoGen.py config/rae.py -o rae.geo - gmsh -3 workspace/rae.geo -o workspace/rae.msh integrations: @@ -30,5 +31,5 @@ integrations: - integrationName: slack type: slack recipients: - - "#geogen" + - "#others" diff --git a/tip.py b/tip.py index 5c51ef8..af3c1fb 100644 --- a/tip.py +++ b/tip.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' -Copyright 2019 University of Liege +Copyright 2020 University of Liege Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ def initData(self): """Initialize data, define numbering """ # build mean line - self.pts = [(np.zeros([(self.wing.pts[-1].shape[0]-3)/2,3]))] + self.pts = [(np.zeros([(self.wing.pts[-1].shape[0]-3)//2,3]))] for i in range(0, self.pts[0].shape[0]): self.pts[0][i,:] = np.array([0.5*(self.wing.pts[-1][1+i,0]+self.wing.pts[-1][-2-i,0]), self.wing.pts[-1][0,1], 0.5*(self.wing.pts[-1][1+i,2]+self.wing.pts[-1][-2-i,2])]) @@ -142,13 +142,15 @@ def writePhysical(self, fname): file.write('Physical Surface("wing") += {') for j in range(0, 3): file.write('{0:d},'.format(self.surN[0][j])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) + file.seek(file.tell() - 1, os.SEEK_SET) file.truncate() file.write('};\n') file.write('Physical Surface("wing_") += {') for j in range(3, 6): file.write('{0:d},'.format(self.surN[0][j])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) + file.seek(file.tell() - 1, os.SEEK_SET) file.truncate() file.write('};\n') file.write('\n') diff --git a/wake.py b/wake.py index 43c1e6e..d90ec1c 100644 --- a/wake.py +++ b/wake.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' -Copyright 2019 University of Liege +Copyright 2020 University of Liege Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -149,14 +149,16 @@ def writePhysical(self, fname): file.write('Physical Line("teTip") = {{{0:d},'.format(self.linN[1][self.wing.n-1])) for i in range(0, self.wing.n-1): file.write('{0:d},'.format(self.wing.linpN[i][0])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) + file.seek(file.tell() - 1, os.SEEK_SET) file.truncate() file.write('};\n') file.write('Physical Surface("wake") = {') for j in range(0, self.wing.n-1): file.write('{0:d},'.format(self.surN[0][j])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) + file.seek(file.tell() - 1, os.SEEK_SET) file.truncate() file.write('};\n') file.write('\n') - file.close() \ No newline at end of file + file.close() diff --git a/wing.py b/wing.py index 58ef6ff..431642b 100644 --- a/wing.py +++ b/wing.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- ''' -Copyright 2019 University of Liege +Copyright 2020 University of Liege Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -133,8 +133,8 @@ def specPts(self, idx): def read(self,fname): """Read data from file and stroe in matrix """ - _file = file(fname) - label = _file.next().split(',') + _file = open(fname, 'r') + label = next(_file).split(',') _file.close() data = np.loadtxt(fname, skiprows=1) return data @@ -256,14 +256,16 @@ def writePhysical(self, fname): for i in range(0, self.n-1): for j in range(0, 3): file.write('{0:d},'.format(self.surN[i][j])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) # first seek end of file; f.seek(0, 2) is legal + file.seek(file.tell() - 1, os.SEEK_SET) # then go backward file.truncate() file.write('};\n') file.write('Physical Surface("wing_") = {') for i in range(0, self.n-1): for j in range(3, 6): file.write('{0:d},'.format(self.surN[i][j])) - file.seek(-1, os.SEEK_END) + file.seek(0, os.SEEK_END) + file.seek(file.tell() - 1, os.SEEK_SET) file.truncate() file.write('};\n') file.write('\n')