Skip to content
Snippets Groups Projects
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