From f8b942dffa30274e90f492f4413f569c98b80098 Mon Sep 17 00:00:00 2001 From: Dechamps Paul <paul.dechamps@student.uliege.be> Date: Tue, 23 Nov 2021 00:59:49 +0100 Subject: [PATCH] Mesh adaptation fixed. --- dart/tests/bliHighLift.py | 2 +- dart/tests/bliNonLift.py | 4 +- dart/tests/bliSeparated.py | 4 +- dart/tests/bliTransonic.py | 2 +- dart/viscous/Drivers/VDriver.py | 37 ++-- dart/viscous/Drivers/VGroupConstructor.py | 204 +++++++++++++--------- dart/viscous/Drivers/VPostProcess.py | 7 +- dart/viscous/Physics/VClosures.py | 44 ++--- dart/viscous/Physics/VDataStructures.py | 36 ++-- dart/viscous/Physics/VVariables.py | 34 ++-- dart/viscous/Solvers/VSolver.py | 2 - dart/viscous/Solvers/VTimeSolver.py | 18 +- 12 files changed, 224 insertions(+), 170 deletions(-) diff --git a/dart/tests/bliHighLift.py b/dart/tests/bliHighLift.py index c2029fa..900259c 100755 --- a/dart/tests/bliHighLift.py +++ b/dart/tests/bliHighLift.py @@ -66,7 +66,7 @@ def main(): user_xtr=[None,None] user_Ti=None - mapMesh = 0 + mapMesh = 1 # Time solver parameters Time_Domain=True # True for unsteady solver, False for steady solver diff --git a/dart/tests/bliNonLift.py b/dart/tests/bliNonLift.py index 23ac27a..456ab36 100755 --- a/dart/tests/bliNonLift.py +++ b/dart/tests/bliNonLift.py @@ -68,7 +68,7 @@ def main(): user_xtr=[None,None] user_Ti=None - mapMesh = 0 + mapMesh = 1 # Time solver parameters Time_Domain = True # True for unsteady solver, False for steady solver @@ -89,7 +89,7 @@ def main(): # mesh the geometry print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) tms['msh'].start() - pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.01, 'msLe' : 0.001} + pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.01, 'msLe' : 0.01} #pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.002, 'msLe' : 0.0001} msh, gmshWriter = floD.mesh(dim, 'models/n0012.geo', pars, ['field', 'airfoil', 'downstream']) tms['msh'].stop() diff --git a/dart/tests/bliSeparated.py b/dart/tests/bliSeparated.py index fcae11d..1bc07a1 100755 --- a/dart/tests/bliSeparated.py +++ b/dart/tests/bliSeparated.py @@ -66,7 +66,7 @@ def main(): user_xtr=[None,None] user_Ti=None - mapMesh = 0 + mapMesh = 1 # Time solver parameters Time_Domain=True # True for unsteady solver, False for steady solver @@ -89,7 +89,7 @@ def main(): # mesh the geometry print(ccolors.ANSI_BLUE + 'PyMeshing...' + ccolors.ANSI_RESET) tms['msh'].start() - pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.005, 'msLe' : 0.0001} + pars = {'xLgt' : 5, 'yLgt' : 5, 'msF' : 1, 'msTe' : 0.01, 'msLe' : 0.00001} msh, gmshWriter = floD.mesh(dim, 'models/n0012.geo', pars, ['field', 'airfoil', 'downstream']) tms['msh'].stop() diff --git a/dart/tests/bliTransonic.py b/dart/tests/bliTransonic.py index bc3fd2e..eee531e 100755 --- a/dart/tests/bliTransonic.py +++ b/dart/tests/bliTransonic.py @@ -68,7 +68,7 @@ def main(): user_xtr=[None,None] user_Ti=None - mapMesh = 0 + mapMesh = 1 # Time solver parameters Time_Domain=True # True for unsteady solver, False for steady solver diff --git a/dart/viscous/Drivers/VDriver.py b/dart/viscous/Drivers/VDriver.py index 76c926e..1867c33 100644 --- a/dart/viscous/Drivers/VDriver.py +++ b/dart/viscous/Drivers/VDriver.py @@ -136,15 +136,24 @@ class Driver: dataIn = [None,None] for n in range(0, len(groups)): groups[n].connectListNodes, groups[n].connectListElems, dataIn[n] = groups[n].connectList() - inMesh, paramDict, data, bNodes, inMeshbNodes, xxInit = GroupConstructor().mergeVectors(dataIn, self.mapMesh, nFactor) + fMeshDict, cMeshDict, data = GroupConstructor().mergeVectors(dataIn, self.mapMesh, nFactor) # Initialize data container. - var = Variables(data, paramDict, bNodes, self.xtrF, self.Ti, self.Re) + var = Variables(fMeshDict, self.xtrF, self.Ti, self.Re) if self.it!=0: # Extenal flow local markers. var.extPar[4::var.nExtPar] = data[:,8] + """if self.it >= 0: + plt.plot(var.xGlobal[:var.bNodes[1]], var.extPar[2:var.bNodes[1]*var.nExtPar: var.nExtPar]) + plt.plot(cMeshDict['globCoord'][:cMeshDict['bNodes'][1]], cMeshDict['vtExt'][:cMeshDict['bNodes'][1]],'ob') + plt.plot(var.xGlobal[var.bNodes[1]:var.bNodes[2]], var.extPar[var.bNodes[1]*var.nExtPar + 2:var.bNodes[2]*var.nExtPar: var.nExtPar]) + plt.plot(cMeshDict['globCoord'][cMeshDict['bNodes'][1]:cMeshDict['bNodes'][2]], cMeshDict['vtExt'][cMeshDict['bNodes'][1]:cMeshDict['bNodes'][2]],'or') + plt.plot(var.xGlobal[var.bNodes[2]:], var.extPar[var.bNodes[2]*var.nExtPar + 2:: var.nExtPar]) + plt.plot(cMeshDict['globCoord'][cMeshDict['bNodes'][2]:], cMeshDict['vtExt'][cMeshDict['bNodes'][2]:],'og') + plt.show()""" + # Boundary condition (Airfoil/Wake). DirichletBC=Conditions.Boundaries(self.Re) @@ -165,8 +174,8 @@ class Driver: if self.it == 0: print('+------------------------------- Solver setup ---------------------------------+') if self.mapMesh: - print('| - Mesh mapped from {:>5.0f} to {:>5.0f} elements.{:>35s}'.format(len(inMesh), var.nN, '|')) - print('| - Number of elements: {:<.0f}. {:>51s}'.format(var.nN,'|')) + print('| - Mesh mapped from {:>5.0f} to {:>5.0f} elements.{:>35s}'.format(len(cMeshDict['locCoord']), var.nN, '|')) + print('| - Number of elements: {:>5.0f}. {:>49s}'.format(var.nN,'|')) if var.xtrF[0] is None: print('| - Free transition on the upper side. {:>41}'.format('|')) else: @@ -177,7 +186,7 @@ class Driver: print('| - Forced transition on the lower side; x/c = {:<.4f}. {:>25s}'.format(var.xtrF[1], '|')) print('| - Critical amplification ratio: {:<.2f}. {:>40s}'.format(var.Ncrit,'|')) - # Output solver parameters. + # Output solver parameters. print('|{:>79}'.format('|')) print('| Numerical parameters {:>57}'.format('|')) print('| - CFL0: {:<3.2f} {:>65}'.format(tSolver.getCFL0(),'|')) @@ -200,7 +209,10 @@ class Driver: initializer=Conditions.Initial(DirichletBC) # Compute initial condition based on Twaithes solution. - initializer.initialConditions(var) # Set boundary condition + initializer.initialConditions(var) # Set boundary condition + + tSolver.jacEval0 = 1 + tSolver.setCFL0(1) print('| - Using Twaithes solution as initial guess. {:>34}'.format('|')) @@ -239,7 +251,7 @@ class Driver: self.blParPrevious=var.blPar.copy() # Compute blowing velocities and sort the boundary layer parameters. - self.blScalars, AFblwVel, WKblwVel, AFblVectors, WKblVectors, AFdeltaStarOut, WKdeltaStarOut = PostProcess().sortParam(var, self.mapMesh, inMesh, inMeshbNodes, xxInit) + self.blScalars, AFblwVel, WKblwVel, AFblVectors, WKblVectors, AFdeltaStarOut, WKdeltaStarOut = PostProcess().sortParam(var, self.mapMesh, cMeshDict) self.xtr = var.xtr.copy() self.blVectors = AFblVectors @@ -249,7 +261,7 @@ class Driver: groups[0].HEnd = [AFblVectors[2][var.bNodes[1]-1], AFblVectors[2][var.bNodes[2]-1]] groups[0].CtEnd = [AFblVectors[8][var.bNodes[1]-1], AFblVectors[8][var.bNodes[2]-1]] groups[0].deltaStar = AFdeltaStarOut - groups[0].xx = xxInit[:inMeshbNodes[2]] + groups[0].xx = cMeshDict['locCoord'][:cMeshDict['bNodes'][2]] # Sort the following results in reference frame. groups[0].deltaStar = groups[0].deltaStar[groups[0].connectListNodes.argsort()] @@ -263,12 +275,13 @@ class Driver: self.Cdp = self.blScalars[2] # Cdf comes from the airfoil as there is no friction in the wake. groups[1].deltaStar = WKdeltaStarOut - groups[1].xx = xxInit[inMeshbNodes[2]:] + groups[1].xx = cMeshDict['locCoord'][cMeshDict['bNodes'][2]:] # Sort the following results in reference frame. groups[1].deltaStar = groups[1].deltaStar[groups[1].connectListNodes.argsort()] groups[1].xx = groups[1].xx[groups[1].connectListNodes.argsort()] groups[1].u = WKblwVel[groups[1].connectListElems.argsort()] - - """self.writeFile() - Validation().main(1,self.wData, WKblVectors, var.xGlobal[var.bNodes[2]:]) """ \ No newline at end of file + + """if self.it >= 0: + self.writeFile() + Validation().main(1,self.wData, WKblVectors, var.xGlobal[var.bNodes[2]:])""" \ No newline at end of file diff --git a/dart/viscous/Drivers/VGroupConstructor.py b/dart/viscous/Drivers/VGroupConstructor.py index bca6618..9d1ed68 100755 --- a/dart/viscous/Drivers/VGroupConstructor.py +++ b/dart/viscous/Drivers/VGroupConstructor.py @@ -31,77 +31,116 @@ class GroupConstructor(): """Merges 3 groups upper/lower sides and wake. """ - # Saves the initial mesh. - inMesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][1:,0], dataIn[1][:,0])) - inMeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][1:,0])] - - xxInit_up, _, _, _, _ = self.__getBLcoordinates(dataIn[0][0]) - xxInit_lw, _, _, _, _ = self.__getBLcoordinates(dataIn[0][1]) - xxInit_lw = np.delete(xxInit_lw, 0) # Delete stagnation point doublon. - xxInit_wk, _, _, _, _ = self.__getBLcoordinates(dataIn[1]) - xxInit = np.concatenate((xxInit_up, xxInit_lw, xxInit_wk)) - for k in range(len(dataIn)): if len(dataIn[k]) == 2: # Airfoil case. - - if mapMesh: - dataUpper = self.interpolateToFineMesh(dataIn[k][0], nFactor) - dataLower = self.interpolateToFineMesh(dataIn[k][1], nFactor) - else: - dataUpper = dataIn[k][0] - dataLower = dataIn[k][1] - - xx_up, dv_up, vtExt_up, _, alpha_up = self.__getBLcoordinates(dataUpper) - xx_lw, dv_lw, vtExt_lw, _, alpha_lw = self.__getBLcoordinates(dataLower) + + xx_up, dv_up, vtExt_up, _, alpha_up = self.__getBLcoordinates(dataIn[k][0]) + xx_lw, dv_lw, vtExt_lw, _, alpha_lw = self.__getBLcoordinates(dataIn[k][1]) else: # Wake case - if mapMesh: - dataWake = self.interpolateToFineMesh(dataIn[k], nFactor) - else: - dataWake = dataIn[k] - - xx_wk, dv_wk, vtExt_wk, _, alpha_wk = self.__getBLcoordinates(dataWake) - - # Delete stagnation point doublon - xx_lw = np.delete(xx_lw,0) - dv_lw = np.delete(dv_lw,0) - vtExt_lw = np.delete(vtExt_lw,0) - alpha_lw = np.delete(alpha_lw,0) - - # Nodes at the boundary of the computational domain: - # [Stagnation point, First lower side point, First wake point] - boundaryNodes = np.zeros(3, dtype=int) - boundaryNodes[0] = 0 - boundaryNodes[1] = len(xx_up) - boundaryNodes[2] = len(xx_up) + len(xx_lw) - - param={'xx':None, 'dv':None, 'vtExt':None, 'alpha':None} - param['xx'] = np.concatenate((xx_up,xx_lw,xx_wk)) - param['dv'] = np.concatenate((dv_up,dv_lw,dv_wk)) - param['vtExt'] = np.concatenate((vtExt_up,vtExt_lw,vtExt_wk)) - param['alpha'] = np.concatenate((alpha_up,alpha_lw,alpha_wk)) - - data = np.zeros((len(param['xx']),9)) - data = np.concatenate((dataUpper, dataLower, dataWake), axis=0) - data = np.delete(data,boundaryNodes[1], axis = 0) # Delete stagnation point doublon - - dx = np.zeros(len(param['xx'])) - for i in range(1, len(param['xx'])): - - if i == boundaryNodes[1]: - - dx[i] = param['xx'][i] - param['xx'][0] - elif i == boundaryNodes[2]: - - dx[i] = 0 - - else: + xx_wk, dv_wk, vtExt_wk, _, alpha_wk = self.__getBLcoordinates(dataIn[k]) + + if mapMesh: + # Save initial mesh. + cMesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][1:,0], dataIn[1][:,0])) + cMeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][1:,0])] + cxx = np.concatenate((xx_up, xx_lw[1:], xx_wk)) + cvtExt = np.concatenate((vtExt_up, vtExt_lw[1:], vtExt_wk)) + + # Create fine mesh. + fMeshUp = self.createFineMesh(dataIn[0][0][:,0], nFactor) + fMeshLw = self.createFineMesh(dataIn[0][1][:,0], nFactor) + fMeshWk = self.createFineMesh(dataIn[1][:,0] , nFactor) + fMesh = np.concatenate((fMeshUp, fMeshLw[1:], fMeshWk)) + fMeshbNodes = [0, len(fMeshUp), len(fMeshUp) + len(fMeshLw[1:])] + + fxx_up = self.interpolateToFineMesh(xx_up, fMeshUp, nFactor) + fxx_lw = self.interpolateToFineMesh(xx_lw, fMeshLw, nFactor) + fxx_wk = self.interpolateToFineMesh(xx_wk, fMeshWk, nFactor) + fxx = np.concatenate((fxx_up, fxx_lw[1:], fxx_wk)) + + fvtExt_up = self.interpolateToFineMesh(vtExt_up, fMeshUp, nFactor) + fvtExt_lw = self.interpolateToFineMesh(vtExt_lw, fMeshLw, nFactor) + fvtExt_wk = self.interpolateToFineMesh(vtExt_wk, fMeshWk, nFactor) + fvtExt = np.concatenate((fvtExt_up, fvtExt_lw[1:], fvtExt_wk)) + + fMe_up = self.interpolateToFineMesh(dataIn[0][0][:,5], fMeshUp, nFactor) + fMe_lw = self.interpolateToFineMesh(dataIn[0][1][:,5], fMeshLw, nFactor) + fMe_wk = self.interpolateToFineMesh(dataIn[1][:,5] , fMeshWk, nFactor) + fMe = np.concatenate((fMe_up, fMe_lw[1:], fMe_wk)) + + frho_up = self.interpolateToFineMesh(dataIn[0][0][:,6], fMeshUp, nFactor) + frho_lw = self.interpolateToFineMesh(dataIn[0][1][:,6], fMeshLw, nFactor) + frho_wk = self.interpolateToFineMesh(dataIn[1][:,6] , fMeshWk, nFactor) + frho = np.concatenate((frho_up, frho_lw[1:], frho_wk)) + + fdStarExt_up = self.interpolateToFineMesh(dataIn[0][0][:,7], fMeshUp, nFactor) + fdStarExt_lw = self.interpolateToFineMesh(dataIn[0][1][:,7], fMeshLw, nFactor) + fdStarExt_wk = self.interpolateToFineMesh(dataIn[1][:,7] , fMeshWk, nFactor) + fdStarext = np.concatenate((fdStarExt_up, fdStarExt_lw[1:], fdStarExt_wk)) + + fdv = np.concatenate((dv_up, dv_lw[1:], dv_wk)) + + fMeshDict = {'globCoord': fMesh, 'bNodes': fMeshbNodes, 'locCoord': fxx, + 'vtExt': fvtExt, 'Me': fMe, 'rho': frho, 'deltaStarExt': fdStarext, 'dv': fdv} + + cMe = np.concatenate((dataIn[0][0][:,5], dataIn[0][1][1:,5], dataIn[1][:,5])) + cRho = np.concatenate((dataIn[0][0][:,6], dataIn[0][1][1:,6], dataIn[1][:,6])) + cdStarExt = np.concatenate((dataIn[0][0][:,7], dataIn[0][1][1:,7], dataIn[1][:,7])) + cMeshDict = {'globCoord': cMesh, 'bNodes': cMeshbNodes, 'locCoord': cxx, + 'vtExt': cvtExt, 'Me': cMe, 'rho': cRho, 'deltaStarExt': cdStarExt, 'dv': fdv} + + dataUpper = np.empty((len(fMeshUp), 0)) + dataLower = np.empty((len(fMeshLw), 0)) + dataWake = np.empty((len(fMeshWk), 0)) + for iParam in range(len(dataIn[0][0][0,:])): + interpParamUp = self.interpolateToFineMesh(dataIn[0][0][:,iParam], fMeshUp, nFactor) + dataUpper = np.column_stack((dataUpper, interpParamUp)) + interpParamLw = self.interpolateToFineMesh(dataIn[0][1][:,iParam], fMeshLw, nFactor) + dataLower = np.column_stack((dataLower, interpParamLw)) + interpParamWk = self.interpolateToFineMesh(dataIn[1][:,iParam] , fMeshWk, nFactor) + dataWake = np.column_stack((dataWake, interpParamWk)) + + dataLower = np.delete(dataLower, 0, axis = 0) # Remove stagnation point doublon. + + else: + + Mesh = np.concatenate((dataIn[0][0][:,0], dataIn[0][1][1:,0], dataIn[1][:,0])) + MeshbNodes = [0, len(dataIn[0][0][:,0]), len(dataIn[0][0][:,0]) + len(dataIn[0][1][1:,0])] + + xx = np.concatenate((xx_up, xx_lw[1:], xx_wk)) + vtExt = np.concatenate((vtExt_up, vtExt_lw[1:], vtExt_wk)) + + alpha = np.concatenate((alpha_up, alpha_lw, alpha_wk)) + dv = np.concatenate((dv_up, dv_lw[1:], dv_wk)) + + Me = np.concatenate((dataIn[0][0][:,5], dataIn[0][1][1:,5], dataIn[1][:,5])) + rho = np.concatenate((dataIn[0][0][:,6], dataIn[0][1][1:,6], dataIn[1][:,6])) + dStarext = np.concatenate((dataIn[0][0][:,7], dataIn[0][1][1:,7], dataIn[1][:,7])) + + fMeshDict = {'globCoord': Mesh, 'bNodes': MeshbNodes, 'locCoord': xx, + 'vtExt': vtExt, 'Me': Me, 'rho': rho, 'deltaStarExt': dStarext, 'dv': dv} + + cMeshDict = fMeshDict.copy() + + dataUpper = dataIn[0][0] + dataLower = dataIn[0][1][1:, :] + dataWake = dataIn[1] + + data = np.concatenate((dataUpper, dataLower, dataWake), axis = 0) - dx[i] = param['xx'][i] - param['xx'][i-1] + """param = 'rho' + plt.plot(fMeshDict['globCoord'][:fMeshDict['bNodes'][1]], fMeshDict[param][:fMeshDict['bNodes'][1]],'-b') + plt.plot(cMeshDict['globCoord'][:cMeshDict['bNodes'][1]], cMeshDict[param][:cMeshDict['bNodes'][1]],'ob') + plt.plot(fMeshDict['globCoord'][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]], fMeshDict[param][fMeshDict['bNodes'][1]:fMeshDict['bNodes'][2]],'-r') + plt.plot(cMeshDict['globCoord'][cMeshDict['bNodes'][1]:cMeshDict['bNodes'][2]], cMeshDict[param][cMeshDict['bNodes'][1]:cMeshDict['bNodes'][2]],'or') + plt.plot(fMeshDict['globCoord'][fMeshDict['bNodes'][2]:], fMeshDict[param][fMeshDict['bNodes'][2]:],'-g') + plt.plot(cMeshDict['globCoord'][cMeshDict['bNodes'][2]:], cMeshDict[param][cMeshDict['bNodes'][2]:],'og') + plt.show()""" - return inMesh, param, data, boundaryNodes, inMeshbNodes, xxInit + return fMeshDict, cMeshDict, data def __getBLcoordinates(self,data): """Transform the reference coordinates into airfoil coordinates @@ -126,33 +165,30 @@ class GroupConstructor(): return xx, dv, vt, nN, alpha - def interpolateToFineMesh(self, iData, nFactor): - - inMesh = iData[:,0] - - outMesh = [] - for iPoint in range(len(inMesh) - 1): - - dx = inMesh[iPoint + 1] - inMesh[iPoint] - - for iRefinedPoint in range(nFactor): + def interpolateToFineMesh(self, cVector, fMesh, nFactor): + + fVector = np.empty(len(fMesh)-1) + for cPoint in range(len(cVector) - 1): + dv = cVector[cPoint + 1] - cVector[cPoint] - outMesh = np.append(outMesh, inMesh[iPoint] + iRefinedPoint * dx / nFactor) + for fPoint in range(nFactor): + fVector[nFactor * cPoint + fPoint] = cVector[cPoint] + fPoint * dv / nFactor + + fVector = np.append(fVector, cVector[-1]) - outMesh = np.append(outMesh, inMesh[-1]) - outData = np.empty((len(outMesh), len(iData[0,:]))) - outData[:,0] = outMesh + return fVector - for iParam in range(1, len(iData[0, :])): + def createFineMesh(self, cMesh, nFactor): - # Create interpolation function between the initial mesh - # and the function to evaluate. + fMesh = [] + for iPoint in range(len(cMesh) - 1): - f_interp = interpolate.interp1d(inMesh, iData[:,iParam]) + dx = cMesh[iPoint + 1] - cMesh[iPoint] - # Map the function to the new mesh. - outData[:, iParam] = f_interp(outData[:, 0]) + for iRefinedPoint in range(nFactor): - return outData + fMesh = np.append(fMesh, cMesh[iPoint] + iRefinedPoint * dx / nFactor) + fMesh = np.append(fMesh, cMesh[-1]) + return fMesh diff --git a/dart/viscous/Drivers/VPostProcess.py b/dart/viscous/Drivers/VPostProcess.py index 3d844db..92f0d7b 100644 --- a/dart/viscous/Drivers/VPostProcess.py +++ b/dart/viscous/Drivers/VPostProcess.py @@ -6,7 +6,7 @@ class PostProcess: def __init__(self): pass - def sortParam(self,var, mapMesh, inMesh, inMeshbNodes, xxInit): + def sortParam(self,var, mapMesh, cMeshDict): # Recompute deltaStar. @@ -14,6 +14,9 @@ class PostProcess: var.blPar[9::var.nBlPar] = var.u[0::var.nVar] * var.u[1::var.nVar] if mapMesh: + inMesh = cMeshDict['globCoord'] + inMeshbNodes = cMeshDict['bNodes'] + xxInit = cMeshDict['locCoord'] rho, invVel, deltaStar = self.inverseMeshMapping(var, inMesh, inMeshbNodes) @@ -52,8 +55,6 @@ class PostProcess: blwVel[iPoint-1] = (var.extPar[iPoint*var.nExtPar+1] * var.u[iPoint*var.nVar+3] * var.blPar[iPoint*var.nBlPar+9] - var.extPar[iPrev*var.nExtPar+1] * var.u[iPrev*var.nVar+3] * var.blPar[iPrev*var.nBlPar+9]) / (var.extPar[iPoint*var.nExtPar+1] * (var.xx[iPoint] - var.xx[iPrev])) - print('blwVel bnodes2', blwVel[var.bNodes[2]]) - print('blwVel bnodes2-1', blwVel[var.bNodes[2]-1]) blwVel = np.delete(blwVel, var.bNodes[2]) # Separate airfoil and wake blowing velocities. AFblwVel=blwVel[:var.bNodes[2]-1] diff --git a/dart/viscous/Physics/VClosures.py b/dart/viscous/Physics/VClosures.py index 28e4491..1acad30 100755 --- a/dart/viscous/Physics/VClosures.py +++ b/dart/viscous/Physics/VClosures.py @@ -28,10 +28,9 @@ class Closures: Hk = (H - 0.29*Me**2)/(1+0.113*Me**2) # Kinematic shape factor if name == "airfoil": Hk = max(Hk, 1.02) - Hk = min(Hk,6) else: Hk = max(Hk, 1.00005) - Hk = min(Hk,6) + Hk = min(Hk,6) Hstar2 = (0.064/(Hk-0.8)+0.251)*Me**2 # Density shape parameter delta = min((3.15+ H + (1.72/(Hk-1)))*theta, 12*theta) Hks = Hk - 4.35 @@ -63,40 +62,35 @@ class Closures: """Turbulent closure derived from Nishida and Drela (1996) """ # eliminate absurd transients - Ct = min(Ct, 0.30) - Ct = max(Ct, 0.0000001) + Ct = max(min(Ct, 0.30), 0.0000001) Hk = (H - 0.29*Me**2)/(1+0.113*Me**2) - if name == 'wake': - Hk = max(Hk, 1.00005) - Hk = min(Hk,10) - else: - Hk = max(Hk, 1.00005) - Hk = min(Hk,10) + Hk = max(min(Hk, 10), 1.00005) Hstar2 = ((0.064/(Hk-0.8))+0.251)*Me**2 gam = 1.4 - 1 Fc = np.sqrt(1+0.5*gam*Me**2) + if Ret <= 400: H0 = 4 elif Ret > 400: H0 = 3 + (400/Ret) - if Ret > 200: - Ret = Ret - elif Ret <= 200: - Ret = 200 + + Ret = max(Ret, 200) + if Hk <= H0: Hstar = ((0.5-4/Ret)*((H0-Hk)/(H0-1))**2)*(1.5/(Hk+0.5))+1.5+4/Ret elif Hk > H0: Hstar = (Hk-H0)**2*(0.007*np.log(Ret)/(Hk-H0+4/np.log(Ret))**2 + 0.015/Hk) + 1.5 + 4/Ret + Hstar = (Hstar + 0.028*Me**2)/(1+0.014*Me**2) # Whitfield's minor additional compressibility correction logRt = np.log(Ret/Fc) - logRt = np.max((logRt,3)) - arg = np.max((-1.33*Hk, -20)) + logRt = max(logRt,3) + arg = max(-1.33*Hk, -20) Us = (Hstar/2)*(1-4*(Hk-1)/(3*H)) # Equivalent normalized wall slip velocity delta = min((3.15+ H + (1.72/(Hk-1)))*theta, 12*theta) Ctcon = 0.5/(6.7**2*0.75) + if name == 'wake': - if Us > 0.99995: - Us = 0.99995 + Us = min(Us, 0.99995) n = 2 # two wake halves Cf = 0 # no friction inside the wake Hkc = Hk - 1 @@ -109,15 +103,16 @@ class Closures: n = 1 Cf = (1/Fc)*(0.3*np.exp(arg)*(logRt/2.3026)**(-1.74-0.31*Hk)+0.00011*(np.tanh(4-(Hk/0.875))-1)) Hkc = max(Hk-1-18/Ret, 0.01) - # dissipation coefficient + # Dissipation coefficient Hmin = 1 + 2.1/np.log(Ret) Fl = (Hk-1)/(Hmin-1) Dfac = 0.5+0.5*np.tanh(Fl) Cdw = 0.5*(Cf*Us) * Dfac Cdd = (0.995-Us)*Ct**2 Cdl = 0.15*(0.995-Us)**2/Ret - if n*Hstar*Ctcon*((Hk-1)*Hkc**2)/((1-Us)*(Hk**2)*H) >= 0: - Cteq = np.sqrt(n*Hstar*Ctcon*((Hk-1)*Hkc**2)/((1-Us)*(Hk**2)*H)) #Here it is Cteq^0.5 + CteqSquared = n*Hstar*Ctcon*((Hk-1)*Hkc**2)/((1-Us)*(Hk**2)*H) + if CteqSquared >= 0: + Cteq = np.sqrt(CteqSquared) #Here it is Cteq^0.5 else: Cteq = 0.03 Cd = n*(Cdw+ Cdd + Cdl) @@ -206,7 +201,7 @@ class Closures: Rnorm = (np.log10(Ret) - (logRet_crit-Dgr))/(2*Dgr) if Rnorm <=0: Rfac = 0 - if Rnorm >= 1: + elif Rnorm >= 1: Rfac = 1 else: Rfac = 3*Rnorm**2 - 2*Rnorm**3 @@ -215,7 +210,7 @@ class Closures: arg = 3.87*Hmi-2.52 dndRet = 0.028*(Hk-1)-0.0345*np.exp(-(arg**2)) Ax = (m*dndRet/theta)*Rfac - # set correction for separated profiles + # Set correction for separated profiles if Hk > Hk1: Hnorm = (Hk - Hk1)/(Hk2-Hk1) if Hnorm >=1: @@ -229,6 +224,5 @@ class Closures: if Ax2 < 0: Ax2 = 0 Ax = Hfac*Ax2 + (1-Hfac)*Ax1 - if Ax < 0: - Ax = 0 + Ax = max(Ax, 0) return Ax \ No newline at end of file diff --git a/dart/viscous/Physics/VDataStructures.py b/dart/viscous/Physics/VDataStructures.py index 7e9903e..ca867fb 100755 --- a/dart/viscous/Physics/VDataStructures.py +++ b/dart/viscous/Physics/VDataStructures.py @@ -16,30 +16,28 @@ # ------------------------------------------------------------------------------ import numpy as np -class DGeometry: +class PGeometry: def __init__(self, data, paramDict, _bNodes): # Private - self.__globCoord = data[:,0] # Global coordinates of each marker - self.__locCoord = paramDict['xx'] # Local coordinates of each marker - self.__nMarkers = len(self.__locCoord) # Number of markers in the computational domain + self.__globCoord = data[:,0] # Global coordinates of each marker + self.__locCoord = paramDict['xx'] # Local coordinates of each marker + self.__nMarkers = len(self.__locCoord) # Number of markers in the computational domain self.__boundaryNodes = _bNodes # Boundary nodes of the computational domain [Stagnation point, # First point on lower side, # First wake point] - # Public - - def GetglobCoord(self): return self.__globCoord - def GetlocCoord(self): return self.__locCoord - def GetnMarkers(self): return self.__nMarkers - def GetglobCoord(self): return self.__bNodes - def GetboundaryNodes(self): return self.__boundaryNodes + def GetglobCoord(self): return self.__globCoord + def GetlocCoord(self): return self.__locCoord + def GetnMarkers(self): return self.__nMarkers + def GetglobCoord(self): return self.__bNodes + def GetboundaryNodes(self): return self.__boundaryNodes -class DSolution: +class PSolution: def __init__(self, _xtrF): @@ -79,7 +77,7 @@ class DSolution: self.__xtr[side] = xtrIn pass - def initializeSolution(self, DGeometry): + def initializeSolution(self, PGeometry): nMarkers = PGeometry.GetnMarkers() self.u = np.empty(self.__nVar * nMarkers) @@ -87,7 +85,7 @@ class DSolution: return self.u, self.blPar -class DOuterFlow: +class POuterFlow: def __init__(self, data) -> None: @@ -100,6 +98,14 @@ class DOuterFlow: self.outerLocCoord = self.outerRe = +class PDataContainer: + def __init__(self, _Re) -> None: + + self.Re = _Re # Flow reynolds number. + self.Geometry = PGeometry() # Geometry components. + self.Solution = PSolution() # Solution components. + self.OuterFlow = POuterFlow() # Outer (inviscid) flow parameters. + @@ -214,4 +220,4 @@ class DVariables: Ncrit=-8.43-2.4*np.log(tau/100) # Drela 1998 else: Ncrit=9 - return Ncrit + return Ncrit \ No newline at end of file diff --git a/dart/viscous/Physics/VVariables.py b/dart/viscous/Physics/VVariables.py index 094e74d..5e4e026 100755 --- a/dart/viscous/Physics/VVariables.py +++ b/dart/viscous/Physics/VVariables.py @@ -66,13 +66,13 @@ class Variables: - Critical amplification ratio for the e^N method (default value= 9.) """ - def __init__(self, data, paramDict, bNodes, xtrF, Ti, Re): + def __init__(self, fMeshDict, xtrF, Ti, Re): self.__Ti = Ti self.Re = Re - self.xx = paramDict['xx'] + self.xx = fMeshDict['locCoord'] self.nN = len(self.xx) - self.bNodes = bNodes + self.bNodes = fMeshDict['bNodes'] # Solution self.nVar = 5 self.u = np.zeros(self.nVar*self.nN) @@ -93,13 +93,13 @@ class Variables: self.nExtPar = 6 self.extPar = np.zeros(self.nExtPar*self.nN) - self.extPar[0::self.nExtPar] = data[:,5] - self.extPar[1::self.nExtPar] = data[:,6] - self.extPar[2::self.nExtPar] = paramDict['vtExt'] - self.extPar[3::self.nExtPar] = data[:,7] - self.extPar[4::self.nExtPar] = paramDict['xx'] - self.dv = paramDict['dv'] - self.xGlobal = data[:,0] + self.extPar[0::self.nExtPar] = fMeshDict['Me'] + self.extPar[1::self.nExtPar] = fMeshDict['rho'] + self.extPar[2::self.nExtPar] = fMeshDict['vtExt'] + self.extPar[3::self.nExtPar] = fMeshDict['deltaStarExt'] + self.extPar[4::self.nExtPar] = fMeshDict['locCoord'] + self.dv = fMeshDict['dv'] + self.xGlobal = fMeshDict['globCoord'] self.flowRegime = np.zeros(self.nN, dtype=int) @@ -122,11 +122,13 @@ class Variables: pass def turbIntensity(self,Ti): - '''Computes the critical amplification ratio Ncrit based on the input - free-stream turbulence intensity. Ncrit=9 by default.''' - if Ti is not None and Ti<=1: - tau=2.7*np.tanh(self.Ti/2.7) - Ncrit=-8.43-2.4*np.log(tau/100) # Drela 1998 + """Computes the critical amplification ratio Ncrit based on the input + free-stream turbulence intensity. Ncrit=9 by default. + """ + + if Ti is not None and Ti <= 1: + tau = 2.7 * np.tanh(self.Ti / 2.7) + Ncrit = -8.43 - 2.4*np.log(tau / 100) # Drela 1998 else: - Ncrit=9 + Ncrit = 9 return Ncrit diff --git a/dart/viscous/Solvers/VSolver.py b/dart/viscous/Solvers/VSolver.py index 91bf0b9..64a8e58 100644 --- a/dart/viscous/Solvers/VSolver.py +++ b/dart/viscous/Solvers/VSolver.py @@ -154,8 +154,6 @@ class flowEquations: # Shear lag equation ignored in the laminar portion of the flow timeMatrix[4] = [0, 0, 0, 0, 1] - if np.linalg.det(timeMatrix) == 0: - raise RuntimeError('Singular time matrix.') sysRes = np.linalg.solve(timeMatrix, spaceMatrix).flatten() return sysRes diff --git a/dart/viscous/Solvers/VTimeSolver.py b/dart/viscous/Solvers/VTimeSolver.py index 1b4fe23..3e6de63 100644 --- a/dart/viscous/Solvers/VTimeSolver.py +++ b/dart/viscous/Solvers/VTimeSolver.py @@ -18,6 +18,7 @@ from dart.viscous.Physics.VClosures import Closures from matplotlib import pyplot as plt from fwk.coloring import ccolors +import scipy.sparse.linalg as linSolver import numpy as np import math @@ -122,8 +123,10 @@ class implicitEuler(timeConfig): # Initialize time parameters self.__CFL0=_cfl0 - self.__maxIt = 20000 + self.__maxIt = 15000 self.__tol = 1e-8 + self.jacEval0 = 5 + self.solver=_solver self.transSolver = transition self.wakeBC = wakeBC @@ -324,7 +327,7 @@ class implicitEuler(timeConfig): CFL = self.__CFL0 # Initialized CFL number. CFLAdapt = 1 # Flag for CFL adaptation. - jacEval = 3 # Number of iterations for which Jacobian is frozen. + jacEval = self.jacEval0 # Number of iterations for which Jacobian is frozen. dt = self.computeTimeStep(CFL, dx, iInvVel) # Initial time step. IMatrix=np.identity(nVar) / dt # Identity matrix used to construct the linear system. @@ -344,6 +347,7 @@ class implicitEuler(timeConfig): # Linear solver. slnIncr = np.linalg.solve((Jacobian + IMatrix), - sysRes) + #slnIncr, exitCode = linSolver.gmres((Jacobian + IMatrix), -sysRes, tol = 1e-10) # Increment solution and correct absurd transcient results. @@ -408,7 +412,7 @@ class implicitEuler(timeConfig): CFL = self.__CFL0* (normSysRes0/normSysRes)**0.7 - CFL = max(CFL, 0.1) + CFL = max(CFL, 0.01) dt = self.computeTimeStep(CFL, dx, iInvVel) IMatrix=np.identity(nVar) / dt @@ -418,8 +422,8 @@ class implicitEuler(timeConfig): else: # Maximum number of iterations reached. if normSysRes >= 1e-3 * normSysRes0: - print('|', ccolors.ANSI_RED + 'Too many iteration at position {:<.4f}. normLinSysRes = {:<.3f}. {:>30s}' - .format(var.xGlobal[iMarker], + print('|', ccolors.ANSI_RED + 'Too many iteration at position {:<.4f}. Marker: {:>5.0f}. normLinSysRes = {:<.3f}. {:>30s}' + .format(var.xGlobal[iMarker], iMarker, np.log10(normSysRes/normSysRes0),'|'), ccolors.ANSI_RESET) var.u[iMarker*nVar:(iMarker+1)*nVar] = u0[(iMarker)*nVar: (iMarker+1)*nVar].copy() @@ -440,8 +444,8 @@ class implicitEuler(timeConfig): var.extPar[iMarker*nExtPar+0], name) else: - print('|', ccolors.ANSI_YELLOW+ 'Too many iteration at position {:<.4f}. normLinSysRes = {:<.3f}. {:>30s}' - .format(var.xGlobal[iMarker], + print('|', ccolors.ANSI_YELLOW+ 'Too many iteration at position {:<.4f}. Marker: {:>5.0f} normLinSysRes = {:<.3f}. {:>30s}' + .format(var.xGlobal[iMarker], iMarker, np.log10(normSysRes/normSysRes0),'|'), ccolors.ANSI_RESET) -- GitLab