Source code for dtOOPythonApp.builder.vec3dThreeD_skinAndSplit

#------------------------------------------------------------------------------
#  dtOO < design tool Object-Oriented >
#    
#    Copyright (C) 2024 A. Tismer.
#------------------------------------------------------------------------------
#License
#    This file is part of dtOO.
#
#    dtOO is distributed in the hope that it will be useful, but WITHOUT
#    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#    FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE.txt file in the
#    dtOO root directory for more details.
#
#    You should have received a copy of the License along with dtOO.
#
#------------------------------------------------------------------------------

from dtOOPythonApp.tools.dtBundleTools import dtBundleBuilder

from dtOOPythonSWIG import bSplineCurve_pointConstructOCC
from dtOOPythonSWIG import bSplineSurface_exchangeSurfaceConstructOCC 
from dtOOPythonSWIG import vectorDtPoint3 
from dtOOPythonSWIG import dtPoint3 
from dtOOPythonSWIG import vec3dCurveOneD 
from dtOOPythonSWIG import analyticCurve
from dtOOPythonSWIG import analyticFunction
from dtOOPythonSWIG import analyticSurface
from dtOOPythonSWIG import dtLinearAlgebra
from dtOOPythonSWIG import vectorHandlingConstAnalyticFunction
from dtOOPythonSWIG import vec3dTransVolThreeD_skinBSplineSurfaces
from dtOOPythonSWIG import vec3dSurfaceTwoD
from dtOOPythonSWIG import bSplineSurface_bSplineSurfaceSplitConstructOCC
from dtOOPythonSWIG import bSplineSurface_skinConstructOCC
from dtOOPythonSWIG import dtOCCBSplineCurve

from typing import List, Optional
import logging

