diff --git a/blast/api/blaster_api.py b/blast/api/blaster_api.py index 5551c3128ba1dc9d40d4bd94ab8913470091ae25..85fb54c968510dac49d7dd057eaf79396cc6c853 100644 --- a/blast/api/blaster_api.py +++ b/blast/api/blaster_api.py @@ -67,7 +67,7 @@ def init_blaster(cfg, icfg, iSolverName='DART', task='analysis'): raise RuntimeError('BLASTERAPI: Missing or invalid Reynolds number') _Re = cfg['Re'] - _Minf = cfg.get('Minf', 0.1) + _Minf = cfg.get('Minf', 0.1) # Used for time step computation only. _cfl0 = cfg.get('CFL0', 1.) _verbose = cfg.get('Verb', 0) _xtrF = cfg.get('xtrF', [-1, -1]) diff --git a/blast/tests/dart/adjoint_2D.py b/blast/tests/dart/adjoint_2D.py index 0c543385e21adb5f1febfb97ed1f83a5566d873d..049a421232e3145846f5ff44dfffea119083822e 100644 --- a/blast/tests/dart/adjoint_2D.py +++ b/blast/tests/dart/adjoint_2D.py @@ -84,7 +84,7 @@ def cfgBlast(verb): 'resetInv' : True, # bool, flag to reset the inviscid calculation at every iteration. 'sections' : [0], # List of sections for boundary layer calculation 'xtrF' : [0.2, 0.2], # Forced transition locations - 'interpolator' : 'Matching', # Interpolator for the coupling + 'interpolator' : 'Matching' # Interpolator for the coupling } def main(): diff --git a/blast/tests/dart/rae2822_3D.py b/blast/tests/dart/rae2822_3D.py index 52ee476e533d0c918a7010814b5a27d3245fde28..2f0e2432872f4486d936911622d6ad59e0052de1 100644 --- a/blast/tests/dart/rae2822_3D.py +++ b/blast/tests/dart/rae2822_3D.py @@ -146,9 +146,9 @@ def main(): print(ccolors.ANSI_BLUE + 'PyTesting...' + ccolors.ANSI_RESET) tests = CTests() tests.add(CTest('Cl', isol.getCl(), 0.135, 5e-2)) - tests.add(CTest('Cd wake', vsol.Cdt, 0.0074, 1e-3, forceabs=True)) - tests.add(CTest('Cd integral', vsol.Cdf + isol.getCd(), 0.0140, 1e-3, forceabs=True)) - tests.add(CTest('Cdf', vsol.Cdf, 0.0061, 1e-3, forceabs=True)) + tests.add(CTest('Cd wake', vsol.Cdt, 0.00603, 1e-2)) + tests.add(CTest('Cd integral', vsol.Cdf + isol.getCd(), 0.0134, 1e-2)) + tests.add(CTest('Cdf', vsol.Cdf, 0.00557, 1e-2)) tests.add(CTest('Iterations', len(aeroCoeffs), 3, 0, forceabs=True)) tests.run() diff --git a/blast/tests/test_api_3D.py b/blast/tests/test_api_3D.py deleted file mode 100644 index 695925204c173341523bae3cd5ea37b762877195..0000000000000000000000000000000000000000 --- a/blast/tests/test_api_3D.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# Copyright 2022 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. - - -# @author Paul Dechamps -# @date 2024 -# Test the blaster api for a 2D problem. - -# Imports. -from fwk.wutils import parseargs -import fwk -from fwk.testing import * -from fwk.coloring import ccolors -import blast.utils as vutils - -import math -import numpy as np -import os - -from blast.api.blaster_api import init_blaster - -def cfgInviscid(nthrds, verb): - # Parameters - return { - # Options - 'scenario' : 'aerodynamic', - 'task' : 'analysis', - 'Threads' : nthrds, # number of threads - 'Verb' : verb, # verbosity - # Model (geometry or mesh) - 'File' : os.path.abspath(os.path.join(os.path.abspath(__file__), '../../models/dart/rae_3.geo')), # Input file containing the model - 'Pars' : {'spn' : 1.0, 'lgt' : 6.0, 'wdt' : 3.0, 'hgt' : 6.0, 'msN' : 0.02, 'msF' : 1}, # parameters for input file model - 'Dim' : 3, # problem dimension - 'Format' : 'vtk', # save format (vtk or gmsh) - # Markers - 'Fluid' : 'field', # name of physical group containing the fluid - 'Farfield' : ['upstream', 'farfield', 'downstream'], # LIST of names of physical groups containing the farfield boundaries (upstream/downstream should be first/last element) - 'Wings' : ['wing'], # LIST of names of physical groups containing the lifting surface boundary - 'Wakes' : ['wake'], # LIST of names of physical group containing the wake - 'WakeTips' : ['wakeTip'], # LIST of names of physical group containing the edge of the wake - 'Tes' : ['te'], # LIST of names of physical group containing the trailing edge - 'Symmetry': 'symmetry', # name of physical group containing the symmetry BC - 'Upstream' : 'upstream', - # Freestream - 'M_inf' : 0.8, # freestream Mach number - 'AoA' : 0.0, # freestream angle of attack - # Geometry - 'S_ref' : 1.0, # reference surface length - 'c_ref' : 1.0, # reference chord length - 'x_ref' : 0.0, # reference point for moment computation (x) - 'y_ref' : 0.0, # reference point for moment computation (y) - 'z_ref' : 0.0, # reference point for moment computation (z) - # Numerical - 'LSolver' : 'GMRES', # inner solver (Pardiso, MUMPS or GMRES) - 'G_fill' : 2, # fill-in factor for GMRES preconditioner - 'G_tol' : 1e-5, # tolerance for GMRES - 'G_restart' : 50, # restart for GMRES - 'Rel_tol' : 1e-6, # relative tolerance on solver residual - 'Abs_tol' : 1e-8, # absolute tolerance on solver residual - 'Max_it' : 50 # solver maximum number of iterations - } - -def cfgBlast(verb): - return { - 'Re' : 1e7, # Freestream Reynolds number - 'Minf' : 0.8, # Freestream Mach number (used for the computation of the time step only) - 'CFL0' : 1, # Inital CFL number of the calculation - - 'sections' : np.linspace(0.01, 0.95, 3), # Sections on the wing - 'writeSections': [0.2, 0.4, 0.6, 0.8, 1.0], # Spanwise locations to write the solution - 'Sym':[0.], # Symmetry plane - 'span': 1., # Span of the wing - 'interpolator': 'Rbf', # Interpolator type - 'rbftype': 'linear', # Radial basis function (rbf) type - 'smoothing': 1e-8, # rbf smoothing factor - 'degree': 0, # Degree of the interpolator - 'neighbors': 10, # Number of neighbors for the interpolator - 'saveTag': 4, # Tag to save the solution with VTK - - 'Verb': verb, # Verbosity level of the solver - 'couplIter': 5, # Maximum number of iterations - 'couplTol' : 5e-2, # Tolerance of the VII methodology - 'iterPrint': 1, # int, number of iterations between outputs - 'resetInv' : False, # bool, flag to reset the inviscid calculation at every iteration. - 'xtrF' : [0., 0.], # Forced transition locations - } - -def main(): - # Timer. - tms = fwk.Timers() - tms['total'].start() - - args = parseargs() - icfg = cfgInviscid(args.k, args.verb) - vcfg = cfgBlast(args.verb) - - parsViscous = {'spn': icfg['Pars']['spn'], 'lgt': icfg['Pars']['lgt'], - 'nLe': 25, 'nMid': 50, 'nTe': 10, 'nSpan': 60, 'nWake': 25, - 'progLe': 1.1, 'progMid': 1.0, 'progTe': 1.0, 'progSpan': 1.0, 'progWake': 1.15} - - vMeshFile = os.path.abspath(os.path.join(os.path.abspath(__file__), '../../models/dart/rae_3_visc.geo')) - vMsh = vutils.mesh(vMeshFile, parsViscous) - vcfg['vMsh'] = vMsh - - # Init via API - obj = init_blaster(vcfg, icfg, iSolverName='DART', task='analysis') - coupler, isol, vsol = obj['coupler'], obj['isol'], obj['vsol'] - - # Init via utils - coupler2, isol2, vsol2 = vutils.initBlast(icfg, vcfg) - - print(ccolors.ANSI_BLUE + 'PySolving...' + ccolors.ANSI_RESET) - tms['solver'].start() - aeroCoeffs = coupler.run() - aeroCoeffs2 = coupler2.run() - tms['solver'].stop() - - # Display results. - print(ccolors.ANSI_BLUE + 'PyRes...' + ccolors.ANSI_RESET) - print(' Re M alpha Cl Cd Cd_wake Cdp Cdf Cm') - print('{0:6.1f}e6 {1:8.2f} {2:8.1f} {3:8.4f} {4:8.4f} {5:8.4f} {6:8.4f} {7:8.4f} {8:8.4f}'.format(vcfg['Re']/1e6, isol.getMinf(), isol.getAoA()*180/math.pi, isol.getCl(), vsol.Cdf + isol.getCd(), vsol.Cdt, vsol.Cdp, vsol.Cdf, isol.getCm())) - - # Save results - isol.save(sfx='_viscous') - tms['total'].stop() - - print(ccolors.ANSI_BLUE + 'PyTiming...' + ccolors.ANSI_RESET) - print('CPU statistics') - print(tms) - print('SOLVERS statistics') - print(coupler.tms) - - # Test solution - print(ccolors.ANSI_BLUE + 'PyTesting...' + ccolors.ANSI_RESET) - tests = CTests() - tests.add(CTest('Cl', isol.getCl(), isol2.getCl(), 1e-12)) - tests.add(CTest('Cd wake', vsol.Cdt, vsol2.Cdt, 1e-12, forceabs=True)) - tests.add(CTest('Cd integral', vsol.Cdf + isol.getCd(), vsol2.Cdf + isol2.getCd(), 1e-12, forceabs=True)) - tests.add(CTest('Cdf', vsol.Cdf, vsol2.Cdf, 1e-12, forceabs=True)) - tests.add(CTest('Iterations', len(aeroCoeffs), len(aeroCoeffs2), 0, forceabs=True)) - tests.run() - - # eof - print('') - -if __name__ == "__main__": - main() diff --git a/blast/utils.py b/blast/utils.py index 8bb1cb5f821efdc6566c157f1186854db327ccfe..c7e36d6dbf6c01c9c9ab7dd9b6942c1f75030c72 100644 --- a/blast/utils.py +++ b/blast/utils.py @@ -3,7 +3,7 @@ from fwk.wutils import parseargs from fwk.coloring import ccolors import numpy as np -def initBL(Re, Minf, CFL0, nSections, span, xtrF = [None, None], verb=None): +def initBL(Re, Minf, CFL0, nSections, xtrF = [None, None], span=1.0, verb=None): """ Initialize boundary layer solver. Params @@ -72,8 +72,10 @@ def initBlast(iconfig, vconfig, iSolver='DART'): vconfig['nSections'] = len(vconfig['sections']) if 'sfx' not in vconfig: vconfig['sfx'] = '' + if 'span' not in vconfig: + vconfig['span'] = 1.0 # Viscous solver - vSolver = initBL(vconfig['Re'], vconfig['Minf'], vconfig['CFL0'], vconfig['nSections'], span=vconfig['span'], xtrF=vconfig['xtrF'], verb=vconfig['Verb']) + vSolver = initBL(vconfig['Re'], vconfig['Minf'], vconfig['CFL0'], vconfig['nSections'], xtrF=vconfig['xtrF'], span=vconfig['span'], verb=vconfig['Verb']) # Inviscid solver if iSolver == 'DART':