Post.Rotor: rotor specific post-processing
Specific post-processing for rotors or propellers.
Those functions work with a solution tree “t” or a blade surface tree “teff”.
List of functions
– Force extractions
Extract the radius field, using the rotation axis and center. |
|
Extract the theta field, using the rotation axis and center. |
|
Extract slices on blade and compute Kp,Cf,CnM2,CmM2. |
|
Compute Zb. |
|
Compute thrust and torque. |
– Accumulator export
Export accumulator (psi,rad) in a zone for a given psi. |
|
Export accumulator (psi,rad) in a zone for a given radius. |
|
Export accumulator (psi,rad) in a map zone. |
Contents
Force extractions
- Post.Rotor.extractRadius(teff, axis_pnt, axis_vct, loc='node')
Extract the radius field on a surface, using the rotation axis and center.
- Parameters:
teff ([zone, list of zones, base, tree]) – surface stress tree
axis_pnt (list of 3 floats) – center of rotation
axis_vct (list of 3 floats) – axis of rotation
loc (string, 'node' or 'center') – location of the new field ‘Radius’
- Returns:
teff
- Return type:
same as input with new flow field
Example of use:
import Transform.PyTree as T import Generator.PyTree as G import Converter.PyTree as C import Converter.Internal as Internal import Post.Rotor as Rotor import math a = G.cylinder((0.,0.,0.), 0.5, 1., 360., 0., 10., (50,50,30)) coordZ = Internal.getNodeFromName(a, 'CoordinateZ')[1] coordX = Internal.getNodeFromName(a, 'CoordinateX')[1] Internal.getNodeFromName(a, 'CoordinateZ')[1] = coordX Internal.getNodeFromName(a, 'CoordinateX')[1] = coordZ axis_pnt = (0,0,0) axis_vct = [1,0,0] theta = 25. costheta = math.cos(math.radians(theta)) sintheta = - math.sin(math.radians(theta)) a = T.rotate(a, (0,0,0), (0.,theta,0.)) a = T.rotate(a, (0,0,0), (0.,0.,theta)) a = T.rotate(a, (0,0,0), (theta,0.,0.)) #rotation y x,y,z = axis_vct axis_vct[0] = costheta*x + sintheta*z axis_vct[1] = y axis_vct[2] = - sintheta*x + costheta*z #rotation z x,y,z = axis_vct axis_vct[0] = costheta*x + sintheta*y axis_vct[1] = - sintheta*x + costheta*y axis_vct[2] = z #rotation x x,y,z = axis_vct axis_vct[0] = x axis_vct[1] = costheta*y + sintheta*z axis_vct[2] = - sintheta*y + costheta*z a = Rotor.extractRadius(a, axis_pnt, axis_vct) C.convertPyTree2File(a, 'out.cgns')
- Post.Rotor.extractTheta(teff, axis_pnt, axis_vct, loc='node')
Extract the theta field on a surface, using the rotation axis and center. Theta values are comprised between 0 and 2*pi.
- Parameters:
teff ([zone, list of zones, base, tree]) – surface stress tree
axis_pnt (list of 3 floats) – center of rotation
axis_vct (list of 3 floats) – axis of rotation
loc (string, 'node' or 'center') – location of the new field ‘Theta’
- Returns:
teff
- Return type:
same as input with new flow field
Example of use:
import Transform.PyTree as T import Generator.PyTree as G import Converter.PyTree as C import Converter.Internal as Internal import Post.Rotor as Rotor import math a = G.cylinder((0.,0.,0.), 0.5, 1., 360., 0., 10., (50,50,30)) coordZ = Internal.getNodeFromName(a, 'CoordinateZ')[1] coordX = Internal.getNodeFromName(a, 'CoordinateX')[1] Internal.getNodeFromName(a, 'CoordinateZ')[1] = coordX Internal.getNodeFromName(a, 'CoordinateX')[1] = coordZ axis_pnt = (0,0,0) axis_vct = [1,0,0] theta = 25. costheta = math.cos(math.radians(theta)) sintheta = - math.sin(math.radians(theta)) a = T.rotate(a, (0,0,0), (0.,theta,0.)) a = T.rotate(a, (0,0,0), (0.,0.,theta)) a = T.rotate(a, (0,0,0), (theta,0.,0.)) #rotation y x,y,z = axis_vct axis_vct[0] = costheta*x + sintheta*z axis_vct[1] = y axis_vct[2] = - sintheta*x + costheta*z #rotation z x,y,z = axis_vct axis_vct[0] = costheta*x + sintheta*y axis_vct[1] = - sintheta*x + costheta*y axis_vct[2] = z #rotation x x,y,z = axis_vct axis_vct[0] = x axis_vct[1] = costheta*y + sintheta*z axis_vct[2] = - sintheta*y + costheta*z a = Rotor.extractTheta(a, axis_pnt, axis_vct) C.convertPyTree2File(a, 'out.cgns')
- Post.Rotor.extractSlices(teff, bladeName, psi, radii, RoInf, PInf, ASOUND, Mtip, AR, CHORD, MU, adimCnM2=0, adimCmM2=0, adimKp=0, relativeShaft=0., localFrame=True, delta=0.05, rotationCenter=[0., 0., 0.], coordDir='CoordinateZ', coordSlice='CoordinateX', sliceNature='straight', accumulatorSlices=None, accumulatorCnM2=None, accumulatorCmM2=None)
Extract slices on blades. Export Cp, Cf on those slices. Compute CnM2 and CmM2 on those slices.
- Parameters:
teff ([zone, list of zones, base, tree]) – surface stress tree
bladeName (string) – name of the blade base to work with
psi (float) – angular angle of blade in teff (in degree)
radii (list of floats) – list of radii at which the solution on the blade must be extracted
RoInf (float) – infinite flow density
PInf (float) – infinite flow pressure
ASOUND (float) – infinite flow sound speed
Mtip (float) – blade mach tip
AR (float) – blade length
CHORD (float) – blade mean chord
MU (float) – advance ratio
adimCnM2 (float) – scaling value for CnM2. If adimCnM2=0, automatically computes the value with adimCnM2=0.5*RoInf*ASOUND**2*CHORD
adimCmM2 (float) – scaling value for CmM2. If adimCmM2=0, automatically computes the value with adimCmM2=0.5*RoInf*ASOUND**2*CHORD
adimKp (float) – scaling value for adimKp. If adimKp=0, automatically computes the value with adimKp=0.5*RoInf*(abs(radius)*Mtip*ASOUND/AR+MU*Mtip*ASOUND*math.sin(psi))**2
relativeShaft (float) – relative shaft angle if the mesh is not in the wind frame
localFrame (boolean) – if True, return CnM2 and CmM2 in relative (blade section) frame
delta (float) – mean mesh step on blade in the span wise direction
rotationCenter (list of floats) – coordinates of the center of rotation
coordDir (string ('CoordinateX', 'CooridnateY' or 'CoordinateZ')) – axis of rotation
coordSlice (string ('CoordinateX', 'CooridnateY' or 'CoordinateZ')) – slicing direction
sliceNature (string ('straight' or 'curved')) – if ‘straight’, slices the blade in the slicing direction. If ‘curved’, initializes the radius field using both the center and the axis of rotation, and slices at constant radii
accumulatorSlices (dictionary with key values (psi,radius)) – if not None, accumulate slices
accumulatorCnM2 (dictionary with key values (psi,radius)) – if not None, accumulate CnM2
accumulatorCmM2 (dictionary with key values (psi,radius)) – if not None, accumulate CmM2
- Returns:
list of slices, list of CnM2, list of CmM2 (one for each radius)
- Return type:
list of zones, list of 3 floats, list of 3 floats
Example of use:
# - extractSlices (pyTree) - import Converter.PyTree as C import Post.Rotor as PR import math Mtip = 0.6462; MU = 0.4 CHORD = 0.14; AR = 2.1 RoInf = 1.225; PInf = 101325.; AINF = 340.1 SIGMA = 4*CHORD / (math.pi*AR) teff = C.convertFile2PyTree('stress_419.cgns') accu = {} psi = 419.; radius = [1.2,1.3,2.] slices, CnM2, CmM2 = PR.extractSlices(teff, 'Blade7A_00', psi, radius, RoInf, PInf, AINF, Mtip, AR, CHORD, MU, accumulatorCnM2=accu, localFrame=True, relativeShaft=-12.12) # export for Cp, Cf C.convertPyTree2File(slices, 'slice.cgns') # export for CnM2 maps exp = PR.exportAccumulatorMap(accu, vars=['CnM2x','CnM2y','CnM2z']) C.convertPyTree2File(exp, 'map.cgns')
- Post.Rotor.computeZb(teff, psi, RoInf, ASOUND, Mtip, AR, SIGMA, relativeShaft=0., accumulatorZb=None)
Compute Zb in the wind frame.
- Parameters:
teff ([zone, list of zones, base, tree]) – surface stress tree
psi (float) – angular angle of blade in teff (in degree)
RoInf (float) – infinite flow density
ASOUND (float) – infinite flow sound speed
Mtip (float) – blade mach tip
AR (float) – blade length in m
SIGMA (float) – rotor solidity (= Nb*c / pi*AR)
relativeShaft (float) – relative shaft angle if the mesh is not in the wind frame
accumulatorZb (dictionary) – if not None, accumulate Zb
- Returns:
[Xb,Yb,Zb]
- Return type:
list of 3 floats
Example of use:
# - computeZb (pyTree) - import Converter.PyTree as C import Post.Rotor as PR import math Mtip = 0.6462; MU = 0.4 CHORD = 0.14; AR = 2.1 RoInf = 1.225; PInf = 101325.; AINF = 340.1 SIGMA = 4*CHORD / (math.pi*AR) teff = C.convertFile2PyTree('stress_419.cgns') zb = PR.computeZb(teff, 419., RoInf, AINF, Mtip, AR, SIGMA, relativeShaft=-12.12); print(zb) #> [-1.101453126880057, -0.11259440192933268, 10.18004327358801] accu = {} zb = PR.computeZb(teff, 419., RoInf, AINF, Mtip, AR, SIGMA, relativeShaft=-12.12, accumulatorZb=accu) ret = PR.exportAccumulatorPerRadius(accu, vars=['Xb','Yb','Zb']) C.convertPyTree2File(ret, 'Zb.cgns')
- Post.Rotor.computeThrustAndTorque(teff, psi, PInf, center=(0, 0, 0), relativeShaft=0., accumulatorThrust=None)
Compute Thrust in the rotor frame (that is orthogonal to rotor).
- Parameters:
teff ([zone, list of zones, base, tree]) – surface stress tree
psi (float) – angular angle of blade in teff (in degree)
PInf (float) – infinite flow pressure
center (list of 3 floats) – center for momentum computations
relativeShaft (float) – relative shaft angle if the mesh is not in the rotor frame
accumulatorThrust (dictionary) – if not None, accumulate thrust and torque
- Returns:
thrust=[tx,ty,tz] and torque=[mx,my,mz]
- Return type:
2 lists of 3 floats
Example of use:
# - computeThrustAndTorque (pyTree) - import Converter.PyTree as C import Post.Rotor as PR import math Mtip = 0.6462; MU = 0.4 CHORD = 0.14; AR = 2.1 RoInf = 1.225; PInf = 101325.; AINF = 340.1 SIGMA = 4*CHORD / (math.pi*AR) teff = C.convertFile2PyTree('stress_419.cgns') thrust,torque = PR.computeThrustAndTorque(teff, 419., PInf, center=(0,0,0), relativeShaft=0.); print('thrust', thrust, 'torque',torque) #> thrust [368.952736931205, -39.172151751517326, 3543.2002154791667] torque [226.5518638611441, 950.9479780913017, -935.2791149345967] accu = {} thrust, torque = PR.computeThrustAndTorque(teff, 419., PInf, center=(0,0,0), relativeShaft=0., accumulatorThrust=accu) ret = PR.exportAccumulatorPerRadius(accu, vars=['ThrustX','ThrustY','ThrustZ','TorqueX','TorqueY','TorqueZ']) C.convertPyTree2File(ret, 'Thrust.cgns')
Accumulator export
- Post.Rotor.exportAccumulatorPerPsi(accumulator, psi=0., vars=['F1', 'F2'])
Export a given psi of an accumulator (psi,rad) in a 1D zone. For distributed computations, the exported zone is identical on all processors.
- Parameters:
accumulator (dictionary) – (psi,rad) accumulator
psi (float) – angular angle to be extracted (in degree)
vars (list of strings) – the name of variables stored in accumulator
- Returns:
a single Zone with vars corresponding to psi
- Return type:
Zone
Example of use:
# - exportAccumulatorPerPsi (pyTree) - import Post.Rotor as PR import Converter.PyTree as C accu = {} for psi in range(0, 360, 10): for rad in range(0, 10): accu[(psi,rad)] = [psi+rad*0.1] z = PR.exportAccumulatorPerPsi(accu, psi=10., vars=['F']) C.convertPyTree2File(z, 'out.cgns')
- Post.Rotor.exportAccumulatorPerRadius(accumulator, rad=0., vars=['F1', 'F2'])
Export a given radius of an accumulator (psi,rad) in a 1D zone. For distributed computations, the exported zone is identical on all processors.
- Parameters:
accumulator (dictionary) – (psi,rad) accumulator
rad (float) – radius to be extracted
vars (list of strings) – the name of variables stored in accumulator
- Returns:
a single Zone with vars corresponding to rad
- Return type:
Zone
Example of use:
# - exportAccumulatorPerRadius (pyTree) - import Post.Rotor as PR import Converter.PyTree as C accu = {} for psi in range(0, 360, 10): for rad in range(0, 10): accu[(psi,rad)] = [psi+rad*0.1] z = PR.exportAccumulatorPerRadius(accu, rad=4, vars=['F']) C.convertPyTree2File(z, 'out.cgns')
- Post.Rotor.exportAccumulatorMap(accumulator, vars=['Fx', 'Fy', 'Fz'])
Export accumulator (psi,rad) to a 2D zone. For distributed computations, the exported zone is identical on all processors.
- Parameters:
accumulator (dictionary) – (psi,rad) accumulator
vars (list of strings) – the name of variables stored in accumulator
- Returns:
a single Zone with fields
- Return type:
Zone
Example of use:
# - exportAccumulatorMap (pyTree) - import Post.Rotor as PR import Converter.PyTree as C accu = {} for psi in range(0, 365, 10): for rad in range(0, 10): accu[(psi,rad)] = [psi+rad*0.1] z = PR.exportAccumulatorMap(accu, vars=['F']) C.convertPyTree2File(z, 'out.cgns')