[docs] class vec3dThreeD_skinAndSplit(dtBundleBuilder): """Create mesh blocks and meanplane curves from blade and surrounding surface. This class: - Splits blade and the mesh block surfaces at defined positions. - Skins mesh block volumes of the corresponding surfaces. - Creates a meanplane curves at the inlet and outlet. - Creates trailing edge mesh blocks. Attributes ---------- label_: str Label. aFOne_: vec3dSurfaceTwoD First BSpline surface. aFTwo_: vec3dSurfaceTwoD Second BSpline surface. splitDim_: int Dimension where surface is splitted before skinned. splits_: List[Tuple[float]] Positions for splitting. thickness_: float Thickness of the trailing edge mesh blocks. meanplaneFromBlocks_: bool Activates creation of meanplane curve. meanplaneExtOut_: float Extention of meanplane curve towards outlet. meanplaneExtIn_: float Extention of meanplane curve towards inlet. nMeanplaneBlocks_: int Number of block faces used for the meanplane. Examples -------- >>> from dtOOPythonSWIG import dtPoint3 >>> from dtOOPythonSWIG import bSplineCurve_pointConstructOCC >>> from dtOOPythonSWIG import bSplineSurface_skinConstructOCC >>> from dtOOPythonSWIG import vec3dSurfaceTwoD Create first analyticFunction: >>> aFOne = vec3dSurfaceTwoD( ... bSplineSurface_skinConstructOCC( ... bSplineCurve_pointConstructOCC( ... dtPoint3(0,0,0), dtPoint3(1,0,0) ... ).result(), ... bSplineCurve_pointConstructOCC( ... dtPoint3(0,1,0), dtPoint3(1,1,0) ... ).result() ... ).result() ... ) Create second analyticFunction: >>> aFTwo = vec3dSurfaceTwoD( ... bSplineSurface_skinConstructOCC( ... bSplineCurve_pointConstructOCC( ... dtPoint3(0,0,1), dtPoint3(1,0,1) ... ).result(), ... bSplineCurve_pointConstructOCC( ... dtPoint3(0,1,1), dtPoint3(1,1,1) ... ).result() ... ).result() ... ) Initialize builder: >>> builder = vec3dThreeD_skinAndSplit("unitCube", aFOne, aFTwo) Build volume: >>> builder.build() Check label of first analyticFunction: >>> builder.lVH_aF().labels()[0] 'unitCube' The main method of this class is :meth:`build`. The analytic functions of the blade surface ``aFOne_`` and the surrounding surface ``aFTwo_`` are split at the positions specified in ``splits_``. The input parameter ``splitDim_`` specifies the parameter direction in which the surfaces are split. A value of ``0`` corresponds to splitting along the u-parameter direction. The format of ``splits_`` is ``List[Tuple[float, float]]``. Each entry ``splits_[i]`` corresponds to one resulting mesh block. A mesh block is created by splitting the surfaces ``aFOne_`` and ``aFTwo_`` between the normalized minimum and maximum parameter values specified by ``splits_[i][0]`` and ``splits_[i][1]``. Depending on whether ``splitDim_`` specifies the u- or v-direction, the values in ``splits_`` are converted into the corresponding surface parameter values. The mesh block volumes are created by skinning the resulting surfaces. Two trailing edge mesh blocks can additionally be created with a thickness specified by ``teMeshBlockThickness_``. If this value is set to ``None``, no trailing edge mesh blocks are generated. Otherwise, the trailing edge mesh blocks are created by computing a tangential offset of the edges of the first and last mesh blocks surrounding the blade. The offset edges are computed using the method :meth:`teOffsetCurves_vec3dSurfaceTwoD`. This method returns the base curve and a list of points, derived from the base curve, from which the offset curve can be constructed. By skinning the base and offset curves, faces extending from the first and last trailing edge mesh blocks are generated. A second skinning operation is then used to create the trailing edge mesh block volumes. To maintain consistent parameter orientations between the trailing edge mesh blocks and the other mesh blocks, the skinning operation is performed in :meth:`createBlockFaces`. Meanplane curves are generated if the Boolean parameter ``meanplaneFromBlocks`` is set to ``True``. Similar to the trailing edge mesh block edges, the meanplane curves are computed as tangential offsets of the blade mesh blocks using :meth:`teOffsetCurves_vec3dSurfaceTwoD`. The first meanplane curve is offset from the first blade mesh block towards the outlet of the regular channel. The second meanplane curve is offset from the ``n``-th blade mesh block, specified by ``nMeanplaneBlocks_``, towards the inlet. ``nMeanplaneBlocks_`` defines the index of the mesh block from which the meanplane curve is generated, starting at zero. The extension lengths of the offsets for the two meanplane curves are specified by ``meanplaneExtOut_`` and ``meanplaneExtIn_``. The string value stored in ``label_`` is used to label the generated analytic functions. The analytic function objects of the blade mesh blocks, trailing edge mesh blocks, and meanplane curves are added to the container object of the main class using :meth:`appendAnalyticFunction`. """ def __init__( self, label: str, aFOne: analyticFunction, aFTwo: analyticFunction, splitDim: int = 0, splits: List[List[float]] = [[]], tEMeshBlockThickness: Optional[float] = None, meanplaneFromBlocks: bool = False, meanplaneExtOut: Optional[float] = 0.01, meanplaneExtIn: Optional[float] = 0.01, nMeanplaneBlocks: Optional[int] = 3 ) -> None: """Constructor. Parameters ---------- label: str Label. aFOne: analyticFunction First BSpline surface. aFTwo_: analyticFunction Second BSpline surface. splitDim: int Dimension where surface is splitted before it is skinned. splits: List[List[float]] Positions for splitting. tEMeshBlockThickness: Optional[float] = None thickness of the Trailing Edge Mesh Blocks, if not None meanplaneFromBlocks: bool = False activates creation of meanplane curve meanplaneExtOut: Optional[float] = 0.01, extention of meanplane curve towards outlet meanplaneExtIn: Optional[float] = 0.01, extention of meanplane curve towards inlet nMeanplaneBlocks: Optional[int] = 3 number of block faces used for the meanplane Returns ------- None """ logging.info( "Initializing %s ..." % (label) ) super(vec3dThreeD_skinAndSplit, self).__init__() self.label_ = label self.aFOne_ = vec3dSurfaceTwoD.MustDownCast( aFOne ) self.aFTwo_ = vec3dSurfaceTwoD.MustDownCast( aFTwo ) self.splitDim_ = splitDim self.splits_ = splits self.thickness_ = tEMeshBlockThickness self.meanplaneFromBlocks_ = meanplaneFromBlocks self.meanplaneExtOut_ = meanplaneExtOut self.meanplaneExtIn_ = meanplaneExtIn self.nMeanplaneBlocks_ = nMeanplaneBlocks if self.thickness_ != None: self.nMeanplaneBlocks_ = self.nMeanplaneBlocks_ - 1 # adjust splits to corresponding parameter space if splits != [[]]: for split in self.splits_: cc = 0 if self.splitDim_ == 0: split[0] = self.aFOne_.x_percent( split[0], 0.0 )[0] split[1] = self.aFOne_.x_percent( split[1], 0.0 )[0] elif self.splitDim_ == 1: split[0] = self.aFOne_.x_percent( 0.0, split[0] )[1] split[1] = self.aFOne_.x_percent( 0.0, split[1] )[1]
[docs] def build(self) -> None: """Build part. This method: - Splits the blade and surrounding mesh block surfaces at predefined positions. - Creates mesh block volumes by skinning the corresponding surfaces. - Generates meanplane curves at the inlet and outlet. - Creates trailing edge mesh blocks. Parameters ---------- None Returns ------- None If no split positions are defined (``splits_ == [[]]``), the two surfaces are skinned directly, resulting in a single continuous mesh block. If split positions are defined, the mesh blocks are created by iterating over the entries in ``splits_``. Within this loop, the following entities are generated: - Mesh block volumes around the blade. - Edge curves for the trailing edge mesh blocks. - Meanplane curves extending towards the inlet and outlet. All geometries are constructed as analytic functions. The loop iteration is tracked using the counter ``cc``. The following figure illustrates the workflow of the operations performed within this loop. .. _vec3d_activity0: .. figure:: bladeFigs/vec3dThreeD_skinAndSplit.png :width: 100% :align: center Workflow of the main loop in :meth:`vec3dThreeD_skinAndSplit`. **Iterate over Splits** :: for split in splits_ All the following operations are performed in the main loop. **Split the Surfaces and Skin the Volumes** For each entry in ``splits_``, the surface functions ``aFOne_`` and ``aFTwo_`` are split within the parameter range defined by ``split[0]`` and ``split[1]``. This operation is performed using the `dtOO` class `bSplineSurface_bSplineSurfaceSplitConstructOCC`. The resulting surfaces are stored in the variables ``bladeSurf`` and ``blockSurf`` as ``vec3dSurfaceTwoD`` objects. These surfaces are then skinned into a volume using the `dtOO` class `vec3dTransVolThreeD_skinBSplineSurfaces` and appended to the container. The following figure illustrates the blade and the surrounding blade mesh blocks. In the following documentation, the direction specified by ``splitDim_`` corresponds to the u-direction of the blade surface. .. _meshBlockMeth: .. figure:: bladeFigs/guideVane_meshBlocks.png :width: 50% :align: center Blade surface (grey) surrounded by mesh blocks. By skinning the blade surfaces with the surrounding surfaces, the resulting volume parameter directions are defined as follows: - u: direction along the blade surface - v: direction from hub to shroud - w: direction from the blade surface towards the surrounding surface The volumes surrounding the blade are labeled according to the following convention: :: label_ + "_" + str(cc + 1) With this convention, the first blade mesh block in the direction of ``splitDim_`` is assigned the suffix ``_1``. **Creation of Offset Curves** The generation of the trailing edge mesh block curves, as well as the creation of the meanplane curves, is performed using the method :meth:`teOffsetCurves_vec3dSurfaceTwoD`. The method takes a mesh block surface as input. The first input argument defines the normalized parametric position of the base curve on the surface. An integer argument specifies the parameter direction in which the base curve is extracted and offset. By providing a thickness value, the offset distance is defined. The method returns the base curve together with a ``vectorDtPoint3`` object containing the points of the offset curve. Several conditional checks are performed within the loop to ensure that the correct curves are generated. **Trailing-edge mesh block curves** The following condition applies: :: thickness_ != None Trailing-edge mesh blocks are generated only if ``thickness_ != None``. In this case, offset curves are computed for the surfaces ``bladeSurf`` and ``blockSurf`` of the first mesh block (``cc == 0``) and the last mesh block (``cc == len(splits_) - 1``). The following variable names are assigned to the geometry objects returned by :meth:`teOffsetCurves_vec3dSurfaceTwoD`: - ``bladeCurve0``: Base curve on the blade surface of the first blade mesh block. - ``bladeOffset0``: ``vectorDtPoint3`` object containing the offset points of ``bladeCurve0``. - ``blockCurve0``: Base curve on the block surface of the first blade mesh block. - ``blockOffset0``: ``vectorDtPoint3`` object containing the offset points of ``blockCurve0``. - ``bladeCurve1``: Base curve on the blade surface of the last blade mesh block. - ``bladeOffset1``: ``vectorDtPoint3`` object containing the offset points of ``bladeCurve1``. - ``blockCurve1``: Base curve on the block surface of the last blade mesh block. - ``blockOffset1``: ``vectorDtPoint3`` object containing the offset points of ``blockCurve1``. The following figure illustrates the resulting curves for the first mesh block surrounding the blade. The variable :math:`t_{TE}` corresponds to the parameter ``thickness_``. .. _meshBlockCurves: .. figure:: bladeFigs/tEMesBlock_Curves.png :width: 70% :align: center Trailing-edge mesh block curves of the first mesh block (``cc == 0``). **Meanplane curves** The following condition applies: :: meanplaneFromBlocks_ == True The creation of the meanplane curves differs between two main cases. **Meanplane extending towards the inlet** In the first case, the meanplane curves extending towards the inlet are generated. These curves are created during the iteration for which ``cc == nMeanplaneBlocks_`` applies. The curves are based on the third face (``face``) of the mesh block. The offset curve is constructed from the base curve located at 100 percent of the v-direction of this face. The offset length of the curve is specified by ``meanplaneExtIn_``, corresponding to :math:`E_{MP,in}` in :numref:`meanplaneCurves`. The returned geometry objects are assigned to the variables ``mPBlockCurve`` and ``mPBlockOffset``. The ``vectorDtPoint3`` object ``mPBlockOffset`` is converted into a curve and stored in ``mPBlockOffsetCurve``. The curves are labeled and appended to the container using the following naming convention: - ``mPBlockCurve``: ``label_ + "Curve_in0"`` - ``mPBlockOffsetCurve``: ``label_ + "Curve_in1"`` The following figure illustrates the creation of the meanplane curve geometries for the meanplanes extending towards the inlet and the outlet. In this example, the inlet meanplane is located at ``nMeanplaneBlocks_ = 3``. Trailing-edge mesh blocks are enabled. .. _meanplaneCurves: .. figure:: bladeFigs/meanplane_Curves.png :width: 100% :align: center Creation of the meanplane curves extending towards the inlet and the outlet. The block numbers correspond to the mesh block indices and the value of ``cc + 1`` within the loop. **Meanplane extending towards the outlet** The curves for the meanplane extending towards the outlet are created on the first blade mesh block, for which ``cc == 0`` applies. The creation procedure differs depending on whether trailing edge mesh blocks are generated. If no trailing edge mesh blocks are created (``thickness_ == None``), the curves are generated from the curve at 0 percent of the u-direction of ``blockSurf``. The offset length is specified by ``meanplaneExtOut_``, corresponding to :math:`E_{MP,out}` in :numref:`meanplaneCurves`. The generated curve objects are assigned to the variables ``mPBlockCurve`` and ``mPBlockOffset``. If trailing edge mesh blocks are generated, the offset length of the meanplane curve created from the first blade mesh block is ``meanplaneExtOut_ + thickness_`` In this case, the base curve returned by :meth:`teOffsetCurves_vec3dSurfaceTwoD` is not used directly as the meanplane curve. Instead, the base curve is reconstructed from the offset points of the first trailing edge mesh block, ``blockOffset0``. The resulting curve overwrites ``mPBlockCurve``. In both cases, the curve ``mPBlockOffsetCurve`` is generated from the ``vectorDtPoint3`` object ``mPBlockOffset``. The curves are appended to the container as ``vec3dCurveOneD`` objects using the following naming convention: - ``mPBlockCurve``: ``label_ + "Curve_out0"`` - ``mPBlockOffsetCurve``: ``label_ + "Curve_out1"`` The meanplane curves appended to the container in the selected example are shown in the following figure. .. _meanplaneCP: .. figure:: bladeFigs/meanplane_CurvesPushed.png :width: 90% :align: center Final meanplane curves generated in this method. The labels ``in0``, ``in1``, ``out0``, and ``out1`` correspond to the naming convention used for the curves in the implementation. After each iteration of the loop, the iterator is incremented (``cc = cc + 1``) **Trailing Edge Mesh Blocks** The trailing edge volumes are generated from the trailing edge curves. The following operations are performed only if ``thickness_ != None`` applies. **Offset Curves at Trailing Edge** From the ``vectorDtPoint3`` objects of the two trailing edge mesh blocks on the blade side, ``bladeOffset0`` and ``bladeOffset1``, the mean points ``meanPoints`` are computed. Using these points, a mean offset curve ``meanBladeOffsetCurve`` is generated, which defines the offset surface of the trailing edge. The ``vectorDtPoint3`` objects of the block offset curves are converted into the curves ``blockOffsetCurve_0`` and ``blockOffsetCurve_1``. **Trailing Edge Mesh Block Surfaces** The trailing edge mesh block surfaces extending from the blade and from the mesh block surfaces are generated using the method :meth:`createBlockFaces`. The method expects an input list with the following structure: .. code-block:: python blockEdges = Tuple[ Tuple[ analyticGeometry, analyticGeometry ], Tuple[ analyticGeometry, analyticGeometry ] ] The method returns a ``vectorHandlingConstAnalyticFunction`` object ``vh_aF`` containing analytic surface functions generated by skinning the curves within each second-level ``Tuple`` entry. The skinning directions are defined as follows: - ``vh_aF[0]``: from ``blockEdges[0][0]`` to ``blockEdges[0][1]`` - ``vh_aF[1]``: from ``blockEdges[1][0]`` to ``blockEdges[1][1]`` By applying the `dtOO` class `bSplineSurface_exchangeSurfaceConstructOCC` on the skinned surface in the method, the parameter directions of the surfaces are kept consistent with the blade and mesh block surfaces. **Trailing Edge Mesh Block Volumes** The returned vector handler is passed to the ``dtOO`` class ``vec3dTransVolThreeD_skinBSplineSurfaces`` to create the trailing edge mesh block volumes ``theRef``. The volume skinning direction is defined as follows: - ``theRef``: from ``vh_aF[0]`` to ``vh_aF[1]`` The following figure illustrates the skinning of the curves and surfaces. .. _meshBlockSkinning: .. figure:: bladeFigs/tEMesBlock_skinning.png :width: 80% :align: center Skinning of the first trailing edge mesh block. Surface skinning is shown on the left, and volume skinning on the right. The arrows indicate the skinning directions. By arranging the order of the curves in the input list passed to :meth:`createBlockFaces`, the parameter directions of the trailing edge mesh block volumes remain consistent with those of the blade mesh blocks. The generated volumes are appended to the analytic function container using the same naming convention as the blade mesh blocks. The first trailing edge mesh block is labeled with the index zero: ``label_ + "_0"`` The last trailing edge mesh block receives the label: ``label_ + "_" + str(len(splits_) + 1)`` The following figure shows the resulting mesh block volumes. .. _TEmeshBlockMeth: .. figure:: bladeFigs/guideVane_TEmeshBlocks.png :width: 50% :align: center Blade surface (grey) with blade mesh blocks and trailing edge mesh blocks. """ logging.info( "Building %s ..." % (self.label_) ) if self.splits_ == [[]]: # # if no split positions are defined, one volume is created # vh_aF = vectorHandlingConstAnalyticFunction() vh_aF.push_back( self.aFOne_ ) vh_aF.push_back( self.aFTwo_ ) theRef = vec3dTransVolThreeD_skinBSplineSurfaces( vh_aF ).result() theRef.setLabel( self.label_ ) self.appendAnalyticFunction( theRef ) else: # # splits are defined # cc = 0 # # iterate over the split positions # for split in self.splits_: logging.info("meshBlock nr : %d" % cc) logging.info( "Split between %f <--> %f in direction %d" % (split[0], split[1], self.splitDim_) ) vh_aF = vectorHandlingConstAnalyticFunction() # # split the blade surface # #vh_aF.push_back( bladeSurf = vec3dSurfaceTwoD( bSplineSurface_bSplineSurfaceSplitConstructOCC( self.aFOne_.constPtrDtSurface(), self.splitDim_, split[0], split[1] ).result() ) vh_aF.push_back((bladeSurf).clone()) # # split the surrounding surface # #vh_aF.push_back( blockSurf = vec3dSurfaceTwoD( bSplineSurface_bSplineSurfaceSplitConstructOCC( self.aFTwo_.constPtrDtSurface(), self.splitDim_, split[0], split[1] ).result() ) vh_aF.push_back((blockSurf).clone()) # # skin the split surfaces to create the mesh block volume # theRef = vec3dTransVolThreeD_skinBSplineSurfaces( vh_aF ).result() # trailing edge active if self.thickness_ != None: theRef.setLabel( self.label_+"_"+str(cc + 1) ) # trailing edge not active else: theRef.setLabel( self.label_+"_"+str(cc) ) self.appendAnalyticFunction( theRef ) # # generate trailing edge mesh block # only done, if thickness_ is defined # if self.thickness_ != None: # # te mesh blocks will be located downstream of the first and last mesh blocks # # first mesh block if cc == 0: logging.info("Extracting trailing edge and block curves from mesh block %d" % (cc+1)) # # needed curves: # curve on blade and block, # their offsets in the tangential direction of the blade and block surfaces # segPercent specifies the u direction where the trailing edge is located on the faces, # this is different for the first and last blocks because the u direction "wraps" # around the blade # offset curves for block and blade are calculated in two function calls # bladeCurve0, bladeOffset0 = self.teOffsetCurves_vec3dSurfaceTwoD( bladeSurf, 0, self.thickness_, 0 ) blockCurve0, blockOffset0 = self.teOffsetCurves_vec3dSurfaceTwoD( blockSurf, 0, self.thickness_, 0 ) # last mesh block if cc == (len(self.splits_)-1): logging.info("Extracting trailing edge and block curves from mesh block %d" % (cc+1)) bladeCurve1, bladeOffset1, = self.teOffsetCurves_vec3dSurfaceTwoD( bladeSurf, 1, self.thickness_, 0 ) blockCurve1, blockOffset1 = self.teOffsetCurves_vec3dSurfaceTwoD( blockSurf, 1, self.thickness_, 0 ) # # meanplane extention curves # if self.meanplaneFromBlocks_ == True: # # meanplane curves extending to the inlet # if cc == self.nMeanplaneBlocks_: # face 3 of the mesh block is the one normal to the blade face = vec3dSurfaceTwoD.DownCast( theRef.constPtrVec3dTwoD( 3 ) ) ## debug statement to plot analytical face #plotFace = vec3dSurfaceTwoD.DownCast( # theRef.constPtrVec3dTwoD( # 3 # ) # ) #plotFace.setLabel("TEST_"+self.label_+"_plotFace") #self.appendAnalyticFunction(plotFace) # calculate the tangentially offset curve based on the face mPBlockCurve, mPBlockOffset = self.teOffsetCurves_vec3dSurfaceTwoD( face, 1, (self.meanplaneExtIn_), 1 ) # create the curve from a vectorDtPoint3 and append AF mPBlockOffsetCurve = bSplineCurve_pointConstructOCC(mPBlockOffset,2).result() self.appendAnalyticFunction(vec3dCurveOneD( mPBlockOffsetCurve ) << self.label_ + "Curve_in1") self.appendAnalyticFunction(vec3dCurveOneD( mPBlockCurve ) << self.label_ + "Curve_in0") # # meanplane curves extending to the outlet # elif cc == 0: if self.thickness_ == None: # calculating offset curve mPBlockCurve, mPBlockOffset = self.teOffsetCurves_vec3dSurfaceTwoD( blockSurf, 0, (self.meanplaneExtOut_), 0 ) else: # the meanplane offset curve is calculated from the same blockSurf which is used # for the trailing edge mesh block # the offset distance is (self.thickness_+self.meanplaneExtOut_) mPBlockCurve, mPBlockOffset = self.teOffsetCurves_vec3dSurfaceTwoD( blockSurf, 0, (self.thickness_+self.meanplaneExtOut_), 0 ) # mPBlockCurve is overwritten with blockOfsset of the trailing edge mesh block mPBlockCurve = bSplineCurve_pointConstructOCC(blockOffset0,2).result() # create the curve from a vectorDtPoint3 and appending AF mPBlockOffsetCurve = bSplineCurve_pointConstructOCC(mPBlockOffset,2).result() self.appendAnalyticFunction(vec3dCurveOneD( mPBlockOffsetCurve ) << self.label_ + "Curve_out1") self.appendAnalyticFunction(vec3dCurveOneD( mPBlockCurve ) << self.label_ + "Curve_out0") else: pass cc = cc + 1 # # Create the trailing edge mesh block volumes # if self.thickness_ != None: # # calculate mean offset of the blade trailing edge. # trailing edge converges at u = 0 and u = 1 in one curve, # here two tangential directions are returned by the two calls # of teBlockCurves_vec3dSurfaceTwoD() (at the first and last meshBlocks) # from the two offsets a mean is calculated # meanPoints = vectorDtPoint3() for i in range(len(bladeOffset0)): meanPoints.append( dtPoint3( (bladeOffset0[i][0]+bladeOffset1[i][0])*0.5, (bladeOffset0[i][1]+bladeOffset1[i][1])*0.5, (bladeOffset0[i][2]+bladeOffset1[i][2])*0.5, ) ) # create the curve of the blade offset meanBladeOffsetCurve = bSplineCurve_pointConstructOCC(meanPoints,2).result() # create the curves of the block offsets blockOffsetCurve_1 = bSplineCurve_pointConstructOCC(blockOffset1,2).result() blockOffsetCurve_0 = bSplineCurve_pointConstructOCC(blockOffset0,2).result() logging.info("Creating trailing edge mesh blocks") # create the block faces by skinning the curves in the list # the structure of the list is important for the directions (see description in function) vh_aF = self.createBlockFaces( [[meanBladeOffsetCurve, bladeCurve0], [blockOffsetCurve_0, blockCurve0]] ) # generate the volume from the faces theRef = vec3dTransVolThreeD_skinBSplineSurfaces( vh_aF ).result() theRef.setLabel( self.label_+"_0" ) self.appendAnalyticFunction( theRef ) # do the same for the te mesh block at u = 1 vh_aF = self.createBlockFaces( [[bladeCurve0, meanBladeOffsetCurve], [blockCurve1, blockOffsetCurve_1] ] ) theRef = vec3dTransVolThreeD_skinBSplineSurfaces( vh_aF ).result() theRef.setLabel( self.label_+"_"+str(len(self.splits_)+1) ) self.appendAnalyticFunction( theRef ) return
# # Extracts the necessary curves and their offsets for the generation of the trailing edge meshBlocks # and the generation of the meanplane curves # segPercent is 0 for the first and 1 for the last mesh blocks #
[docs] def teOffsetCurves_vec3dSurfaceTwoD(self, surf, segPercent, blockThickness, splitDim): """Extract a curve on a face and calculate points, which are tangentially offset to the face. This method: - Extracts a curve from a surface at a constant parameter value. - Computes tangential offset points along the curve span. - Returns the extracted curve together with the offset points. Parameters ---------- surf : vec3dSurfaceTwoD Input surface. segPercent : float Normalized parameter position at which the curve is extracted from the surface. blockThickness : float Offset distance used for the tangential offset curve. splitDim : int Parameter direction in which the curve is extracted (u- or v-direction). Returns ------- curve : analyticGeometry Curve extracted from the surface at ``segPercent`` in the direction specified by ``splitDim``. offsetPoints : vectorDtPoint3 Container holding the points of the tangentially offset curve. The surface from which the curve is extracted is provided through the parameter ``surf``. The normalized parameter position ``segPercent`` defines where the curve is extracted. It can be either ``0`` or ``1``, corresponding to the minimum or maximum parameter boundary of the surface. The parameter ``splitDim`` specifies whether the extraction is performed in the u- or v-direction of the surface. The following convention is used: - u-direction: ``0`` - v-direction: ``1`` The parameter ``blockThickness`` defines the offset distance. The following figure illustrates the workflow of this method. .. _createOffset_activity0: .. figure:: bladeFigs/createOffsetCurves.png :width: 60% :align: center Workflow of method :meth:`teOffsetCurves_vec3dSurfaceTwoD`. **Set Direction** Depending on the value of ``segPercent``, the offset direction factor ``f`` is assigned either ``-1`` or ``1``. **Check splitDim** Depending on ``splitDim``, the base curve ``curve`` is extracted from ``surf`` at either a constant u-parameter or a constant v-parameter. The normalized position ``segPercent`` is assigned to either ``uu`` or ``vv`` as the constant parameter value. **Get Number of Control Points and Create Container** The extracted ``curve`` is converted into a B-spline curve using the ``dtOO`` class ``dtOCCBSplineCurve``. This allows the control point count of the curve to be queried and stored in ``n``. The output container ``offsetPoints`` of type ``vectorDtPoint3`` is then initialized. **Iterate over Control Points** The offset points are computed by iterating over the control point indices. Depending on ``splitDim``, tangent vectors in either the u-direction or the v-direction of the surface are evaluated at the surface coordinates defined by ``uu`` and ``vv``. One parameter value remains constant, while the second parameter value is computed from the normalized iterator expression ``i / (n - 1)``. The offset point is computed as the surface point evaluated at ``(uu, vv)`` plus the corresponding tangent vector multiplied by ``blockThickness`` and the direction factor ``f`` (see :numref:`meshBlockCurves`). Each computed point is appended to ``offsetPoints``. The method returns ``curve`` and ``offsetPoints``. """ # set direction f of the offset based on splitDim if segPercent == 0: f = -1 elif segPercent == 1: f = 1 # convert the surface to an analytic surface surf = analyticSurface(surf.constPtrDtSurface()) # # Depending on splitDim the operations are performed in different # surface directions # # surface directions: # splitDim = 0: # v-direction is the hub-to-shroud direction # u-direction is along the blade contour # splitDim = 1: # v-direction is the blade skin to block skin direction # u-direction is the hub to shroud direction # according to the split dimension which is set the curve is cut out # and segPercent set on uu or vv if splitDim == 0: # u-direction curve = analyticCurve.MustDownCast( surf.segmentConstUPercent(segPercent) ).ptrConstDtCurve() uu = segPercent elif splitDim == 1: # v-direction curve = analyticCurve.MustDownCast( surf.segmentConstVPercent(segPercent) ).ptrConstDtCurve() vv = segPercent # get number of control points of the curve bsc_curve = dtOCCBSplineCurve.MustDownCast(curve) n = bsc_curve.nControlPoints() # initialize point vectors for the offset curves offsetPoints = vectorDtPoint3() # iterate over control points for i in range(n): # calculate the percentual vv or uu position by normalizing the number of # controlpoints # calculate the tangential directions of the faces at the support points if splitDim == 0: vv = i/(n-1) # tangential direction of the blade at the trailing edge tangent = dtLinearAlgebra.normalize( surf.firstDerU(surf.u_percent(uu), surf.v_percent(vv)) ) elif splitDim == 1: uu = i/(n-1) # tangential direction of the face normal between blade and thickness faces tangent = dtLinearAlgebra.normalize( surf.firstDerV(surf.u_percent(uu), surf.v_percent(vv)) ) # appending the blade point offset in tangential direction # the offset will have the specified thickness, f sets the direction offsetPoints.append( surf.getPoint( surf.u_percent(uu), surf.v_percent(vv) ) + tangent * blockThickness*f ) ## Debug statement to plot tangents #tangentCurve = bSplineCurve_pointConstructOCC( # vectorDtPoint3() # << surf.getPoint(surf.u_percent(uu), surf.v_percent(vv)) # << surf.getPoint(surf.u_percent(uu), surf.v_percent(vv)) + tangent * blockThickness*f, # 1 #).result() #tang = (vec3dCurveOneD( tangentCurve ) << self.label_ + "Curve_te"+str(uu)+"_"+str(i)) #self.appendAnalyticFunction(tang) # return the curve on the surface and the vector with the offset points # the offset points and not the offset curves are returned, because a # mean offset has to be calculated for trailing edge at the blade return curve, offsetPoints
# # creating the faces for the trailing edge meshBlocks #
[docs] def createBlockFaces(self, curves): """Create trailing edge block faces by skinning edge curves. This method: - Iterates over the first-level curve list. - Skins the curve pairs defined in the second-level lists. - Returns the generated surfaces in a container. Parameters ---------- curves : Tuple[Tuple[analyticGeometry, analyticGeometry],Tuple[analyticGeometry, analyticGeometry]] Collection of curve pairs to be skinned with each other. Returns ------- vh_aF : vectorHandlingConstAnalyticFunction Container holding the analytic functions of the generated surfaces. The curves to be skinned are provided to the method in the following format: .. code-block:: python curves = Tuple[ Tuple[ analyticGeometry, analyticGeometry ], Tuple[ analyticGeometry, analyticGeometry ] ] The method initializes a ``vectorHandlingConstAnalyticFunction`` object named ``vh_aF``. The skinning operation is performed by iterating over the first-level ``Tuple`` using: .. code-block:: python for curves0 in curves: For each entry ``curves0``, the skinning operation is performed from ``curves0[0]`` to ``curves0[1]``. After skinning, the ``dtOO`` class ``bSplineSurface_exchangeSurfaceConstructOCC`` is applied in order to exchange the parameter directions of the resulting surface. This produces the following parameter directions on the surface: - u: direction from ``curves0[0]`` to ``curves0[1]`` - v: direction from hub to shroud The resulting surfaces are converted into ``vec3dSurfaceTwoD`` objects and appended to ``vh_aF``. Finally, the generated surfaces are returned through ``vh_aF``. """ vh_aF = vectorHandlingConstAnalyticFunction() for curves0 in curves: vh_aF.push_back( vec3dSurfaceTwoD( bSplineSurface_exchangeSurfaceConstructOCC( bSplineSurface_skinConstructOCC( curves0[0], curves0[1] ).result() ).result() ).clone() ) return vh_aF