-
Paul Dechamps authoredPaul Dechamps authored
coupler.py 4.55 KiB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 University of Liège
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# VII Coupler
# Paul Dechamps
import fwk
from fwk.coloring import ccolors
import math
import numpy as np
class Coupler:
def __init__(self, iSolverAPI, vSolver, _maxCouplIter=150, _couplTol=1e-4, _iterPrint=1, _resetInv=False):
self.iSolverAPI = iSolverAPI
self.vSolver = vSolver
self.maxCouplIter = _maxCouplIter
self.couplTol = _couplTol
self.resetInv = _resetInv
self.iterPrint = _iterPrint if self.iSolverAPI.getVerbose() == 0 and self.vSolver.verbose == 0 else 1
self.tms = fwk.Timers()
def run(self):
# Aerodynamic coefficients.
aeroCoeffs = np.zeros((0, 2))
# Convergence parameters.
couplIter = 0
cdPrev = 0.0
while couplIter < self.maxCouplIter:
# Run inviscid solver.
self.tms['inviscid'].start()
if self.resetInv:
self.iSolverAPI.reset()
self.iSolverAPI.run()
self.tms['inviscid'].stop()
# Write inviscid Cp distribution.
if couplIter == 0:
self.iSolverAPI.writeCp(sfx='_Inviscid')
# Impose inviscid boundary in the viscous solver.
self.tms['processing'].start()
self.iSolverAPI.imposeInvBC(couplIter)
self.tms['processing'].stop()
# Run viscous solver.
self.tms['viscous'].start()
exitCode = self.vSolver.run(couplIter)
self.tms['viscous'].stop()
# Impose blowing boundary condition in the inviscid solver.
self.tms['processing'].start()
self.iSolverAPI.imposeBlwVel()
self.tms['processing'].stop()
aeroCoeffs = np.vstack((aeroCoeffs, [self.iSolverAPI.getCl(), self.vSolver.Cdt]))
# Check convergence status.
error = abs((self.vSolver.Cdt - cdPrev) / self.vSolver.Cdt) if self.vSolver.Cdt != 0 else 1
if error <= self.couplTol:
print(ccolors.ANSI_GREEN, '{:>4.0f}| {:>7.5f} {:>7.5f} {:>7.5f} | {:>6.4f} {:>6.4f} | {:>6.3f}\n'.format(couplIter, self.iSolverAPI.getCl(), self.iSolverAPI.getCd()+self.vSolver.Cdf, self.vSolver.Cdt, self.vSolver.getxoctr(0, 0), self.vSolver.getxoctr(0, 1), np.log10(error)), ccolors.ANSI_RESET)
return aeroCoeffs
cdPrev = self.vSolver.Cdt
if couplIter == 0:
print('- AoA: {:<2.2f} Mach: {:<1.1f} Re: {:<2.1f}e6'.format(self.iSolverAPI.getAoA()*180/math.pi, self.iSolverAPI.getMinf(), self.vSolver.getRe()/1e6))
print('{:>5s}| {:>7s} {:>7s} {:>7s} | {:>6s} {:>6s} | {:>6s}'.format('It', 'Cl', 'Cd', 'Cdwake', 'xtrT', 'xtrB', 'Error'))
print(' ----------------------------------------------------------')
if couplIter % self.iterPrint == 0:
print(' {:>4.0f}| {:>7.4f} {:>7.4f} {:>7.4f} | {:>6.4f} {:>6.4f} | {:>6.3f}'.format(couplIter, self.iSolverAPI.getCl(), self.iSolverAPI.getCd()+self.vSolver.Cdf, self.vSolver.Cdt, self.vSolver.getxoctr(0, 0), self.vSolver.getxoctr(0, 1), np.log10(error)))
if self.iSolverAPI.getVerbose() != 0 or self.vSolver.verbose != 0:
print('')
couplIter += 1
self.tms['processing'].stop()
else:
print(ccolors.ANSI_RED, 'Maximum number of {:<.0f} coupling iterations reached'.format(self.maxCouplIter), ccolors.ANSI_RESET)
print('')
print('{:>5s}| {:>7s} {:>7s} {:>7s} | {:>6s} {:>8s} | {:>6s}'.format('It', 'Cl', 'Cd', 'Cdwake', 'xtrT', 'xtrB', 'Error'))
print(' ----------------------------------------------------------')
print(ccolors.ANSI_RED, '{:>4.0f}| {:>7.5f} {:>7.5f} {:>7.5f} | {:>6.4f} {:>7.4f} | {:>6.3f}\n'.format(couplIter, self.iSolverAPI.getCl(), self.iSolverAPI.getCd()+self.vSolver.Cdf, self.vSolver.Cdt, self.vSolver.getxoctr(0, 0), self.vSolver.getxoctr(0, 1), np.log10(error)), ccolors.ANSI_RESET)
return aeroCoeffs