Skip to content
This repository was archived by the owner on Sep 5, 2025. It is now read-only.

Commit 46ca55b

Browse files
authored
Merge pull request #17 from ulgltas/adrien
CUPyDO 1.2
2 parents d8e4193 + bffe8cd commit 46ca55b

File tree

17 files changed

+893
-222
lines changed

17 files changed

+893
-222
lines changed

README.md

Lines changed: 18 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -4,170 +4,30 @@ FSI tools for partinioned coupling between generic solid and fluid solvers.
44
[![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE)
55

66
## Features
7-
As of December 2018, interfaces for the following solvers are implemented:
8-
7+
CUPyDO currently features interfaces for the following solvers:
98
- Solid:
109
- Metafor --> A Nonlinear Finite Element solid solver developed at the University of Liège (http://metafor.ltas.ulg.ac.be/dokuwiki/)
1110
- RBM --> A dynamic 2dof pitch/plunge solid solver developed at the University of Liège (https://github.com/ulgltas/NativeSolid)
1211
- modali -> A static/dynamic modal solver developed at the University of Liège (https://github.com/ulgltas/modali)
1312
- GetDP --> A free finite element software and a general environment for the treatment of discrete problems, developed at University of Liège (http://getdp.info/)
1413
- Fluid:
15-
- PFEM --> Particle Finite Element Method fluid solver developed at the University of Liège (https://github.com/ulgltas/PFEM)
16-
- SU2 --> Open-source CFD code developed at Stanford University (http://su2.stanford.edu/)
17-
- Flow --> A Full Potential Finite Element fluid solver, part of the waves project, developed at the University of Liège (https://github.com/ulgltas/waves)
18-
19-
## CUPyDO Compilation (linux - gcc)
20-
Required packages
21-
```bash
22-
sudo apt-get install build-essential
23-
sudo apt-get install cmake
24-
sudo apt-get install python2.7 python2.7-dev libpython2.7-dev
25-
sudo apt-get install swig
26-
sudo apt-get install python-numpy python-scipy
27-
```
28-
Optional packages (parallel build, required for SU2+MPI)
29-
```bash
30-
sudo apt-get install libopenblas-dev liblapack-dev
31-
sudo apt-get install openmpi-bin openmpi-common libopenmpi-dev
32-
sudo apt-get install petsc-dev
33-
sudo apt-get install python-mpi4py
34-
sudo apt-get install python-petsc4py
35-
```
36-
Compilation
37-
```bash
38-
mkdir build && cd build
39-
[export INCLUDE=${INCLUDE}:/path/to/petsc/include]
40-
cmake [-DWITH_MPI=ON] [-DCMAKE_BUILD_TYPE=Debug] ..
41-
make -j4
42-
make install
43-
```
44-
Notes:
45-
* MPI should be enabled if you want to use the MPI version of SU2. Keep this option disabled otherwise.
46-
* `path/to/petsc/include` is usually `/usr/lib/petscdir/version/` on Ubuntu/Debian
47-
* The "install" step is mandatory. It copies the binaries in `CUPyDO/ccupydo`.
48-
49-
50-
Run test battery
51-
```bash
52-
ctest [-R include_pattern] [-E exclude_pattern] -j4
53-
```
54-
55-
Run test file
56-
```bash
57-
python run.py path/to/testfile_fsi.py -n4
58-
```
59-
60-
## Interfaced solvers compilation (linux - gcc)
61-
Brief instructions to compile interfaced solvers. The full documentation is available on the aforementioned websites.
62-
The directories containing the external solvers must be placed at the same level as CUPyDO directory.
63-
64-
### Common packages
65-
```bash
66-
sudo apt-get install gmsh
67-
sudo apt-get install libtbb-dev
68-
sudo apt-get install libvtk6.3 libvtk6-dev libvtk6-qt-dev python-vtk6 python-pyqt5
69-
```
70-
71-
### Metafor
72-
[Linux, Windows, macOS]
73-
74-
Required packages
75-
```bash
76-
sudo apt install subversion
77-
sudo apt install bison flex
78-
mkdir Metafor && cd Metafor
79-
git clone [email protected]:ulgltas/linuxbin.git
80-
```
81-
Compilation
82-
```bash
83-
svn co svn+ssh://[email protected]/home/metafor/SVN/oo_meta/trunk oo_meta
84-
mkdir oo_metaB && cd oo_metaB
85-
cmake -C ../oo_meta/CMake/configMachine-CUPyDO.cmake [-DCMAKE_INSTALL_PREFIX=/path/to/Metafor/install/folder] [-DCMAKE_BUILD_TYPE=Debug] ../oo_meta
86-
make -j4
87-
```
88-
Notes:
89-
* Metafor cannot be built with the "parasolid" interface which uses the same class names as `waves/fwk`
90-
* A "sutdent" configuration can be used but some tests will not pass due to license restrictions.
91-
92-
### RBM [NativeSolid]
93-
[Linux]
94-
95-
Required packages
96-
```bash
97-
sudo apt-get install liblapacke-dev
98-
sudo apt-get install libatlas-base-dev
99-
```
100-
Compilation
101-
```bash
102-
git clone [email protected]:ulgltas/NativeSolid.git
103-
cd NativeSolid
104-
mkdir build && cd build
105-
cmake ..
106-
make -j4
107-
```
108-
Windows: FIX LAPACKE
109-
110-
### modali
111-
[Linux]
112-
113-
Get the code
114-
```bash
115-
git clone [email protected]:ulgltas/modali.git
116-
```
117-
118-
### SU2
119-
[Linux]
120-
```bash
121-
sudo apt-get install autoconf
122-
git clone [email protected]:su2code/SU2.git
123-
cd SU2
124-
git checkout tags/v6.2.0
125-
unset MKLROOT # <= MKL should be disabled
126-
./bootstrap
127-
./configure --prefix=/path/to/SU2/install/folder CXXFLAGS="-O3" [--enable-mpi --with-cc=/path/to/mpicc --with-cxx=/path/to/mpicxx] --enable-PY_WRAPPER [--enable-tecio]
128-
make -j4
129-
make install
130-
```
131-
Notes:
132-
* The INSTALL step is mandatory!
133-
* MPI should be enabled/disabled in both CUPyDO and SU2.
134-
135-
136-
### Waves/flow
137-
[Linux, Windows, macOS]
138-
139-
Required packages
140-
```bash
141-
sudo apt-get install libgmm++-dev libeigen3-dev
142-
sudo apt-get install libmumps-seq-dev libopenblas-dev
143-
```
144-
Optionnal packages
145-
```bash
146-
sudo apt-get install python-matplotlib
147-
```
148-
Compilation
149-
```bash
150-
git clone [email protected]:ulgltas/waves.git
151-
cd waves
152-
mkdir build && cd build
153-
cmake -C disable-trilinos.cmake ..
154-
make -j4
155-
```
156-
Note:
157-
* `disable-trilinos.cmake` is not mandatory but it helps save much build time.
158-
159-
### PFEM
160-
[Linux, Windows, macOS]
161-
```bash
162-
git clone [email protected]:ulgltas/waves.git
163-
[build waves as above]
164-
[email protected]:am-dept/PFEM.git
165-
cd PFEM
166-
mkdir build && cd build
167-
cmake ..
168-
make -j4
169-
```
170-
14+
- PFEM --> Particle Finite Element Method fluid solver developed at the University of Liège (https://gitlab.uliege.be/am-dept/PFEM)
15+
- SU2 --> Open-source CFD code developed at Stanford University (https://su2code.github.io/)
16+
- Flow --> A Full Potential Finite Element fluid solver, part of the waves project, developed at the University of Liège (https://gitlab.uliege.be/am-dept/waves)
17+
- VLM --> A Vortex Lattice Method, developed at the University of Liège (https://github.com/ulgltas/VLM)
18+
19+
Furthermore, CUPyDO features two interpolation alogrithms:
20+
- Radial Basis Functions (RBF)
21+
- Thin Plate Spline (TPS)
22+
23+
Finally, CUPyDO features two main couplers:
24+
- Block-Gauss-Seidel (BGS) with
25+
- constant (static) relaxation
26+
- Aitken relaxation
27+
- Interface Quasi-Newton with Inverse Least-Square (IQN_ILS)
28+
29+
## Compilation
30+
Detailed build instructions can be found in the [wiki](https://github.com/ulgltas/CUPyDO/wiki/Installation).
17131

17232
## Examples
17333
Examples of simulations are available in [CUPyDO/tests](https://github.com/ulgltas/CUPyDO/tree/master/tests) and [CUPyDO/cases](https://github.com/ulgltas/CUPyDO/tree/master/cases).

cupydo/interfaces/Cupydo.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ def __initFluid(self, p, withMPI, comm):
109109
elif p['fluidSolver'] == 'Flow':
110110
import cupydo.interfaces.Flow as fItf
111111
fluidSolver = fItf.Flow(p['cfdFile'], args.n)
112+
elif p['fluidSolver'] == 'VLM':
113+
import cupydo.interfaces.VLM as fItf
114+
fluidSolver = fItf.VLMSolver(p['cfdFile'])
112115
else:
113116
raise RuntimeError('Interface for', p['fluidSolver'], 'not found!\n')
114117
return fluidSolver
@@ -139,7 +142,7 @@ def __initSolid(self, p, myId):
139142
# Sample parameters list
140143

141144
# Solvers
142-
# - p['fluidSolver'], fluid solvers available: SU2, Pfem, Flow
145+
# - p['fluidSolver'], fluid solvers available: SU2, Pfem, Flow, VLM
143146
# - p['solidSolver'], solid solvers available: Metafor, RBMI, Modal, GetDP
144147
# Configuration files
145148
# - p['cfdFile'], path to fluid cfg file

cupydo/interfaces/Flow.py

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -77,35 +77,48 @@ def __initFlow(self, p, _nthreads):
7777

7878
# mesh the geometry
7979
self.msh = gmsh.MeshLoader(p['File'],__file__).execute(**p['Pars'])
80-
gmshWriter = tbox.GmshExport(self.msh)
8180
if p['Dim'] == 2:
8281
mshCrck = tbox.MshCrack(self.msh, p['Dim'])
83-
mshCrck.addCrack(p['Wake'])
84-
mshCrck.addBoundaries([p['Fluid'], p['Farfield'][-1], p['Body']])
85-
mshCrck.run(gmshWriter)
82+
mshCrck.setCrack(p['Wake'])
83+
mshCrck.addBoundaries([p['Fluid'], p['Farfield'][-1], p['Wing']])
84+
mshCrck.run()
8685
else:
87-
mshCrck = tbox.MshCrack(self.msh, p['Dim'])
88-
mshCrck.addCrack(p['Wake'])
89-
mshCrck.addBoundaries([p['Fluid'], p['Symmetry'], p['Farfield'][-1]] + p['Body'])
90-
mshCrck.addExcluded(p['WakeTip'])
91-
mshCrck.run(gmshWriter)
92-
del gmshWriter
86+
for i in range(0, len(p['Wakes'])):
87+
mshCrck = tbox.MshCrack(self.msh, p['Dim'])
88+
mshCrck.setCrack(p['Wakes'][i])
89+
if 'Fuselage' in p:
90+
mshCrck.addBoundaries([p['Fluid'], p['Symmetry'], p['Farfield'][-1], p['Fuselage'], p['Wings'][i]])
91+
else:
92+
mshCrck.addBoundaries([p['Fluid'], p['Symmetry'], p['Farfield'][-1], p['Wings'][i]])
93+
mshCrck.setExcluded(p['WakeTips'][i])
94+
mshCrck.run()
95+
tbox.GmshExport(self.msh).save(self.msh.name)
9396
del mshCrck
9497
self.mshWriter = Writer(self.msh)
9598

9699
# initialize mesh deformation handler
97100
self.mshDef = tbox.MshDeform(self.msh, p['Dim'])
98101
self.mshDef.nthreads = _nthreads
99102
self.mshDef.setField(p['Fluid'])
100-
self.mshDef.setFixed(p['Farfield'])
101-
self.mshDef.setMoving([p['Fsi']])
102-
if p['Dim'] == 3:
103-
self.mshDef.setSymmetry([p['Symmetry']], 1)
104-
self.mshDef.setInternal([p['Wake'], p['Wake']+'_'])
103+
self.mshDef.addFixed(p['Farfield'])
104+
if p['Dim'] == 2:
105+
self.mshDef.addMoving([p['Wing']])
106+
self.mshDef.addInternal([p['Wake'], p['Wake']+'_'])
107+
else:
108+
if 'Fuselage' in p:
109+
self.mshDef.addFixed(p['Fuselage'])
110+
self.mshDef.setSymmetry(p['Symmetry'], 1)
111+
for i in range(0, len(p['Wings'])):
112+
if p['Wings'][i] == p['Fsi']:
113+
self.mshDef.addMoving([p['Wings'][i]])
114+
else:
115+
self.mshDef.addFixed([p['Wings'][i]])
116+
self.mshDef.addInternal([p['Wakes'][i], p['Wakes'][i]+'_'])
117+
self.mshDef.initialize()
105118

106119
# initialize the problem
107120
p['AoA'] = p['AoA']*np.pi/180 # convert to radians
108-
phiInfFun = flow.Fun0PosPhiInf(p['Dim'], p['AoA'])
121+
phiInfFun = flow.F0PsPhiInf(p['Dim'], p['AoA'])
109122
if p['Dim'] == 2:
110123
velInfFun = tbox.Fct1C(-np.cos(p['AoA']), -np.sin(p['AoA']), 0.)
111124
else:
@@ -115,32 +128,34 @@ def __initFlow(self, p, _nthreads):
115128

116129
# add medium
117130
if p['M_inf'] == 0:
118-
self.fCp = flow.Fun0EleCpL()
119-
pbl.set(flow.Medium(self.msh, p['Fluid'], flow.Fun0EleRhoL(), flow.Fun0EleMachL(), self.fCp, phiInfFun))
131+
pbl.set(flow.Medium(self.msh, p['Fluid'], flow.F0ElRhoL(), flow.F0ElMachL(), flow.F0ElCpL(), phiInfFun))
120132
else:
121-
self.fCp = flow.Fun0EleCp(p['M_inf'])
122-
pbl.set(flow.Medium(self.msh, p['Fluid'], flow.Fun0EleRho(p['M_inf'], p['M_crit']), flow.Fun0EleMach(p['M_inf']), self.fCp, phiInfFun))
133+
pbl.set(flow.Medium(self.msh, p['Fluid'], flow.F0ElRho(p['M_inf'], p['M_crit']), flow.F0ElMach(p['M_inf']), flow.F0ElCp(p['M_inf']), phiInfFun))
123134
# add initial condition
124135
pbl.add(flow.Initial(self.msh, p['Fluid'], phiInfFun))
125-
# add farfield and symmetry boundary conditions
126-
for bd in p['Farfield']:
127-
pbl.add(flow.Freestream(self.msh, bd, velInfFun))
136+
# add farfield boundary conditions
137+
pbl.add(flow.Dirichlet(self.msh, p['Farfield'][0], phiInfFun))
138+
for i in range (1, len(p['Farfield'])):
139+
pbl.add(flow.Freestream(self.msh, p['Farfield'][i], velInfFun))
128140
# add solid boundaries and identify f/s boundary
129141
if p['Dim'] == 2:
130-
self.boundary = flow.Boundary(self.msh, [p['Body'], p['Fluid']])
142+
self.boundary = flow.Boundary(self.msh, [p['Wing'], p['Fluid']])
131143
pbl.add(self.boundary)
132144
else:
133-
for bd in p['Body']:
145+
for bd in p['Wings']:
134146
bnd = flow.Boundary(self.msh, [bd, p['Fluid']])
135147
pbl.add(bnd)
136148
if bd == p['Fsi']:
137149
self.boundary = bnd
150+
if 'Fuselage' in p:
151+
pbl.add(flow.Boundary(self.msh, [p['Fuselage'], p['Fluid']]))
138152
# add wake/kutta condition
139153
if p['Dim'] == 2:
140154
pbl.add(flow.Wake(self.msh, [p['Wake'], p['Wake']+'_', p['Fluid']]))
141-
pbl.add(flow.Kutta(self.msh, [p['Te'], p['Wake']+'_', p['Body'], p['Fluid']]))
155+
pbl.add(flow.Kutta(self.msh, [p['Te'], p['Wake']+'_', p['Wing'], p['Fluid']]))
142156
else:
143-
pbl.add(flow.Wake(self.msh, [p['Wake'], p['Wake']+'_', p['Fluid'], p['TeTip']]))
157+
for i in range(0, len(p['Wakes'])):
158+
pbl.add(flow.Wake(self.msh, [p['Wakes'][i], p['Wakes'][i]+'_', p['Fluid'], p['TeTips'][i]]))
144159

145160
# initialize the solver
146161
if p['NSolver'] == 'Picard':
@@ -173,18 +188,14 @@ def run(self, t1, t2):
173188
self.__setCurrentState()
174189

175190
def __setCurrentState(self):
176-
"""Compute nodal forces from nodal Pressure coefficient
191+
"""Compute nodal forces from nodal normalized forces
177192
Adrien Crovato
178193
"""
179-
# integrate Cp at element
180-
cpiE = self.boundary.integrate(self.solver.phi, self.fCp)
181-
# transfer integrated Cp from elements to nodes
182-
cfN = self.boundary.transfer(cpiE)
183194
i = 0
184195
for n in self.boundary.nodes:
185-
self.nodalLoad_X[i] = -self.dynP * cfN[i][0]
186-
self.nodalLoad_Y[i] = -self.dynP * cfN[i][1]
187-
self.nodalLoad_Z[i] = -self.dynP * cfN[i][2]
196+
self.nodalLoad_X[i] = -self.dynP * self.boundary.cLoadX[i]
197+
self.nodalLoad_Y[i] = -self.dynP * self.boundary.cLoadY[i]
198+
self.nodalLoad_Z[i] = -self.dynP * self.boundary.cLoadZ[i]
188199
i += 1
189200

190201
def getNodalInitialPositions(self):
@@ -263,7 +274,6 @@ def exit(self):
263274
"""
264275
Exit the Flow solver
265276
"""
266-
del self.fCp
267277
del self.solver
268278
del self.mshDef
269279
del self.msh

0 commit comments

Comments
 (0)