API documentation

The documentation of the C++ code.

C++ core classes

Python pyDtOO classes

The documentation of the pyDtOO package.

class pyDtOO.dtClusteredSingletonState.dtClusteredSingletonState[source]

Manage database.

Connection to the database that holds at least fitness and objective values. Objectives (inputs, parameters, degrees of freedom, …) are the values that are changed during optimization to improve the fitness (result value, …) of the problem. Every individual has an ID and a state as integer and str, respectively. This class also stores optional (additional) data for each individual. A data value is in the simplest case a scalar value as integer or float. But it can be also a float array or a dict.

The class stores all data in the directory DATADIR. Fitness value, objective value, ID and state are stored in the files fitness.*, objective.*, id.* and state.*, respectively. If additional data is used the files are named according to the ADDDATA array. The data in DATADIR are divided in chunks of 1000 lines per file.

PREFIX

Prefix for the state label. The default is ‘A1’

Type:

str

CASE

Label of the simulation case. The default is ‘’

Type:

str

LOCKDIR

Directory of the lock directory. The default is dtGod().LockPath()

Type:

dtDirectory

PIDDIR

Directory of the PIDDIR. The default is ‘./runPid’

Type:

str

DATADIR

Directory to store the data. The default is ‘./runData’

Type:

str

NPROC

Number of processes. The default is 1

Type:

int

SIMSH

Name of the simulation script. The default is ‘’

Type:

str

ADDDATA

Array of additional (optional) data. The default is []

Type:

List[str]

ADDDATADEF

Default values for additional data. The default is []

Type:

List[ Union[ List[float], int, dict] ]

PROB

Problem class. The default is None

Type:

Any

id_

ID of individual

Type:

float

state_

State of individual

Type:

str

Examples

Add additional values for each individual

>>> dtClusteredSingletonState.ADDDATA = [
...   'dict',
...   'float',
...   'int',
...   'np-float-arr',
...   'np-int-arr',
...   'str',
... ]
>>> dtClusteredSingletonState.ADDDATADEF = [
...   {'key' : 0.0},
...   1.0,
...   2,
...   np.full(3, 5.0),
...   np.full(3, -5),
...   'test',
... ]

Create first individual

>>> dtClusteredSingletonState(
...   defObj=[0.0,0.0,],
...   defFit=[0.0,0.0,]
... )
<dtClusteredSingletonState.dtClusteredSingletonState object at ...>

Access individual by id

>>> cSS = dtClusteredSingletonState(1)

Check if data exactly matches the ADDDATADEF list

>>> for i in dtClusteredSingletonState.ADDDATA:
...   print(
...     cSS(i)
...     ==
...     dtClusteredSingletonState.ADDDATADEF[
...       dtClusteredSingletonState.ADDDATA.index(i)
...     ]
...   )
True
True
True
[ True  True  True]
[ True  True  True]
True

Write new data

>>> cSS = dtClusteredSingletonState(1)
>>> cSS.update('fitness', 1.0)
>>> cSS.update('objective', [1.0,2.0])
>>> cSS.update('dict', {'float' : 1.0, 'str' : 'myStr'})

Read default data from individual

>>> cSS.id()
1
>>> cSS.state()
'A1_1'
>>> cSS.objective()
array([1., 2.])
>>> cSS.fitness()
array([1.])

Read additional data as str

>>> cSS.read('float')
'1.e+00'
>>> cSS.read('dict')
'{"float": 1.0, "str": "myStr"}'

Read additional data with specified type

>>> cSS.readFloatArray('float')
array([1.])
>>> cSS.readFloat('float')
1.0
>>> cSS.readArray('np-int-arr', int)
array([-5, -5, -5])
>>> cSS.read('np-int-arr')
'-5 -5 -5'
>>> cSS.readDict('dict')
{'float': 1.0, 'str': 'myStr'}

Check data again; some checks have to fail, because the data was updated

>>> for i in dtClusteredSingletonState.ADDDATA:
...   print("=> %s" % i)
...   print(cSS(i))
...   print(
...     cSS(i)
...     ==
...     dtClusteredSingletonState.ADDDATADEF[
...       dtClusteredSingletonState.ADDDATA.index(i)
...     ]
...   )
=> dict
{'float': 1.0, 'str': 'myStr'}
False
=> float
1.0
True
=> int
2
True
=> np-float-arr
[5. 5. 5.]
[ True  True  True]
=> np-int-arr
[-5 -5 -5]
[ True  True  True]
=> str
test
True

Check type of elements in the arrays

Note

Numpy versions smaller than 2.0.0 return int and float instead of np.int64 and float64, respectively.

>>> cSS('np-int-arr')[0]
np.int64(-5)
>>> cSS('np-float-arr')[0]
np.float64(5.0)

Stored scalar integer values should be returned as int for both versions

>>> cSS('int')
2
static clear(remove: bool = False) None

Clear database.

Parameters:

remove (bool) – Flag to clean directory, too.

Return type:

None

static currentMaxId() int[source]

Get current maximum ID stored in database.

Raises:

ValueError – If file index < 0.

Returns:

Maximum ID.

Return type:

int

Examples

>>> dtClusteredSingletonState.clear(True)
>>> a = dtClusteredSingletonState()
>>> b = dtClusteredSingletonState()
>>> dtClusteredSingletonState.currentMaxId()
2
static fileIndex(id: int) int[source]

Get file index of individual’s data.

Parameters:

id (int) – ID of individual.

Returns:

File index.

Return type:

int

fitness() numpy.ndarray[source]

Read fitness for current individual.

Returns:

Fitness.

Return type:

numpy.ndarray

static formatToWrite(value: float | int | dict | numpy.array) str[source]

Converts value to str.

Parameters:

value (Union[float, int, dict, np.array]) – Value to convert.

Returns:

Converted value.

Return type:

str

Examples

>>> dtClusteredSingletonState.formatToWrite(1.0)
'1.e+00'
>>> dtClusteredSingletonState.formatToWrite(1)
'1'
>>> dtClusteredSingletonState.formatToWrite('word')
'word'
>>> dtClusteredSingletonState.formatToWrite(
...   {'str' : 'word', 'float' : 1.0}
... )
'{"str": "word", "float": 1.0}'
>>> dtClusteredSingletonState.formatToWrite(np.full(2,1.0))
'1.e+00 1.e+00'
>>> try:
...   dtClusteredSingletonState.formatToWrite(['a', 'b',])
... except ValueError as e:
...   print(e)
Unknown datatype.
>>> class testclass:
...   pass
>>> try:
...   dtClusteredSingletonState.formatToWrite(testclass)
... except ValueError as e:
...   print(e)
Unknown datatype.
static fullAddRead(addFileV: List, addDtypeV: List = []) List[numpy.ndarray]

Read additional data of all individuals.

Parameters:
  • addFileV (np.ndarray) – List of additional data to read.

  • addDtypeV (np.ndarray) – List of additional dtype.

Return type:

List

Examples

>>> dtClusteredSingletonState.clear(True)
>>> dtClusteredSingletonState.ADDDATA = ['float', 'dict']
>>> dtClusteredSingletonState.ADDDATADEF = [1.0, {'test' : 2.0},]
>>> a = dtClusteredSingletonState()
>>> b = dtClusteredSingletonState()
>>> A = dtClusteredSingletonState.fullAddRead(['float', 'dict'])
>>> A['float']
array([1., 1.])
>>> A['dict']
array([{'test': 2.0}, {'test': 2.0}], dtype=object)
>>> A['dict'][0]['test']
2.0
static fullAddReadDict(addFile: str, maxFileIndex: int) numpy.ndarray[source]

Read additional dicts of all individuals.

Parameters:
  • addFile (str) – File name of additional dict.

  • maxFileIndex (int) – Maximum file index.

Returns:

Additional dicts for all individuals.

Return type:

np.ndarray

static fullRead() Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Read IDs, objective values and fitness values of all individuals.

Parameters:
  • addFile (Union[ None, List[str] ], optional) – List of additional files to read. The default is None.

  • addDtype (Union[float, int, dict], optional) – dtype of additional values. The default is float.

Returns:

  • Union[ – Tuple[np.ndarray, np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]

  • ] – Tuple of IDs, objective and fitness values. If addFile is not None, then the return tuple is extended by additional array.

Examples

>>> dtClusteredSingletonState.clear(True)
>>> a = dtClusteredSingletonState(defObj=[1.0, 1.0],defFit=[1.5,1.5])
>>> b = dtClusteredSingletonState(defObj=[2.0, 2.0],defFit=[2.5, 2.5])
>>> I,O,F = dtClusteredSingletonState.fullRead()
>>> for i,o,f in zip(I,O,F):
...   i
...   o
...   f
np.int64(1)
array([1., 1.])
array([1.5, 1.5])
np.int64(2)
array([2., 2.])
array([2.5, 2.5])
hasDirectory() bool[source]

Check if individual’s case directory exist

Return type:

bool

id() int[source]

Get individual’s ID.

Raises:

ValueError – If ID < 0.

Returns:

ID.

Return type:

int

objective() numpy.ndarray[source]

Read objective for current individual.

Returns:

Objective.

Return type:

numpy.ndarray

static oneD(arr: numpy.ndarray) numpy.ndarray[source]

Convert array’s shape to one-dimensional numpy.ndarray.

Parameters:

arr (numpy.ndarray) – Array.

Returns:

Converted array.

Return type:

numpy.ndarray

read(fName: str) str[source]

Read data of fName for current individual.

Parameters:

fName (str) – Label of data.

Returns:

Value.

Return type:

str

readArray(fName: str, dtype: float | int | str) numpy.ndarray[source]

Read data of fName for current individual and return as array.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

numpy.ndarray

readDict(fName: str) dict[source]

Read data of fName for current individual and return as dict.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

dict

readFloat(fName: str) float[source]

Read data of fName for current individual and return as float.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

float

readFloatArray(fName: str) numpy.ndarray[source]

Read data of fName for current individual and return as float array.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

numpy.ndarray

static readIdFromObjective(obj: numpy.ndarray) int[source]

Returns ID of individual with objective obj.

Parameters:

obj (numpy.ndarray) – Objective.

Returns:

ID.

Return type:

int

Warns:

Warning if difference in objective values >0.1.

Examples

>>> dtClusteredSingletonState.clear(True)
>>> a = dtClusteredSingletonState(defObj=[1.0, 1.0],defFit=[2.0])
>>> a.objective()
array([1., 1.])
>>> b = dtClusteredSingletonState(defObj=[2.0, 2.0],defFit=[2.0])
>>> b.objective()
array([2., 2.])
>>> dtClusteredSingletonState.readIdFromObjective(np.array(a.objective()))
1
>>> dtClusteredSingletonState.readIdFromObjective(np.array(b.objective()))
2
readInt(fName: str) int[source]

Read data of fName for current individual and return as integer.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

int

readIntArray(fName: str) numpy.ndarray[source]

Read data of fName for current individual and return as int array.

Parameters:

fName (str) – Label of data.

Returns:

Converted value.

Return type:

numpy.ndarray

state() str[source]

Get individual’s state.

Raises:

ValueError – If ID < 0.

Returns:

State.

Return type:

str

static twoD(arr: numpy.ndarray) numpy.ndarray[source]

Convert array’s shape to two-dimensional numpy.ndarray.

Parameters:

arr (numpy.ndarray) – Array.

Returns:

Converted array.

Return type:

numpy.ndarray

update(fileName: str, value: float | int | dict | numpy.array) None

Write data of fName for current individual.

Parameters:
  • fileName (str) – Label of data.

  • value (Union[float, int, dict, np.array]) – Value.

Return type:

None

Python dtOOPythonApp classes

The documentation of the dtOOPythonApp package.

The following classes are used in the demonstration case of the radial turbine.

class dtOOPythonApp.builder.analyticGeometry_piecewiseMeridionalRotContour.analyticGeometry_piecewiseMeridionalRotContour(label: str, hubCurves: List[dtOOPythonSWIG.analyticGeometry], shroudCurves: List[dtOOPythonSWIG.analyticGeometry], interface_hub: List[Tuple[int, float]] = [], interface_shroud: List[Tuple[int, float]] = [], interface_curvature: List[Tuple[float, float, int]] = [], rotVector: dtOOPythonSWIG.dtVector3 = dtOOPythonSWIG.dtVector3)[source]

Create regular channels and special hub and shroud curves.

This class:

  • Creates interface curves in the meridional contour.

  • Splits the hub and shroud curves at the intersection points with the interfaces.

  • Creates regular channels between the interfaces.

  • Creates lists of boundary curves for a layered flow channel downstream of the last interface.

  • Returns the volumes of the regular channels and the boundary curve lists.

label_

Label.

Type:

str

rotVector_

Rotation vector.

Type:

dtVector3

normalAxis_

Vector normal to the 2D domain.

Type:

dtVector3

interfaces_

List of interface curves.

Type:

List[analyticGeometry]

hubSplits_

List of splits on hub curves. Each entry represents:

  • hubSplits_[i][n]: n-th split on the i-th hub curve.

  • hubSplits_[i][n][0]: Relative position where the split is applied.

  • hubSplits_[i][n][1]: ID of the interface creating the split.

Type:

List[List[Tuple[float, int]]]

shroudSplits_

List of splits on shroud curves. Each entry represents:

  • shroudSplits_[i][n]: n-th split on the i-th shroud curve.

  • shroudSplits_[i][n][0]: Relative position where the split is applied.

  • shroudSplits_[i][n][1]: ID of the interface creating the split.

Type:

List[List[Tuple[float, int]]]

hubCurves_

Split hub curves.

Type:

List[analyticGeometry]

shroudCurves_

Split shroud curves.

Type:

List[analyticGeometry]

inOutCurves_

List of inlet and outlet curves of the complete domain.

Type:

List[analyticGeometry]

regChannels_

List of channel surfaces.

Type:

List[analyticGeometry]

speHub_

List of hub curves of the layered region.

Type:

List[analyticGeometry]

speShroud_

List of shroud curves of the layered region.

Type:

List[analyticGeometry]

inOutLayerReg_

List of inlet and outlet curves of the layered region.

Type:

List[analyticGeometry]

Return type:

None

Examples

>>> import dtOOPythonSWIG as dtOO

Define list of hub curves:

>>> hubCurves = [
...      dtOO.analyticCurve(
...        dtOO.bSplineCurve_pointConstructOCC(
...          dtOO.vectorDtPoint3()
...            << dtOO.dtPoint3(+0.50, +0.00, 1.00)
...            << dtOO.dtPoint3(+0.00, +0.00, 0.50),
...            1
...        ).result()
...      ),
...      dtOO.analyticCurve(
...        dtOO.bSplineCurve_pointConstructOCC(
...          dtOO.vectorDtPoint3()
...            << dtOO.dtPoint3(+0.00, +0.00, 0.50)
...            << dtOO.dtPoint3(+0.00, +0.00, 0.00),
...            1
...        ).result()
...      )
...    ]

Define list of shroud curves:

>>> shroudCurves = [
...      dtOO.analyticCurve(
...        dtOO.bSplineCurve_pointConstructOCC(
...          dtOO.vectorDtPoint3()
...            << dtOO.dtPoint3(+1.00, +0.00, 1.00)
...            << dtOO.dtPoint3(+1.00, +0.00, 0.00),
...            1
...        ).result()
...      )
...    ]

Initialize builder:

>>> builder = analyticGeometry_piecewiseMeridionalRotContour(
...  label = "channel",
...  hubCurves = hubCurves,
...  shroudCurves = shroudCurves,
...  interface_hub = [[0, 0.7]],
...  interface_shroud = [[0, 0.3]],
...  interface_curvature = [[0.5, 0.2, -1]],
... )

Build volume:

>>> builder.build()

Return the six sided domain and check type:

>>> builder.getRegChannel(0, 12).virtualClassName()
'partRotatingMap2dTo3d'

The main method of this class is the constructor. The inputs are the hub and shroud curves (hubCurves and shroudCurves), as well as the lists defining the interface parameters (interface_hub, interface_shroud and interface_curvature).

The normal axis normalAxis_ of the flow channel’s cross-section is returned by the method calculateNormalAxis(). It is used to determine the direction of the interface curves.

The interface curves are created with the method createInterface(). The method returns the curves in the list interfaces_. With the method detectIntersect(), it is checked whether the interface curves intersect the hub or shroud curves; if so, an exception is raised.

Special inlet and outlet curves are created as straight lines at the inlet and outlet of the meridional contour. The list inOutCurves_ contains these curves.

The hub and shroud curves are split at the intersection points corresponding to the start or end points of the interface curves using createSplits(). The lists hubSplits_ and shroudSplits_ track which curves are split by which interface and at which percentual position along their span. The method createSplits() returns the split curves in the lists hubCurves_ and shroudCurves_.

The newly split curves are managed with cti (curve-to-interface) lists. These lists are initially returned by createSplits() and track which interface curve is associated with which hub and shroud curve. The lists are modified by propagate_interface_ids_next() to indicate which hub and shroud curves belong to which regular channel.

The regular channels are created between two neighbouring interfaces in the flow direction of the channel contour. The first regular channel is created between the inlet and the first interface. The following regular channels are created between neighbouring interfaces.

The surfaces of the regular channels are created from the interface curves and the hub and shroud curves extending between them. These curves are identified with the method findChannelCurves(). The surfaces are created in the constructor of this class and stored in the list regChannels_.

The hub and shroud curves that are not part of the regular channels are stored as special curves in the lists speHub_ and speShroud_. These curves later form the basis of a layered flow channel. The inlet and outlet curves for this layered flow channel are stored in the list inOutLayerReg_ and are formed by the last interface curve and the outlet of the flow domain.

The build() method is used for debugging the class. If the debug option is enabled in the class constructor, the created geometries are returned to ParaView, where they can be plotted with the names assigned in the build() method and the label label_.

The method getRegChannel() returns the volume of a specified regular channel. The volume is created by rotating the face of a regular channel around the rotational axis rotVector_ with a specified angle.

The getter method getLayerRegionCurves() returns the lists speHub_, speShroud_, and inOutLayerReg_.

__init__(label: str, hubCurves: List[dtOOPythonSWIG.analyticGeometry], shroudCurves: List[dtOOPythonSWIG.analyticGeometry], interface_hub: List[Tuple[int, float]] = [], interface_shroud: List[Tuple[int, float]] = [], interface_curvature: List[Tuple[float, float, int]] = [], rotVector: dtOOPythonSWIG.dtVector3 = dtOOPythonSWIG.dtVector3) None[source]

Constructor.

This method:

  • Creates the interface curves.

  • Splits the hub and shroud curves at the interfaces.

  • Creates inlet and outlet lines.

  • Creates regular channel surfaces.

  • Creates lists with curves for layered region.

Parameters:
  • label (str) – Label.

  • hubCurves (List[analyticGeometry]) – List of hub curves.

  • shroudCurves (List[analyticGeometry]) – List of shroud curves.

  • interface_hub (List[Tuple[int, float]]) –

    Positions of the interfaces on the hub curves. Each entry represents:

    • interface_hub[i]: Interface number

    • interface_hub[i][0]: Curve number where the interface is located

    • interface_hub[i][1]: Percentage along the curve (0 to 1)

  • interface_shroud (List[Tuple[int, float]]) –

    Positions of the interfaces on the shroud curves. Each entry represents:

    • interface_shroud[i]: Interface number

    • interface_shroud[i][0]: Curve number where the interface is located

    • interface_shroud[i][1]: Percentage along the curve (0 to 1)

  • interface_curvature (List[Tuple[float, float, int]]) –

    Curvature of the interface curve from hub to shroud. Each entry represents:

    • interface_curvature[i]: Interface number

    • interface_curvature[i][0]: Curvature offset point [%] from hub to shroud

    • interface_curvature[i][1]: Curvature as a percentage of the connection line length

    • interface_curvature[i][2]: Curvature direction

  • rotVector (dtVector3) – Rotation vector.

Return type:

None

The constructor of this class is used to partition the hub and shroud curves into regular channel segments and special hub and shroud curves.

Input Curves

The input lists named hubCurves and shroudCurves define the two-dimensional cross-section of the channel. The curves must be created such that their direction is consistent with the downstream direction of the flow machine. Furthermore, the ordering of the curves in the lists must also follow the downstream direction of the machine.

Here downstream direction refers to the flow direction of a machine in turbine mode. The counter direction is referred to as the upstream direction.

The following figure shows the hub and shroud curves:

_images/hsCurve_noInterface.png

Fig. 38 Hub and shroud curves of the meridional channel. Numbering corresponds to the indices in the hubCurves and shroudCurves lists.

Interface Curves

The method calculateNormalAxis() is used to compute the normal axis of the cross-section, stored in normalAxis_.

By passing hubCurves, shroudCurves, interface_hub, interface_shroud, and interface_curvature, together with the computed normal axis, to createInterface(), the interface curves are created. The method returns a list of interface curves, which is stored in interfaces_. The index of each interface in this list also serves as its interface ID.

Splitting of Hub and Shroud Curves

The hub and shroud curves are split at their intersection points with the interface curves. For this purpose, the lists hubSplits_ and shroudSplits_ are created, where each entry is initialized as an empty list. The number of entries corresponds to the number of hub and shroud curves.

By iterating over the interfaces, each split position together with the corresponding interface ID is stored as a tuple in the respective curve entry at the location where the split occurs.

The resulting lists hubSplits_ and shroudSplits_ are of type List[List[Tuple[float, int]]].

The values in this nested list represent:

  • hubSplits_[i][n]: n-th split on the i-th hub curve.

  • hubSplits_[i][n][0]: Percentual position along the curve span where the split occurs.

  • hubSplits_[i][n][1]: ID of the interface that creates the split.

The splits for the hub and the shroud curves are applied using the method createSplits(). The hub and shroud curves are split independently by calling the method once for the hub curves and once for the shroud curves.

The method takes the split data lists hubSplits_ or shroudSplits_ and the corresponding curve lists hubCurves or shroudCurves as input. Additionally, a label is passed to the method.

The method returns the split hub and shroud curve lists as well as cti (curve-to-interface) lists. If no split is performed on a curve, or if the split position lies at 0 or 100 percent of the curve span, no new split is created and the original curve is appended as a copy.

The resulting curve lists are stored as hubCurves_ and shroudCurves_.

The following figure shows the meridional contour with interface, inlet, and outlet curves. The curves hubCurves[1] and shroudCurves[2] (see Fig. 38) are split into two curves each by the interface curve interfaces_[1]. The resulting curves are stored as hubCurves_[1] and hubCurves_[2] as well as shroudCurves_[2] and shroudCurves_[3] in the instantiated curve lists.

_images/hsCurves.png

Fig. 39 Meridional channel with interface (red) and inlet and outlet curves (orange). Numbering of the hub and shroud curves (black) corresponds to the indices in the hubCurves_ and shroudCurves_ lists.

Curve-to-Interface Lists

The cti lists (curve-to-interface) track which hub and shroud curves are upstream of which interface. The lists contain one entry per hub or shroud curve. If a curve endpoint lies on an interface curve, the corresponding entry stores the interface ID; otherwise the entry is None.

For the example shown in Fig. 39, the resulting cti lists are:

  • hub_cti = [0, 1, None, None, None]

  • shroud_cti = [0, None, 1, None, None]

The cti lists are passed to the method propagate_interface_ids_next(), where the entries are matched to the regular channels to which the curves belong. The returned values overwrite the original cti lists.

The resulting shroud_cti list is:

  • shroud_cti = [0, 1, 1, None, None]

Inlet and Outlet Curves of the Meridional Contour

In inOutCurves_, the inlet and outlet curves of the meridional contour are stored. The inlet curve is created as a straight line between the start points of the first curves in the hub and shroud curve lists. The outlet curve is created in the same way, using the end points of the last hub and shroud curves.

Regular Channels

The number of regular channels corresponds to the number of defined interfaces. The first regular channel is created between the inlet curve and the first interface. Subsequent regular channels are created between adjacent interfaces in flow direction.

The regular channel surfaces are created by iterating over the number of interfaces. For each regular channel, the hub and shroud curves belonging to that channel are determined using the method findChannelCurves(). This method is called once for the hub curves and once for the shroud curves. The inputs are the instantiated curve lists hubCurves_ or shroudCurves_, the cti lists hub_cti or shroud_cti, and the ID of the regular channel, as well as a label. The curves belonging to a channel are identified by matching the channel ID against the cti list entries and are combined into a single curve.

The upstream interface, or in the case of the first regular channel the inlet of the meridional channel, forms the inlet boundary of each regular channel. The downstream interface forms the outlet boundary.

The surfaces are constructed using a bSplineSurface_bSplineCurveFillConstructOCC object from the inlet, outlet, and the combined hub and shroud curves of the regular channel.

To ensure consistent orientation of the resulting surfaces and volumes, the curves are passed to the construct object in the following order:

  1. combined hub curve

  2. inlet of the regular channel

  3. combined shroud curve

  4. outlet of the regular channel

This results in a regular channel volume whose uvw-directions after rotation are:

  • u : circumferential direction

  • v : meridional direction

  • w : hub-to-shroud direction

The regular channel surfaces are stored in the list regChannels_. The following figure shows the surfaces of the regular channels.

_images/regChannels.png

Fig. 40 Regular channels (yellow, green) between the interfaces. Special hub and shroud curves are not part of the regular channels.

Layer Region Curves

The curves downstream of the last interface are not part of the regular channels. Their value in the propagated cti list is None. By iterating over the cti list and checking for None values, the special hub and shroud curves are identified and stored in the lists speHub_ and speShroud_. These special curves are used for the layered flow channel.

The inlet of the layered flow channel is formed by the last interface curve, and the outlet is formed by the outlet of the meridional channel. These curves are stored in the list inOutLayerReg_.

The following figure shows the special curves and the inlet and outlet of the layered flow channel contour.

_images/speCurvesClass.png

Fig. 41 Special hub and shroud curves with numbering according to their positions in the speHub_ and speShroud_ lists. The inlet and outlet curves of the layered flow channel are stored in inOutLayerReg_.

createInterface(hubCurves, shroudCurves, interface_hub, interface_shroud, curve, normalAxis)[source]

Create interface curve between hub and shroud.

This method:

  • Creates a linear mean line between the hub and shroud point of the interface.

  • Creates the interface curve based on the mean line.

  • Checks if the interface curve intersects with any hub or shroud curves.

Parameters:
  • hubCurves (List[analyticGeometry]) – List of hub curves.

  • shroudCurves (List[analyticGeometry]) – List of shroud curves.

  • interface_hub (List[Tuple[int, float]]) –

    Positions of the interfaces on the hub curves. Each entry represents:

    • interface_hub[i]: Interface number.

    • interface_hub[i][0]: Curve number where the interface is located.

    • interface_hub[i][1]: Percentage along the curve (0 to 1).

  • interface_shroud (List[Tuple[int, float]]) –

    Positions of the interfaces on the shroud curves. Each entry represents:

    • interface_shroud[i]: Interface number.

    • interface_shroud[i][0]: Curve number where the interface is located.

    • interface_shroud[i][1]: Percentage along the curve (0 to 1).

  • curve (List[Tuple[float, float, int]]) –

    Curvature of the interface curve from hub to shroud. Each entry represents:

    • curve[i]: Interface number.

    • curve[i][0]: Curvature offset point [%] from hub to shroud.

    • curve[i][1]: Curvature as a percentage of the connection line length.

    • curve[i][2]: Curvature direction.

  • normalAxis (dtVector3) – Normal axis

Returns:

interfaces – List of interface curves.

Return type:

List[analyticGeometry]

The interfaces are created between points on the hub and shroud curves (pointHub and pointShroud), which are specified using the input lists interface_hub and interface_shroud.

The lists are unpacked as follows:

  • interface_hub[i]: Start point of the i-th interface curve on the hub.

  • interface_shroud[i]: End point of the i-th interface curve on the shroud.

The lower-level list entries define the hub and shroud curves and the procentual positions along those curves at which the interface start and end points are located:

  • interface_hub[i][0]: Index of the hub curve on which the start point lies.

  • interface_hub[i][1]: Percentage along the hub curve where the start point is located.

By iterating over the interface lists, the interface curves are constructed.

Between the hub and shroud points, a straight line MP_linear is created, spanning from the hub point to the shroud point. Based on this line and the input list curve, the curvature of the interface is defined.

The list curve is structured as follows. The highest level corresponds to the interface index:

  • curve[i]: Parameters of the i-th interface.

The lower level defines the curvature properties of the interface:

  • curve[i][0]: Control point offset as a percentage of the length of MP_linear.

  • curve[i][1]: Control point base position as a percentage along MP_linear.

  • curve[i][2]: Direction of the control point offset.

The following figure illustrates the creation of the interface curves, with emphasis on the curvature definition of the second interface curve.

_images/interfaceCalcMethod.png

Fig. 42 Creation of the interface curves (red) between the hub and shroud curves (black), using the linear mean-plane curve MP_linear (green).

Table 4 gives the mapping between the mathematical symbols in Fig. 42 and the naming of the variables in this method.

Table 4 Mapping between mathematical symbols and variable names.

Symbol

Label

\(a\)

curve[i][0]

\(b\)

curve[i][1]

\(c\)

curve[i][2]

\(MP,lin\)

MP_linear

The curvature is defined using a single control point pointCurve (\(\mathbf{P_{C}}\)). This control point is computed by applying an offset from a point (\(\mathbf{P_{MP}}\)) located along the span of MP_linear. The position along the span is given as a percentage in curve[i][1] (\(b\)).

The offset is applied in the normal direction of MP_linear (\(\mathbf{v}\)) within the two-dimensional plane of the meridional contour. This direction is computed as the normalized cross product of the tangential direction of MP_linear (\(\mathbf{t}\)) and the normal axis of the meridional contour normalAxis (\(\mathbf{n_{global}}\)):

\[\mathbf{v} = \frac{\mathbf{t} \times \mathbf{n_{global}}}{\|\mathbf{t} \times \mathbf{n_{global}}\|}\]

The offset magnitude is defined as a percentage of the length of MP_linear (\(l_{MP,lin}\)), specified by curve[i][0] (\(a\)). The direction of curvature is controlled by curve[i][2] (\(c\)), which takes the values 1 or -1.

The control point pointCurve is then defined as:

\[\mathbf{P_{C}} = \mathbf{P_{MP}} + \mathbf{v} \cdot l_{MP,lin} \cdot a \cdot c\]

The interface curve is created from the start and end points on the hub and shroud (pointHub and pointShroud) together with the control point pointCurve. It is stored in the list interfaces, along with the other interface curves created within this loop.

The method detectIntersect() is used to detect possible intersections between the interface curves and the hub and shroud curves. The inputs to this method are the list of interface curves and a list of curves against which intersections are checked.

The returned lists intersects_hub and intersects_shroud contain information about which interface curves intersect which hub or shroud curves. If no intersections are detected, the lists are empty.

If intersections are detected, the corresponding intersecting curves are reported via logging statements.

The list of interface curves is returned by the method.

detectIntersect(interfaces, curves)[source]

Detect intersections between curves from two lists.

This method:

  • Iterates over the interface list.

  • Cuts each interface curve at 5% and 95% of its span.

  • Iterates over the second curve list.

  • Checks for intersections between the cut interface and each curve.

  • Creates and returns a list managing intersecting curve pairs.

Parameters:
  • interfaces (List[analyticGeometry]) – List of interface curves.

  • curves (List[analyticGeometry]) – List of curves to be checked for intersections.

Returns:

intersectList

List of detected intersections. Each entry represents:

  • intersectList[i]: curve pair entry

  • intersectList[i][0]: ID of interface curve

  • intersectList[i][1]: ID of curve from second list

  • intersectList[i][2]: True if intersection occurs

Return type:

List[Tuple[int, int, bool]]

By comparing curves in the two input lists, possible intersections are detected and stored in intersectList.

The method iterates over all interface curves in interfaces. Each interface is trimmed at 5% and 95% of its parameter range to avoid detecting the intersections at the interface endpoints where they connect to the hub or shroud curves. The resulting trimmed curve is stored as cut_interface.

For each cut_interface, all curves in the input list curves are checked for intersections. This is performed using the object gmf of type dtOO.gslMinFloatAttr. The call gmf.perform() returns True if an intersection is detected, which is stored in the variable interbool.

If interbool is True, the IDs of the interface and curve, together with the boolean flag, are appended to the intersection list.

The resulting intersectList is unpacked as follows:

  • intersectList[i]: detected intersection between two curves

  • intersectList[i][0]: ID of interface curve

  • intersectList[i][1]: ID of curve in second list

  • intersectList[i][2]: True if intersection is detected

The intersection list is returned by the method.

propagate_interface_ids_next(curve_to_interface, lab)[source]

Map curves to IDs of regular channels.

This method:

  • Takes the cti (curve-to-interface) lists created in createSplits()

  • Propagates interface IDs to upstream curve segments

  • Returns the propagated lists

Parameters:
  • curve_to_interface (List) – Curve-to-interface list containing interface IDs or None.

  • lab (str) – Label.

Returns:

result – Propagated curve-to-regular-channel list.

Return type:

List

This method modifies the cti (curve_to_interface) list. The list is initially returned by createSplits(). In its original form, it only marks curves that are directly upstream of an interface.

In this method, the interface IDs are propagated upstream so that all curve segments belonging to the same regular channel carry the same interface ID. This allows the curves to be directly associated with their corresponding regular channels.

As an example, createSplits() may return a cti list such as:

  • shroud_cti = [0, None, 1, None, None, None, None]

After propagation, this method modifies it to:

  • shroud_cti = [0, 1, 1, None, None, None, None]

In this case, entries 1 and 2 can now be identified as belonging to regular channel 1.

The method takes the curve_to_interface list and propagates the integer interface IDs to all upstream curves that currently contain None values.

All interface IDs present in curve_to_interface are first collected in the list iface_indices. If no interface IDs are found, an empty result list is returned.

The index of the first interface is stored in first_idx. Subsequent interface IDs are propagated forward to all curve entries between consecutive interface indices. This process is controlled using the variables start and end within a loop.

The resulting list contains, for each curve, either the corresponding regular channel ID or None. The updated list is returned at the end of the method.

findChannelCurves(curves, cti, ii, lab)[source]

Find and combine curves belonging to a regular channel.

This method:

  • Iterates over a list of curves.

  • Identifies curves that belong to the regular channel.

  • Combines the curves.

  • Returns the combined curve in a list.

Parameters:
  • curves (List[analyticGeometry]) – List of curves.

  • cti (List) –

    Curve-to-interface list mapping split curves to regular channels. Entries can be:

    • int: ID of the regular channel the curve belongs to

    • None: curve belongs to a layered region

  • ii (int) – ID of the regular channel.

  • lab (str) – Label.

Returns:

curve_list – List containing the combined curve.

Return type:

List[analyticGeometry]

The ID of the regular channel is passed to the method via the input ii. The list curves contains the curves that form either the hub or the shroud of the channel surface.

The list cti contains one entry for each curve in curves. The entries are the IDs of the regular channels the corresponding curves belong to (or None if the curve is not part of a regular channel).

By iterating over curves and checking whether the corresponding entry in cti matches ii, the relevant curves are identified.

The first curve belonging to the regular channel is assigned to regCurve. In subsequent iterations, all additional matching curves are merged into regCurve using the dtOO class bSplineCurve_curveConnectConstructOCC.

The combined curve of the regular channel is returned in curve_list.

static createSplits(splits, inCurves, lab)[source]

Split the curves at the defined positions.

This method:

  • Iterates over split definitions.

  • Performs splits on the specified curves at given positions.

  • Creates a curve-to-interface list.

Parameters:
  • splits (List[List[Tuple[float, int]]]) –

    List defining splits for each curve. Each entry represents:

    • splits[i][n] : n-th split on the i-th curve

    • splits[i][n][0] : parameter (percentage) where the split is applied

    • splits[i][n][1] : ID of the interface that defines the split

  • inCurves (List[analyticGeometry]) – Input curves to be split.

  • lab (str) – Label.

Returns:

  • outCurves (List[analyticGeometry]) – List of split curves.

  • curve_to_interface (List) – List containing the interface ID for each curve endpoint. Entries can be:

    • int: ID of the interface located at the curve endpoint

    • None: no interface is located at the curve endpoint

The curves that are split by this method are provided in the input list inCurves. The nested list splits defines the split positions on these curves.

The first-level index splits[i] corresponds to the i-th curve in inCurves. The second-level index splits[i][n] corresponds to the n-th split applied to that curve.

Each split is defined by a tuple containing:

  • the position along the curve (as a percentage of its parameter range),

  • the ID of the interface that defines the split.

The full structure of splits is therefore List[List[Tuple[float, int]]], where splits[i][n][0] defines the split position and splits[i][n][1] defines the corresponding interface ID.

The following figure shows the activity diagram of this method.

_images/createSplits.png

Fig. 43 Activity diagram of the createSplits() method.

At the start of the method, empty lists are created for the split curves outCurves and the curve-to-interface list curve_to_interface. The latter is used to track which interface each curve in outCurves belongs to.

The method generates the split curves by iterating over the first level of the list splits. The curve processed in each iteration is referred to as curve.

If splits occur on this curve, the lists split_pos and interface_ids are created. These lists aggregate the values from the second level of splits in order to support multiple splits per curve.

split_pos contains the percentual split positions along the curve span. The values 0.0 and 1.0 are prepended or appended respectively to ensure the full curve range is covered.

interface_ids stores the IDs of the interfaces associated with each split.

The curve splitting is performed by iterating over split_pos. During this loop, three cases can occur:

  1. Boundary split at 0 or 100 percent

    This case applies when a split position is exactly 0.0 or 1.0. In this situation, split_pos contains two adjacent identical values (i.e. split_pos[n] == split_pos[n+1]).

    The corresponding interface ID is appended to curve_to_interface, but no geometric split is performed.

  2. Single split at full curve length

    This case occurs when the only effective split is at 1.0, resulting in neighbouring entries 0.0 and 1.0 in split_pos.

    The full curve is appended to outCurves without modification. The corresponding entry in curve_to_interface is handled in the subsequent iteration, where case 1 applies.

  3. Regular split case

    If neither Case 1 nor Case 2 applies, a standard split is performed.

    The curve is split using the dtOO class trimmedCurve_uBounds, creating a new curve segment between two neighbouring values in split_pos.

    The interface ID is appended to curve_to_interface if the resulting segment lies upstream of the interface; otherwise, None is appended for downstream segments.

If no split is defined for a curve, it is appended unchanged to outCurves, and None is appended to curve_to_interface.

Finally, the lists outCurves and curve_to_interface are returned.

static calculateNormalAxis(curves)[source]

Calculate the bounding box and normal axis of curves in one plane.

This method:

  • Creates a bounding box around the curves.

  • Calculates the normal axis on the bounding box.

  • Calculates the center of the bounding box.

  • Returns normal axis, center and bounding box.

Parameters:

curves (List[analyticGeometry]) – List of curves.

Returns:

  • normalAxis (dtVector3) – Normal axis of the bounding box.

  • bbCenter (dtPoint3) – Center point of the bounding box.

  • bb (pairDtPoint3) – Bounding box points.

build() None[source]

Plot the instantiated geometries in paraview if debug is enabeled.

Parameters:

None

Return type:

None

This method appends the geometries to the dtBundle objects for debugging.

getRegChannel(pos: int, nSlices: int) dtOOPythonSWIG.analyticGeometry[source]

Return a regular channel.

This method:

  • Returns a rotated segment of a regular channel surface.

Parameters:
  • pos (int) – Channel Id.

  • nSlices (int) – Number of periodic slices.

Returns:

Regular channel volume.

Return type:

analyticGeometry

This getter method is used to return a regular channel specified by the channel ID with pos. The rotation angle can be set with nSlices which determines how many partitions the flow domain will have.

If the number of slices is set to one, a whole 360 degree volume of the flow channel is returned. It is created with the dtOO class rotatingMap2dT03d.

If a number greater than one is handed to the method, the class partRotatingMap2dTo3d is used, where the angle is calculated as \(360°/n_{Slices}\).

The following figure shows the regular channel volumes resulting from the rotation of the regular channel faces.

_images/regChannels3d.png

Fig. 44 Regular channel volumes created by rotating the first (yellow) and second (green) regular channel faces.

getLayerRegionCurves() Tuple[List[dtOOPythonSWIG.analyticGeometry]][source]

Returns the bounding curves for the layered region.

Parameters:

None

Returns:

  • speHub_ (List[analyticGeometry]) – Hub curves of the layered region

  • speShroud_ (List[analyticGeometry]) – Shroud curves of the layered region

  • inOutLayerReg_ (List[analyticGeometry]) – inlet and outlet curves of the layered region

Returns the bounding curves of the layered region shown in Fig. 41.

class dtOOPythonApp.builder.vec3dThreeD_skinAndSplit.vec3dThreeD_skinAndSplit(label: str, aFOne: dtOOPythonSWIG.analyticFunction, aFTwo: dtOOPythonSWIG.analyticFunction, splitDim: int = 0, splits: List[List[float]] = [[]], tEMeshBlockThickness: float | None = None, meanplaneFromBlocks: bool = False, meanplaneExtOut: float | None = 0.01, meanplaneExtIn: float | None = 0.01, nMeanplaneBlocks: int | None = 3)[source]

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.

label_

Label.

Type:

str

aFOne_

First BSpline surface.

Type:

vec3dSurfaceTwoD

aFTwo_

Second BSpline surface.

Type:

vec3dSurfaceTwoD

splitDim_

Dimension where surface is splitted before skinned.

Type:

int

splits_

Positions for splitting.

Type:

List[Tuple[float]]

thickness_

Thickness of the trailing edge mesh blocks.

Type:

float

meanplaneFromBlocks_

Activates creation of meanplane curve.

Type:

bool

meanplaneExtOut_

Extention of meanplane curve towards outlet.

Type:

float

meanplaneExtIn_

Extention of meanplane curve towards inlet.

Type:

float

nMeanplaneBlocks_

Number of block faces used for the meanplane.

Type:

int

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 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 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 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 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 appendAnalyticFunction().

build() None[source]

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

Return type:

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.

_images/vec3dThreeD_skinAndSplit.png

Fig. 45 Workflow of the main loop in 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.

_images/guideVane_meshBlocks.png

Fig. 46 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 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 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 \(t_{TE}\) corresponds to the parameter thickness_.

_images/tEMesBlock_Curves.png

Fig. 47 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 \(E_{MP,in}\) in Fig. 48.

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.

_images/meanplane_Curves.png

Fig. 48 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 \(E_{MP,out}\) in Fig. 48.

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 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.

_images/meanplane_CurvesPushed.png

Fig. 49 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 createBlockFaces(). The method expects an input list with the following structure:

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.

_images/tEMesBlock_skinning.png

Fig. 50 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 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.

_images/guideVane_TEmeshBlocks.png

Fig. 51 Blade surface (grey) with blade mesh blocks and trailing edge mesh blocks.

teOffsetCurves_vec3dSurfaceTwoD(surf, segPercent, blockThickness, splitDim)[source]

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.

_images/createOffsetCurves.png

Fig. 52 Workflow of method 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 Fig. 47).

Each computed point is appended to offsetPoints.

The method returns curve and offsetPoints.

createBlockFaces(curves)[source]

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 – Container holding the analytic functions of the generated surfaces.

Return type:

vectorHandlingConstAnalyticFunction

The curves to be skinned are provided to the method in the following format:

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:

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.

class dtOOPythonApp.builder.analyticSurface_inOutFeMeanplane.analyticSurface_inOutFeMeanplane(prefix: str, label: str, channel: dtOOPythonSWIG.analyticGeometry, curves: dtOOPythonSWIG.labeledVectorHandlingAnalyticGeometry)[source]

Create the meanplane faces connecting to the interfaces of the regular channel.

This class:

  • Gets the offset meanplane curves from aG_.

  • Creates curves on the hub and shroud extending from the offset curves to the respective interfaces along the hub and shroud contours.

  • Creates curves on the interfaces connecting the hub and shroud curves.

  • Creates meanplane faces extending to the inlet and outlet from the generated curves.

prefix_

Prefix of label

Type:

str

label_

Label.

Type:

str

channel_

Channel.

Type:

map3dTo3d

aG_

Mesh block curves.

Type:

labeledVectorHandlingAnalyticGeometry

Return type:

None

Examples

>>> import dtOOPythonSWIG as dtOO

Create three dimensional channel domain.

>>> c0 = dtOO.bSplineCurve_pointConstructOCC(
...       dtOO.vectorDtPoint3()
...         << dtOO.dtPoint3(+1.00, +0.00, 0.50)
...         << dtOO.dtPoint3(+0.50, +0.00, 0.50),
...         1
...     ).result()
>>> c1 = dtOO.bSplineCurve_pointConstructOCC(
...       dtOO.vectorDtPoint3()
...         << dtOO.dtPoint3(+0.50, +0.00, 0.50)
...         << dtOO.dtPoint3(+0.30, +0.00, 0.25)
...         << dtOO.dtPoint3(+0.50, +0.00, 0.00),
...         2
...     ).result()
>>> c2 = dtOO.bSplineCurve_pointConstructOCC(
...       dtOO.vectorDtPoint3()
...         << dtOO.dtPoint3(+0.50, +0.00, 0.00)
...         << dtOO.dtPoint3(+1.00, +0.00, 0.00),
...         1
...     ).result()
>>> c3 = dtOO.bSplineCurve_pointConstructOCC(
...       dtOO.vectorDtPoint3()
...         << dtOO.dtPoint3(+1.00, +0.00, 0.00)
...         << dtOO.dtPoint3(+1.00, +0.00, 0.50),
...         1
...     ).result()
>>> channel2d = dtOO.analyticSurface(
...         dtOO.bSplineSurface_bSplineCurveFillConstructOCC(
...             c0, c1, c2, c3
...         ).result()
...     )
>>> channel = dtOO.rotatingMap2dTo3d(
...             dtOO.dtVector3(0,0,1),
...             channel2d,
...         )

Create the mesh block curves.

>>> c_in1 = dtOO.bSplineCurve_pointConstructOCC(
...           dtOO.vectorDtPoint3()
...             << dtOO.dtPoint3(+0.90, +0.20, 0.00)
...             << dtOO.dtPoint3(+0.90, +0.20, 0.50),
...             1
...         ).result()
>>> c_out1 = dtOO.bSplineCurve_pointConstructOCC(
...           dtOO.vectorDtPoint3()
...             << dtOO.dtPoint3(+0.60, +0.05, 0.00)
...             << dtOO.dtPoint3(+0.65, -0.05, 0.50),
...             1
...         ).result()

Push the mesh block curves into a vector handler.

>>> meshBlockCurves = dtOO.labeledVectorHandlingAnalyticGeometry()
>>> label = "test"
>>> meshBlockCurves.push_back(
...     dtOO.analyticCurve( c_in1 ) << "xyz_"+label+"_meshBlockCurve_in1"
... )
>>> meshBlockCurves.push_back(
...     dtOO.analyticCurve( c_out1 ) << "xyz_"+label+"_meshBlockCurve_out1"
... )

Create the meanplane faces between the interfaces and the mesh block curves.

>>> from dtOOPythonApp.builder import analyticSurface_inOutFeMeanplane
>>> feMeanplane = analyticSurface_inOutFeMeanplane(
...     prefix = "xyz",
...     label = label,
...     channel = channel,
...     curves = meshBlockCurves
... )
>>> feMeanplane.build()

Check the label of the last generated geometry.

>>> feMeanplane.lVH_aG().labels()[-1]
'xyz_test_fe_meanplane_out1'

The main method of this class is build(), where all operations of this class are performed.

The meanplane faces are created as objects of the dtOO class trans4SidedFace. They extend between the interfaces and the corresponding offset mesh block curves, which are created in the class vec3dThreeD_skinAndSplit.

The channel is converted to the type map3dTo3d and instantiated as channel_. It has the following parametric directions:

  • u : circumferential direction

  • v : meridional direction

  • w : hub-to-shroud direction

The interfaces represent the inlet and outlet of the channel domain. The inlet is located at 0% and the outlet at 100% of the v-coordinate of the channel. The hub is located at 0% and the shroud at 100% of the w-coordinate.

The string values of prefix_ and label_ are used to manage the names of the geometry objects in this class.

The offset meanplane curves are passed to the class through curves. This container, of type labeledVectorHandlingAnalyticGeometry, is instantiated as aG_. The curves extend from the hub to the shroud of the channel and follow the naming convention below:

  • Meanplane curve offset toward the inlet: prefix_+"_"+label_+"_meshBlockCurve_in1"

  • Meanplane curve offset toward the outlet: prefix_+"_"+label_+"_meshBlockCurve_out1"

The offset meanplane curves are shown in the following figure.

_images/inOutFEMeanplane_offsetCurves.png

Fig. 53 Offset meanplane curves (blue). Labels correspond to the established naming convention.

The class trans4SidedFace requires a closed loop of four bounding curves with consistent directions. The following curves are used for the interfaces:

  • Edge extending between the offset meanplane curve and the interface on the hub

  • Offset meanplane curve

  • Edge extending between the meanplane curve and the interface on the shroud

  • Edge extending between the hub and shroud edges on the interface

The curves have the following locations, directions, and names:

Table 5 Boundary curves of the trans4SidedFace

Location

From -> To

Name in build()

hub

interface -> meanplane curve

hsCurve_u0_<in/out>

meanplane curve

hub -> shroud

see above

shroud

meanplane curve -> interface

hsCurve_u1_<in/out>

interface

shroud -> hub

interfCurve_<in/out>

By passing the curves to the constructor of trans4SidedFace in the order established in Table 5, the resulting parameter directions are defined as follows:

  • u : direction of the hub curve

  • v : direction of the meanplane curve

The following figure shows the trans4SidedFace objects and their bounding curves.

_images/inOutFEMeanplane_trans4SidedFace.png

Fig. 54 Boundary curves (blue) and resulting trans4SidedFace (yellow). Arrows correspond to the curve directions, and labels correspond to the locations listed in Table 5.

The created geometries are returned to the analytic geometry container of the calling class.

build() None[source]

Build part.

This method:

  • Gets the offset meanplane curves from aG_.

  • Creates curves on the hub and shroud extending from the offset curves to the respective interfaces along the hub and shroud contours.

  • Creates curves on the interfaces connecting the hub and shroud curves.

  • Creates meanplane faces from the generated curves.

Parameters:

None

Return type:

None

A meanplane face is created at the inlet and outlet interfaces in a loop that iterates over mpCurveList. This list has the format List[Tuple[str, int]]. Two entries are defined in the list:

  • mpCurveList[0] : inlet data

  • mpCurveList[1] : outlet data

The tuple entries encode an identifier string mpCurveList[oc][0] and the normalized parameter coordinate mpCurveList[oc][1] of the interface.

The following diagram shows the activities performed in this method.

_images/analyticSurface_inOutFEMeanplane.png

Fig. 55 Activities during the creation of the meanplane face.

Iterate over Inlet and Outlet

The offset meanplane curve of the current interface is allocated to offC. The v-parameter of the channel interface is allocated to vChannel. A point container interfPoints is initialized as a vectorDtPoint3 object.

Iterate over Hub and Shroud Positions

The bounding curves extending along the hub and shroud are created in a loop over the parameter coordinates uu in [1, 0].

Create Points on the current Position

The hub and shroud curves are created from the points pCurve_uvw and pChannel_uvw. pCurve_uvw is the point on offC at the current value uu. It is reparameterized in the parametric space of the channel channel_.

The point pChannel_uvw is created with the same u-coordinate as pCurve_uvw, while the v- and w-coordinates correspond to the coordinates of the current interface on the channel’s hub or shroud position.

The following figure shows the points created in the iterations over the two loops.

_images/inOutFEMeanplane_points.png

Fig. 56 Points which are created (blue). The labeled points pCurve_uvw and pChannel_uvw correspond to the points created at the outlet (oc == 1) on the hub contour (uu == 0).

The point pChannel_uvw is appended to interfPoints in each iteration. Through the iteration over uu in [1, 0], the locations of the points in this container are as follows:

  • interfPoints[0] : shroud

  • interfPoints[1] : hub

Create Hub or Shroud Curve

From the points pCurve_uvw and pChannel_uvw, the hub or shroud curve hsCurve is created. Depending on whether the current iteration creates the hub or the shroud curve (uu == 0 or uu == 1), the direction of the curve is reversed. This results in the hub and shroud curve directions specified in Table 5. The curves are reparameterized in xyz-coordinates and pushed into aG_ with the following naming convention:

"hsCurve_"+"u"+str(uu)+"_"+str(mpCurveList[oc][0])

Check if the Interface Curve Extends over u = 100% of the Channel

The bounding curve on the interface is created from the points in interfPoints on the hub and shroud walls. To enable the extension of the interface meanplane surface across 0% of the channel u-coordinate, a check is implemented that detects jumps in the u-coordinates u1 and u2 of interfPoints[0] and interfPoints[1].

If the normalized u-parameter range of these two points in the channel is greater than 50% (abs(u1-u2) > 0.5), the larger of the two values is subtracted by one. This shifts the value into the negative parameter range. The shifted parameter is reassigned to interfPoints.

Create the Interface Curve

The interface curve interfCurve is created from the points in interfPoints and mapped into channel_ as interfCurveInChannel. Due to the definition of interfPoints, the resulting curve extends from the shroud to the hub walls of the channel. It is pushed into aG_ with the following naming convention:

"interfCurve_"+str(mpCurveList[oc][0])

Create the Meanplane Face

The meanplane faces are constructed as trans4SidedFace objects (see Fig. 54) using the curve sequence established in Table 5. The bounding curves are retrieved from aG_ by their names.

The face is returned to the geometry container of the calling class with the following name:

prefix_+"_"+label_+"_fe_meanplane_"+mpCurveList[oc][0]+str(1)
class dtOOPythonApp.builder.multipleBoundedVolume_gridChannel.multipleBoundedVolume_gridChannel(label: str, channel: dtOOPythonSWIG.analyticGeometry, meanplanes: List[dtOOPythonSWIG.analyticGeometry], couplings: List[dtOOPythonSWIG.analyticGeometry], nBlades: int, nInOutSurfSuction: int = 2, rotVector: dtOOPythonSWIG.dtVector3 = dtOOPythonSWIG.dtVector3, orientation: int = 1)[source]

Create the grid channel as a multiple bounded volume.

This class:

  • Creates multiple bounded surfaces on the hub and shroud.

  • Creates bounding faces from the meanplane and coupling faces.

  • Creates a multiple bounded volume of the grid channel.

label_

Label.

Type:

str

channel_

360° rotated channel domain

Type:

analyticGeometry

meanplanes_

List of meanplane faces

Type:

List[analyticGeometry]

couplings_

List of coupling faces

Type:

List[analyticGeometry]

nBlades_

Number of blades

Type:

int

nInOutSurf_

Number of meanplane faces extending from the mesh blocks to the inlet and outlet each

Type:

int

rotVector_

Rotation vector of the grid channel.

Type:

dtVector3

orientation_

Orientation of the blade in the channel.

  • 1 : Blade is oriented in u-direction of channel

  • -1 : Blade is oriented in negative u-direction of the channel

Type:

int

boundSurf_

Container for bounding surfaces.

Type:

labeledVectorHandlingAnalyticGeometry

gridChannel_

Volume of the grid channel.

Type:

analyticGeometry

Examples

>>> import dtOOPythonSWIG as dtOO

Build channel geometry

>>> channel = dtOO.rotatingMap2dTo3d(
...     dtOO.dtVector3(0,0,1),
...     dtOO.analyticSurface(
...         dtOO.bSplineSurface_bSplineCurveFillConstructOCC(
...             dtOO.bSplineCurve_pointConstructOCC(
...                 dtOO.vectorDtPoint3()
...                   << dtOO.dtPoint3(+1.00, +0.00, 0.50)
...                   << dtOO.dtPoint3(+0.50, +0.00, 0.50),
...                 1
...             ).result(),
...         dtOO.bSplineCurve_pointConstructOCC(
...              dtOO.vectorDtPoint3()
...                << dtOO.dtPoint3(+0.50, +0.00, 0.50)
...                << dtOO.dtPoint3(+0.50, +0.00, 0.00),
...                1
...            ).result(),
...         dtOO.bSplineCurve_pointConstructOCC(
...              dtOO.vectorDtPoint3()
...                << dtOO.dtPoint3(+0.50, +0.00, 0.00)
...                << dtOO.dtPoint3(+1.00, +0.00, 0.00),
...                1
...            ).result(),
...         dtOO.bSplineCurve_pointConstructOCC(
...                   dtOO.vectorDtPoint3()
...                     << dtOO.dtPoint3(+1.00, +0.00, 0.00)
...                     << dtOO.dtPoint3(+1.00, +0.00, 0.50),
...                     1
...             ).result(),
...         ).result()
...     )
... )

Define meanplane curves

>>> c_mp0 = dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(+0.50, +0.00, 0.50)
...       << dtOO.dtPoint3(+0.50, +0.00, 0.00),
...     1
... ).result()
>>> c_mp1 = dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(+0.55, +0.10, 0.50)
...       << dtOO.dtPoint3(+0.60, +0.10, 0.00),
...     1
... ).result()
>>> c_mp2 = dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(+0.90, +0.10, 0.50)
...       << dtOO.dtPoint3(+0.95, +0.10, 0.00),
...     1
... ).result()
>>> c_mp3 = dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(+1.00, +0.00, 0.50)
...       << dtOO.dtPoint3(+1.00, +0.00, 0.00),
...     1
... ).result()

Define coupling curve

>>> c_coup = dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(+0.85, +0.15, 0.50)
...       << dtOO.dtPoint3(+0.85, +0.25, 0.00),
...     1
... ).result()

Create meanplane faces in the channel from the curves

>>> mp0 = dtOO.analyticSurface(
...         dtOO.bSplineSurface_exchangeSurfaceConstructOCC(
...             dtOO.bSplineSurface_skinConstructOCC(
...                 c_mp1, c_mp0
...             ).result()
...         ).result()
...     )
>>> mp1 = dtOO.analyticSurface(
...         dtOO.bSplineSurface_exchangeSurfaceConstructOCC(
...             dtOO.bSplineSurface_skinConstructOCC(
...                 c_mp1, c_mp2
...             ).result()
...         ).result()
...     )
>>> mp2 = dtOO.analyticSurface(
...         dtOO.bSplineSurface_exchangeSurfaceConstructOCC(
...             dtOO.bSplineSurface_skinConstructOCC(
...                 c_mp2, c_mp3
...             ).result()
...         ).result()
...     )

Create coupling faces from meanplane curves and coupling curve

>>> coup0 = dtOO.analyticSurface(
...             dtOO.bSplineSurface_skinConstructOCC(
...                     c_mp2, c_coup
...                 ).result()
...         )
>>> coup1 = dtOO.analyticSurface(
...             dtOO.bSplineSurface_skinConstructOCC(
...                 c_coup, c_mp1
...             ).result()
...     )

Make a list containing the meanplane and coupling faces

>>> meanplaneFaces = [
...        dtOO.map2dTo3d.MustDownCast(mp0),
...        dtOO.map2dTo3d.MustDownCast(mp1),
...        dtOO.map2dTo3d.MustDownCast(mp2),
...    ]
>>> couplingFaces = [
...         dtOO.map2dTo3d.MustDownCast(coup0),
...         dtOO.map2dTo3d.MustDownCast(coup1),
...     ]

Create the grid channel

>>> from dtOOPythonApp.builder import multipleBoundedVolume_gridChannel
>>> gridChannel = multipleBoundedVolume_gridChannel(
...     label = "test",
...     channel = channel,
...     meanplanes = meanplaneFaces,
...     couplings = couplingFaces,
...     nBlades = 12,
...     nInOutSurfSuction = 1
... )
>>> gridChannel.build()

Return the multiple bounded volume and a list with the bounding faces

>>> gc, gcFaces = gridChannel.getGridChannel()

Check the class of the returned volume

>>> gc.virtualClassName()
'multipleBoundedVolume'

The main method of this class is build().

The grid channel is built as a multiple bounded volume. It forms the part of the bladed channel mesh that is not occupied by the mesh blocks. The construction of the multiple bounded volume requires a set of bounding surfaces.

The bounding surfaces boundSurfs_ are based on the meanplane and coupling faces provided to the class through the lists meanplanes_ and couplings_. The following figure shows the surfaces in meanplanes_ and couplings_.

_images/gidChannel_meanplanesAndCouplings.png

Fig. 57 Meanplane faces (yellow and green) and coupling faces (cyan) provided to this class. The blade (grey) is shown for reference.

The grid channel is formed on the blade side from the coupling faces of the mesh blocks (cyan) and the FE-Meanplane faces (Fig. 57 yellow).

The bounding faces on the opposing side of the grid channel are formed through a rotational translation of the faces in meanplanes_ (Fig. 57 yellow and green). These rotated faces form the periodic pressure faces of the bladed channel.

The inlet and outlet faces (Fig. 58 red) of the grid channel are created from the rotation of the interface curves of the FE-Meanplane faces. The FE-Meanplane face from which the inlet interface is created is the last face in the meanplane list meanplanes_[-1]. The face from which the outlet is created is the first face in the meanplane list meanplanes_[0].

The rotation angle is defined through the number of blades nBlades_ in the full 360° channel. The rotation vector is provided through rotVector_.

The bounding surfaces on the hub and shroud are created as multiple bounded surfaces. The required bounding curves (Fig. 58, magenta) are generated from the edges of the other bounding faces of the grid channel. The multiple bounded surfaces need bounding faces on the hub and shroud of the channel geometry channel_ in which the bounding curves are located.

The input orientation_ encodes the orientation of the blade within the channel. The following values are supported:

  • 1: Blade is oriented in the positive u-direction of the channel

  • -1: Blade is oriented in the negative u-direction of the channel

The method calcRotParams() is used to ensure that the bounding faces of the multiple bounded surfaces extend over the correct hub and shroud regions.

The bounding surfaces are appended to the list boundSurf_

The boundary faces of the grid channel and the bounding curves of the hub boundary face, are shown in the following figure.

_images/gidChannel_bound.png

Fig. 58 Bounding faces of the grid channel with periodic faces (yellow / green), inlet and outlet (red), coupling faces (cyan) and bounding curves of the hub boundary (magenta). The blade (grey) is shown for reference.

The following face labels are used for the bounding faces:

  • "inlet": Inlet boundary (Fig. 58 red)

  • "outlet": Outlet boundary (Fig. 58 red)

  • "suction_tri_" + str(i): Suction boundary built from meanplane faces (Fig. 58 and Fig. 57 yellow)

  • "coupling_" + str(i): Boundary connecting to the blade mesh block (Fig. 58 cyan)

  • "pressure_tri_" + str(i): Pressure boundary built from rotated meanplane faces (Fig. 58 yellow)

  • "pressure_quad_" + str(i): Pressure boundary built from rotated meanplane faces (Fig. 58 green)

  • "hub": Multiple bounded surface on the hub

  • "shroud": Multiple bounded surface on the shroud

The strings "pressure" and "suction" correspond to the periodic faces associated with the pressure and suction sides of a turbine channel created with this class.

The markers "tri" and "quad" in the naming of the pressure and suction boundaries are used to distinguish between faces meshed unstructured with prism elements and faces meshed transfinite with hexahedral elements.

The grid channel is created from the faces in boundSurf_ and stored in gridChannel_.

The method getGridChannel() returns the grid channel gridChannel_ together with a list of the bounding faces boundSurf_

If debug mode is enabled, the bounding faces can be plotted using the following naming convention:

"debug_gridChannelFace_" + label_ + "_" + face.getLabel()
build() None[source]

Build part.

This method:

  • Creates multiple bounded surfaces on the hub and shroud.

  • Creates bounding faces from the meanplane and coupling faces.

  • Creates a multiple bounded volume representing the grid channel.

Parameters:

None

Return type:

None

This method creates the grid channel from the faces in meanplanes_ and couplings_. The following figure illustrates the operations performed.

_images/multipleBoundedVolume_gridChannel.png

Fig. 59 Activity diagram of class multipleBoundedVolume_gridChannel. Colors correspond to the creation of geometries shown in Fig. 57 and Fig. 58.

Prepare Containers

Three vector-handling containers are created. The container boundSurf_ stores the bounding surfaces of the multiple bounded volume. The containers hubCurves and shroudCurves store the bounding curves of the multiple bounded surfaces that define the hub and shroud boundaries of the grid channel.

Create Bounding faces for the Multiple Bounded Surfaces on Hub and Shroud

To create the multiple bounded surfaces, bounding faces on the hub and shroud are required. To ensure that these surfaces extend over the full grid channel domain, the hub and shroud points p0h and p0s at the inlet or outlet, depending on orientation_, are extracted from meanplanes_.

By passing these points to the method calcRotParams(), their u-coordinate within the channel, including a tolerance, is calculated. The hub and shroud bounding faces m2d_hub and m2d_shr are then created by rotating a segment of the channel channel_ at this u-coordinate on the hub or shroud around rotVector_.

Iterate over meanplane faces

for i, face in enumerate(meanplanes_):

The periodic faces as well as the inlet and outlet boundaries of the grid channel are created by iterating over meanplanes_.

A volume vol is created by rotating the current meanplane face face. The bounding surfaces of the grid channel are extracted from vol as segments of constant parameter coordinates.

Initially, the string lab is set to "quad".

Interface Meanplane

i == 0 or i == len(meanplanes_) - 1

If the iteration processes the first or last meanplane face, an inlet or outlet interface boundary is created. By definition of meanplanes_, the first entry i == 0 contains the outlet meanplane surface, while the last entry i == len(meanplanes_) - 1 contains the inlet surface.

The inlet and outlet boundaries are added to boundSurf_ with the labels "inlet" and "outlet", respectively.

The corresponding bounding curves on the hub and shroud are appended to hubCurves and shroudCurves.

Periodic FE-Meanplane faces

i < nInOutSurf_ or i >= len(meanplanes_) - nInOutSurf_

The first and last n faces in meanplanes_ are part of the boundary surfaces (compare Fig. 57 and Fig. 58). The number of these faces is specified by nInOutSurf_.

If the iteration is processing one of these faces, the value of lab is changed to "tri". These faces are added to boundSurf_ with the label

"suction_" + lab + "_" + str(i)

The corresponding bounding curves on the hub and shroud are added to the respective containers.

Create Periodic Pressure Surfaces

In every iteration, the rotated meanplane face is added to boundSurf_ with the following label:

"pressure_" + lab + "_" + str(i)

The associated bounding curves are appended to hubCurves and shroudCurves.

Iterate over coupling faces

for i, face in enumerate(couplings_):

All coupling faces are part of the grid channel boundary surfaces. The last two faces in couplings_ correspond to the faces downstream of the trailing edge and are oriented orthogonally to the flow direction. These faces are oriented differently from the remaining coupling faces.

The condition i >= len(couplings_) - 2 identifies these faces and ensures that the correct bounding curves are added to hubCurves and shroudCurves.

Create the Multiple Bounded Surfaces on the Hub and Shroud

The multiple bounded surfaces on the hub and shroud, mbs_hub and mbs_shroud, are created from m2d_hub and m2d_shr together with the lists of bounding curves hubCurves and shroudCurves.

Create the Grid Channel

The grid channel volume is created using the dtOO class multipleBoundedVolume from boundSurf_. The resulting object is stored in gridChannel_.

calcRotParams(p0) float[source]

Calculate the u-parameter of a point within the channel.

This method:

  • Reparametrizes a point in channel coordinates.

  • Offsets the u-parameter by 0.01.

  • Corrects the value if the parameter becomes negative.

  • Returns the resulting u-parameter.

Parameters:

p0 (dtPoint3) – Cartesian point within the channel.

Returns:

uvwP0 – u-parameter of the point in the channel reduced by the tolerance.

Return type:

float

getGridChannel() Tuple[dtOOPythonSWIG.analyticGeometry, List[dtOOPythonSWIG.analyticGeometry]][source]

Return the grid channel volume gridChannel_ and its bounding surfaces boundSurf_.

Parameters:

None

Returns:

  • gridChannel_ (analyticGeometry) – Multiple bounded volume of the grid channel

  • boundSurf_ (labeledVectorHandlingAnalyticGeometry) – List of bounding faces

class dtOOPythonApp.builder.map3dTo3dGmsh_gridFromMultipleBoundedVolumeAndBlocks.map3dTo3dGmsh_gridFromMultipleBoundedVolumeAndBlocks(label: str, channel: dtOOPythonSWIG.analyticGeometry, channelFaces: List[dtOOPythonSWIG.analyticGeometry], blocks: List[dtOOPythonSWIG.analyticGeometry], nMeanplaneBlocks: int, blade: dtOOPythonSWIG.analyticGeometry, nBoundaryLayers: int, nElementsSpanwise: int, nElementsNormal: int, firstElementSizeHubToShroud: float, firstElementSizeNormalBlade: float, bladeHubElementSize: dtOOPythonSWIG.scaOneD = None, bladeHubElementScale: float = None, bladeShroudElementSize: dtOOPythonSWIG.scaOneD = None, bladeShroudElementScale: float = None, charLengthMin: float = 0.05, charLengthMax: float = 0.1, meshTEBlocks: bool = False)[source]

Create mesh’s topology as map3dTo3dGmsh.

This class:

  • Creates the mesh toploogy of bladed channels

  • Adds the geometries of the unstructured region as a multiple bounded volume and a list of bounding surfaces.

  • Adds the mesh blocks.

  • Applies mesh settings.

  • Returns the toplology into the container of the calling class.

label_

Label.

Type:

str

channel_

Channel.

Type:

multipleBoundedVolume

channelFaces_

List of bounding faces surrounding the channel

Type:

List[ map2dTo3d ]

blocks_

List of mesh blocks surrounding the blade.

Type:

List[ map3dTo3d ]

nMeanplaneBlocks_

Number of block faces which are part of the meanplane

Type:

int

blade_

Blade.

Type:

map2dTo3d

nBoundaryLayers_

Number of boundary layers.

Type:

int

nElementsSpanwise_

Number of elements in spanwise direction.

Type:

int

nElementsNormal_

Number of elements on the blade surface.

Type:

int

firstElementSizeHubToShroud_

Size of first element on hub and shroud.

Type:

float

firstElementSizeNormalBlade_

Size of first element at the blade in normal to the blade direction.

Type:

float

bladeHubElementSize_

Function describing the element size versus the standardized unwrapped length of the blade at the hub.

Type:

scaOneD

bladeHubElementScale_

Factor defining the number of elements at the hub for each mesh block.

Type:

float

bladeShroudElementSize_

Function describing the element size versus the standardized unwrapped length of the blade at the shroud.

Type:

scaOneD

bladeShroudElementScale_

Factor defining the number of elements at the shroud for each mesh block.

Type:

float

meshTEBlocks_

Marker if trailing edge mesh blocks should be meshed

Type:

Bool

map3dTo3dGmshJson_

JSON structure for map3dTo3dGmsh.

Type:

jsonPrimitive

Return type:

None

Examples

The main method of this class is build().

The mesh topology is constructed from the channel, represented as a multiple bounded volume channel_, and the blade mesh blocks provided in the list blocks_. Throughout this documentation, N denotes the number of mesh blocks, i.e., len(blocks_).

The mesh regions are numbered as follows:

  • R_0 : Channel

  • R_1 : First mesh block

  • R_(N-1) : (N-1)th mesh block

The multiple bounded volume is meshed using an unstructured mesh with prismatic boundary layers. The mesh block volumes are meshed as transfinite regions with recursive recombination.

The topology settings are initialized from map3dTo3dGmshJson_. The model is created as m3dGmsh.

The bounding surfaces of the multiple bounded volume are provided through the list channelFaces_.

The surfaces of the mesh topology are either taken directly from channelFaces_ or extracted from the block volumes in blocks_ using the method detectFirstAndSecond(). This method takes a block volume as a map3dTo3d object and a parameter direction as an integer input. It returns the faces located at the normalized positions 0 and 1 along the specified parameter direction.

The blade surface is provided through blade_.

The following figure illustrates the surfaces in the mesh topology. The hub and shroud surfaces are not shown.

_images/meshFaces_labeled.png

Fig. 60 Topology faces and their labels used in this class. Interfaces (red), periodic meanplane faces (yellow/green), coupling faces (cyan), and blade surfaces (gray) are highlighted.

By iterating over blocks_, the corresponding surfaces are added to the topology. For each mesh block, the blade surface is added and labeled with the identifier "blade".

The number of mesh block surfaces that belong to the mean plane is specified by the input nMeanplaneBlocks_. These surfaces do not connect to the multiple bounded volume channel. In this class, they are labeled with the identifier "block".

The remaining faces shown in Fig. 60, together with the hub, shroud, and coupling surfaces, are added to the topology through channelFaces_ and labeled according to the strings shown in the figure.

The coupling faces between the mesh blocks and the channel multiple bounded volume are labeled with the identifier "coupling". The hub and shroud bounding surfaces are labeled with the identifiers "hub" and "shroud", respectively.

The periodic faces of the topology are those labeled "suction", "pressure", and "block". The labels "suction" and "pressure" correspond to the suction and pressure sides of a turbine blade.

Periodically connected faces that are meshed using an unstructured mesh are labeled with the identifier "tri". The faces periodic to the "block" faces are meshed as transfinite surfaces and are assigned the identifier "quad". Periodicity on these faces is defined using the observer bVOSetRotationalPeriodicity.

The boolean value meshTEBlocks_ controls whether trailing edge mesh blocks are created. If trailing edge mesh blocks are required, this parameter must be set to True.

Each face identifier is assigned an integer suffix for unique identification. The following faces are added to the topology when trailing edge mesh blocks are enabled:

  • "hub_0""hub_"+str(N)

  • "shroud_0""shroud_"+str(N)

  • "inlet_0"

  • "outlet_0"

  • "suction_tri_0", "suction_tri_1", "suction_tri_"+str(nMeanplaneBlocks_+3), "suction_tri_"+str(nMeanplaneBlocks_+4)

  • "block_0""block_"+str(nMeanplaneBlocks_)

  • "pressure_tri_0", "pressure_tri_1", "pressure_tri_"+str(nMeanplaneBlocks_+3), "pressure_tri_"+str(nMeanplaneBlocks_+4)

  • "pressure_quad_2""pressure_quad_"+str(nMeanplaneBlocks_+2)

  • "blade_0""blade_"+str(N-1)

  • "coupling_0""coupling_"+str(N+2-nMeanplaneBlocks_-1)

Prismatic boundary layers are generated on the "hub" and "shroud" faces. The number of elements in these layers is specified by nBoundaryLayers_. The boundary layers extend onto the "inlet", "outlet", "suction", "pressure", and "coupling" faces of the multiple bounded volume.

The minimum and maximum characteristic mesh sizes of the unstructured mesh are specified by the inputs charLengthMin and charLengthMax.

The method extractEdgesInFirstAndSecond() is used to identify the edges of a surface that lie on two other surfaces.

The following figure illustrates the edge groups to which mesh settings are applied. Each group is highlighted using a uniform color.

_images/guideVane_channelMeshing.png

Fig. 61 Edges of the bladed channel to which mesh settings are applied: hubToShroudLines (orange), bladeHubLines and bladeShroudLines (blue), bladeToBlockLines (green), and the trailing edge mesh block edges contained in tEMeshList (pink). No explicit mesh settings are applied to the gray edges.

Gradings are applied to refine the mesh near the hub, shroud, and blade walls. The method addGrading() is used to create the grading functions. The methods gradingsTypeTransfinite() and gradingsGradingFunctions() are then used to apply these gradings to the mesh setting observer bVOMeshRule.

The following table summarizes the edge groups and their corresponding mesh parameters and settings:

Table 6 Edges and their mesh parameters

Edge group

Number of elements /

Element size

Grading label /

First element size

hubToShroudLines

nElementsSpanwise_

"hubToShroud"

firstElementSizeHubToShroud_

bladeHubLines

bladeHubElementSize_

"tangentialBlade_*"

bladeShroudLines

bladeShroudElementSize_

"tangentialBlade_*"

bladeToBlockLines

nElementsNormal_

"normalBlade"

firstElementSizeNormalBlade_

tEMeshList

nElementsNormal_

No grading

The mesh parameters beginning with nElements... specify a fixed number of elements along each edge. The parameters beginning with firstElementSize... define the size of the first element adjacent to the wall on which the grading is applied.

The mesh sizes along the blade contour (bladeHubLines and bladeShroudLines) are controlled by the functions bladeHubElementSize_ and bladeShroudElementSize_, respectively. For each edge, a minimum number of elements is first determined from its start and end vertices. The blending factors bladeHubElementScale_ and bladeShroudElementScale_ are then used to interpolate between the element counts at both ends, thereby defining the number of elements assigned to the edge.

To ensure a smooth transition in element sizes between consecutive edges, the "tangentialBlade_*" grading is adjusted at both the start and end vertices.

Trailing edge mesh blocks are generated only if meshTEBlocks_ is set to True. The corresponding edges are collected in the list tEMeshList. No grading functions are applied to these edges.

The observer bVOFaceToPatchRule is used to rename the following faces so that they match the boundary naming convention of the OpenFOAM case:

Table 7 Renaming of the faces for openFOAM case setup.

Original name

Boundary name

"*hub*"

label_+"_hub"

"*shroud*"

label_+"_shroud"

"*blade*"

label_+"_blade"

"*inlet*"

label_+"_inlet"

"*outlet*"

label_+"_outlet"

"*suction*"

label_+"_suction"

"*block*"

label_+"_suction"

"*pressure*"

label_+"_pressure"

If debug mode is enabled the geometries are plotted and prefixed with "debug_".

The following observers are also added:

  • bVOReadMSH

  • bVODumpModel

  • bVOWriteMSH

  • bVOOrientCellVolumes

Finally, the mesh topology is returned to the calling class through appendBoundedVolume.

A mesh resulting from this topology is shown in the following figure.

_images/guideVane_mesh.png

Fig. 62 Mesh of a bladed channel resultuing from the described topology.

build() None[source]

Build part.

Parameters:

None

Return type:

None

The model is initialized as m3dGmsh from map3dTo3dGmshJson_. The container aG of type labeledVectorHandlingAnalyticGeometry is created to manage the analytic geometries.

Add the Grid Channel Volume and Faces

The multiple bounded volume of the grid channel``channel_`` is added to the model. Its bounding faces are added by iterating over the list channelFaces_. Regular faces, for which multipleBoundedSurface.ConstDownCast(face) == None applies, are added directly to aG. The hub and shroud faces are of the type multipleBoundedSurface. For these faces, the else branch is executed and their bounding surfaces are added individually.

The face labels are assigned during the generation of the multiple bounded volume in the class multipleBoundedVolume_gridChannel.

Add the Mesh Block Volumes and Faces

The block volumes and their faces are added by iterating over blocks_ using i, block in enumerate(blocks_). The block faces on the blade wall and the surrounding surfaces are extracted using the method detectFirstAndSecond(). The faces on the blade wall are labeled "blade_" + str(i), while the surrounding surfaces are labeled "block_" + str(i).

The block volumes are ordered so that their sequence in blocks_ follows the u-direction of the blade surface blade_. If trailing edge mesh blocks exist, they correspond to the first and last entries of blocks_.

If trailing edge mesh blocks are enabled (meshTEBlocks_ == True), the blade faces of the first and last mesh blocks are not added to aG. Only block faces that are part of the mean plane are added to aG (i <= nMeanplaneBlocks_), corresponding to the "block" faces shown in Fig. 60.

The block volumes are added to the model as dtRegion objects and configured to be meshed using transfinite meshing with recursive recombination.

The observer bVONameRegions is added to establish the naming convention of the regions.

Organize Edges of the Trailing Edge Mesh Blocks

The edges of the trailing edge mesh blocks (shown in pink in Fig. 61) are extracted by first obtaining the blade and block faces of blocks_[0] and blocks_[-1] using detectFirstAndSecond(). Their hub and shroud edges are then identified using extractEdgesInFirstAndSecond().

Using these edges, the list tEMeshList is constructed with the following structure:

tEMeshList = List[
    Tuple[
        Tuple[List[int], List[int]],
        int
    ]
]

The top level list entries have the following meaning:

  • tEMeshList[0] : Edges extending directly from the blade

  • tEMeshList[1] : Edges extending from the outer wall of the first mesh block

  • tEMeshList[2] : Edges extending from the outer wall of the last mesh block

The lower level entries of tEMeshList are defined as follows:

  • tEMeshList[i][0] : Tuple containing lists of edge identifiers

  • tEMeshList[i][0][0] : List of edge identifiers on the hub

  • tEMeshList[i][0][1] : List of edge identifiers on the shroud

  • tEMeshList[i][1] : Integer specifying the edge direction

Manage Faces

The observer bVOAnalyticGeometryToFace is added to implement the faces stored in aG within m3dGmsh.

The periodic faces (shown in yellow and green in Fig. 60) are organized in the list periodics. The list is constructed such that each entry periodics[i] is a Tuple containing a pair of periodic faces. The suction side boundary is stored in periodics[i][0] and the corresponding pressure side boundary in periodics[i][1].

The faces that are meshed unstructured, and their hub-to-shroud edges, are stored in the list unstrFacesAndh2sLines. These faces are identified in aG by their physical labels "inlet", "outlet", "suction_tri", and "pressure_tri" (see Fig. 60).

The list has the following structure:

unstrFacesAndh2sLines = List[
    List[
        map2dTo3d,
        List[int]
    ]
]

Each entry contains an unstructured face, unstrFacesAndh2sLines[i][0], and the list of its edges that extend from hub to shroud, unstrFacesAndh2sLines[i][1].

Manage Edges and Set Number of Elements

The edges to which mesh settings are applied (see Fig. 61) are identified by extracting and organizing lists of edge identifiers returned by the dtGmshModel.

The following edge identifier lists are used to define the mesh settings:

  • hubToShroudLines

  • bladeToBlockLines

  • bladeHubLines

  • bladeShroudLines

The dictionary gradings is created, and grading functions for the edges in hubToShroudLines and bladeToBlockLines are added using the method addGrading().

This method takes the gradings dictionary, a grading function, a label, the model, and the size of the first element in the grading as input.

The grading associated with hubToShroudLines is assigned the label "hubToShroud" and uses the first element size firstElementSizeHubToShroud_. The grading associated with bladeToBlockLines is assigned the label "normalBlade" and uses the first element size firstElementSizeNormalBlade_.

The number of elements and the grading functions are then applied to the edges according to the specifications listed in Table 6.

The mesh settings for the blade edges bladeShroudLines and bladeHubLines are applied by iterating over the corresponding edge lists.

Mesh settings for the trailing edge mesh block edges are applied only if meshTEBlocks_ == True.

Mesh Settings along the Blade

The orientation of the blade edges is determined using boundaryEdgeDirection(). The method is provided with m3dGmsh.getModel() and a list containing the blade surface blade_ together with the corresponding edge lists.

For each edge, the edge length eL is computed and the start and end vertices v0 and v1 are identified. These points are reparameterized onto the blade surface blade_, yielding the surface parameter coordinates p0_uv and p1_uv.

Depending on the iteration the element size functions bladeHubElementSize_ or bladeShroudElementSize_ are then evaluated at the corresponding parameter coordinates to obtain the local element sizes ms_0 and ms_1 in the appropriate parameter direction.

Using these element sizes and the edge length eL, the required numbers of elements, nE_0 and nE_1, are computed and rounded up to the next integer.

The final number of elements assigned to the blade edge is calculated as

nE = math.ceil(
    min(nE_0, nE_1) + elementScale * abs(nE_1 - nE_0)
)

The floating point value elementScale corresponds to either bladeShroudElementScale_ or bladeHubElementScale_, depending on the current iteration.

For each edge, a grading function with the label "tangentialBlade_*" is created. The start and end element sizes of the grading are set to ms_0 and ms_1, respectively.

Set Mesh Rules

The boundary layer directions of the unstructured faces stored in unstrFacesAndh2sLines are determined using detectBoundaryLayerDir(), which returns the list boundaryLayerDir.

The mesh rules are defined using the observer bVOMeshRule. The methods gradingsTypeTransfinite() and gradingsGradingFunction() are used to retrieve the appropriate grading information from the gradings dictionary and pass it to the observer.

Meshing of the unstructured region is performed using the rules "dtMeshGFaceWithTransfiniteLayer" and "dtMeshGRegionWithBoundaryLayer".

The rule "dtMeshGFaceWithTransfiniteLayer" is applied to the faces that are meshed unstructured, namely "*inlet*", "*outlet*", "*suction_tri*" and "*pressure_tri*".

The rule "dtMeshGRegionWithBoundaryLayer" is applied to the region corresponding to the multiple bounded volume, "R_0". The hub and shroud faces, "hub_0" and "shroud_0", on which the boundary layers are generated, are added to the "_faceLabel" entry.

The boundary layers extend onto the faces of "R_0" labeled "*inlet*", "*outlet*", "*pressure_*", "*suction_*", and "*coupling_*". These faces are added to the "_slidableFaceLabel" entry.

The number of boundary layer elements is specified by nBoundaryLayers_, while the boundary layer orientation is defined by boundaryLayerDir.

Define Observers

The observers bVOReadMSH and bVODumpModel are then added.

To define rotational periodicity, a reference coordinate system theT is created and added to the base container object bC. The periodic boundary conditions are established by iterating over periodics and creating a bVOSetRotationalPeriodicity observer for each pair of periodic faces.

The faces are renamed to match the boundary condition naming convention used in an OpenFOAM case through the observer bVOFaceToPatchRule. The corresponding renaming rules are summarized in Table 7.

The observer bVOWriteMSH controls the generation of the mesh file. The observer bVOOrientCellVolumes ensures that all mesh cell volumes have a positive orientation.

The created mesh topology m3dGmsh is returned to the calling class using the method appendBoundedVolume.

static detectFirstAndSecond(channel: dtOOPythonSWIG.map3dTo3d, direction: int) Tuple[dtOOPythonSWIG.map2dTo3d, dtOOPythonSWIG.map2dTo3d][source]

Detect first and second faces in a volume’s parameter direction.

This method returns the faces of a map3dTo3d object at 0 and 100 percent of the u-, v-, or w-paramter.

Parameters:
  • channel (map3dTo3d) – Volume.

  • direction (int) –

    Direction in uvw

    • 1 -> U

    • 2 -> V

    • 3 -> W

Returns:

  • first (map2dTo3d) – First segment in direction

  • second (map2dTo3d) – Second segment in direction

static extractEdgesInFirstAndSecond(theModel: dtOOPythonSWIG.dtGmshModel, faces: List[dtOOPythonSWIG.map2dTo3d], first: dtOOPythonSWIG.map2dTo3d, second: dtOOPythonSWIG.map2dTo3d) Tuple[List[int], List[int]][source]

Extracts edges of faces which lie on another first or second face.

This method:

  • Iterates over faces and extracts the edges of each face

  • Checks if any of the edges are located on the first face

  • Appends the edge to firstEdges if the check applies

  • Checks if any of the edges are located on the second face

  • Appends the edge to secondEdges if the check applies

  • Returns firstEdges and secondEdges

Parameters:
  • theModel (dtGmshModel) – Gmsh model

  • faces (List[map2dTo3d]) – List of faces

  • first (map2dTo3d) – First face

  • second (map2dTo3d) – Second face

Returns:

  • firstEdges (List[int]) – Edges of on first face

  • secondEdges (List[int]) – Edges of on second face

static boundaryEdgeDirection(theModel: dtOOPythonSWIG.dtGmshModel, boundaryLayerDirCheck: List[List[dtOOPythonSWIG.map2dTo3d | List[int]]]) int[source]

Determine the boundary layer direction of a face from two edges.

This method:

  • Iterates over the faces and edges in the input list.

  • Checks whether the u- or v-parameters of the start and end points of the edges on a face are equal within a specified tolerance.

  • Determines and returns the corresponding boundary layer direction.

Parameters:
  • theModel (dtGmshModel) – Gmsh model.

  • boundaryLayerDirCheck (List[List[map2dTo3d, List[int]]]) –

    List containing faces and their corresponding edges.

    The entries are organized as follows:

    • boundaryLayerDirCheck[i] : One face and its associated edges.

    • boundaryLayerDirCheck[i][0] : Face.

    • boundaryLayerDirCheck[i][1] : List of edges.

Returns:

Integer encoding the boundary layer direction.

Return type:

int

The boundary layer direction is determined by iterating over faceLines in boundaryLayerDirCheck in an outer loop and over the edges line in faceLines[1] in the inner loop.

During each iteration of the inner loop, the start and end points p0_uv and p1_uv of the current edge are reparameterized in the parameter space of the surface face.

The method inTolerance() is used to determine whether the difference between the u- or v-parameters lies within the tolerance specified by tol. Depending on the result, the value of boundaryLayerDirT is incremented. The resulting value is appended to the list boundaryLayerDir.

At the end of each outer loop iteration, duplicate entries in boundaryLayerDir are removed using boundaryLayerDir = list(dict.fromkeys(boundaryLayerDir)).

Within this workflow, all boundary layer directions must be oriented consistently. The condition len(boundaryLayerDir) != 1 is therefore used to verify that all detected directions are identical. If this condition is not satisfied, an exception is raised.

Finally, the boundary layer direction is encoded as an integer return value. If boundaryLayerDir[0] equals 1, the method returns 0. If boundaryLayerDir[0] equals 2, the method returns 1. Any other value results in an exception.

static detectBoundaryLayerDirection(theModel: dtOOPythonSWIG.dtGmshModel, boundaryLayerDirCheck: List[List[dtOOPythonSWIG.map2dTo3d | List[int]]]) int[source]

Determine the boundary layer direction of a face from two edges.

This method:

Parameters:
  • theModel (dtGmshModel) – Gmsh model

  • boundaryLayerDirCheck (List[ List[ map2dTo3d, List[int]]]) –

    List containing faces and corresponding edges. Entries correlate to:

    • boundaryLayerDirCheck[i] : Set of one face and its edges

    • boundaryLayerDirCheck[i][0] : Face

    • boundaryLayerDirCheck[i][1] : List of edges

Return type:

int

inTolerance(p0: float, p1: float) bool[source]

Check if two float values lie within a tolerance.

This method:

  • Calculates the difference between two float values

  • Returns boolean depending if tolerance is met

Parameters:
  • tol (float) – Tolerance

  • p0 (float) – First value

  • p1 (float) – Second value

Return type:

bool

addGrading(gradings: Dict, theRef: dtOOPythonSWIG.scaOneD, gradingLabel: str, m3dGmsh: dtOOPythonSWIG.map3dTo3dGmsh = None, firstElementSize: float = 0.0, lastElementSize: float = 0.0) Dict[source]

Create a grading and add it to the grading dictionary.

This method:

  • Creates an entry in the grading dictionary.

  • Labels the grading function and appends it to the container.

  • Creates an observer for the grading.

  • Returns the updated grading dictionary.

Parameters:
  • gradings (Dict) –

    Grading dictionary.

    Each key corresponds to a grading identifier and contains the following information:

    • gradingLabel (List[int, str]): A list containing the grading number and a string identifier.

  • theRef (scaOneD) – Grading function.

  • gradingLabel (str) – Grading label.

  • m3dGmsh (map3dTo3dGmsh) – Gmsh topology object.

  • firstElementSize (float) – Size of the first element in the grading.

  • lastElementSize (float) – Size of the last element in the grading.

Returns:

Updated grading dictionary.

Each key corresponds to a grading identifier and contains the following information:

  • gradingLabel (List[int, str]): A list containing the grading number and a string identifier.

Return type:

Dict

For a new grading, an entry is created in the dictionary gradings using gradingLabel as the key. The corresponding value is a list containing a unique grading number and identifier string of the form

label_ + "_gradings_" + str(gradingNumber) + "_" + gradingLabel

The grading function theRef is assigned this identifier string and added to the analytic function container of the calling class.

Depending on whether the grading specifies only the first element size, (firstElementSize > 0.0) and (lastElementSize == 0.0), or both the first and last element sizes, (firstElementSize > 0.0) and (lastElementSize > 0.0), an observer of type bVOSetPrescribedElementSize is created using the specified element sizes and the grading function.

The observer is then added to the topology.

Finally, the updated grading dictionary is returned.

static gradingsTypeTransfinite(gradings: Dict) str[source]

Get the list of grading numbers and return it as a string.

This method:

  • Iterates over the entries of the grading dictionary

  • Appends the grading numbers to a list

  • Converts the list to a string and returns it

Parameters:

gradings (Dict) –

Grading dictionary with each key containing identifiers for a grading:

  • gradingLabel (List[int, str]): Grading label key contains a list with grading number and a identifier string

Return type:

str

static gradingsGradingFunctions(gradings: Dict) str[source]

Create a string of grading identifiers in a jsonPrimitive format.

This method:

  • Iterates over the entries of the grading dictionary

  • Appends the grading identifiers in the format of a jsonPrimitive

  • Returns the string

Parameters:

gradings (Dict) –

Grading dictionary with each key containing identifiers for a grading:

  • gradingLabel (List[int, str]): Grading label key contains a list with grading number and a identifier string

Returns:

retStr – Return string

Return type:

str

class dtOOPythonApp.builder.analyticGeometry_layerRegion.analyticGeometry_layerRegion(label: str, speHub: List[dtOOPythonSWIG.analyticGeometry], speShroud: List[dtOOPythonSWIG.analyticGeometry], inOutCurves: List[dtOOPythonSWIG.analyticGeometry], layer_thickness: float = 0, layer_supports: List[float] = [], rotVector: dtOOPythonSWIG.dtVector3 = dtOOPythonSWIG.dtVector3, origin: dtOOPythonSWIG.dtPoint3 = dtOOPythonSWIG.dtPoint3)[source]

Create flow channel as five or six sided layer regions on the walls and a multiple bounded volume inside the flow domain.

This class:

  • Takes hub, shroud, inlet and outlet curves of the layered region.

  • Creates layer boundary curves on the hub and shroud walls.

  • Creates layer faces from the boundary curves.

  • Creates layer volumes by rotating the boundaries.

  • Creates a multiple bounded volume in the flow channel connecting to the layers.

label_

Label.

Type:

str

rotVector_

Rotation vector.

Type:

dtVector3

origin_

Origin.

Type:

dtPoint3

normalAxis_

Normal direction of the 2d region curves.

Type:

dtVector3

speCenter_

Center point of the bounding box of the region.

Type:

dtPoint3

speBb_

Bounding box of the whole region.

Type:

pairDtPoint3

hubLayerCurves_

Boundary curves of the hub wall.

Type:

List[analyticGeometry]

hubRadZero_

List containing information about which hub curves are on a radius of zero.

Type:

List[Bool]

hubUnstructBounds_

Boundary curves of the multiple bounded volume at the hub.

Type:

List[analyticGeometry]

shroudLayerCurves_

Boundary curves of the shroud Layer regions.

Type:

List[List[analyticGeometry]]

shroudRadZero_

List containing information about which shroud curves are on a radius of zero.

Type:

List[Bool]

shroudUnstructBounds_

Boundary curves of the multiple bounded volume at the shroud.

Type:

List[analyticGeometry]

interfaceUnstructBound_

Inlet boundary curve of the multiple bounded volume.

Type:

analyticGeometry

outletUnstructBound_

Outlet boundary curve of the multiple bounded volume.

Type:

analyticGeometry

unstructVH_

vector handler containing all boundary curves of the multiple bounded volume.

Type:

vectorHandlingAnalyticGeometry

hubLayers_

List containing the faces of the six sided hub layers.

Type:

List[analyticGeometry]

shroudLayers_

List containing the faces of the six sided shroud layers.

Type:

List[analyticGeometry]

Examples

>>> import dtOOPythonSWIG as dtOO

Define inlet, outlet, hub and shroud curves of the layer.

>>> inlet = dtOO.analyticCurve(
...   dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(0.50, +0.00, 0.80)
...       << dtOO.dtPoint3(0.75, +0.00, 0.80)
...       << dtOO.dtPoint3(1.00, +0.00, 1.00),
...     2
...   ).result()
... )
>>> outlet = dtOO.analyticCurve(
...   dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(0.00, +0.00, 0.00)
...       << dtOO.dtPoint3(1.10, +0.00, 0.00),
...     1
...   ).result()
... )
>>> hub0 = dtOO.analyticCurve(
...   dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(0.50, +0.00, 0.80)
...       << dtOO.dtPoint3(0.25, +0.00, 0.60)
...       << dtOO.dtPoint3(0.00, +0.00, 0.40),
...     2
...   ).result()
... )
>>> hub1 = dtOO.analyticCurve(
...   dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(0.00, +0.00, 0.40)
...       << dtOO.dtPoint3(0.00, +0.00, 0.00),
...     1
...   ).result()
... )
>>> shroud0 = dtOO.analyticCurve(
...   dtOO.bSplineCurve_pointConstructOCC(
...     dtOO.vectorDtPoint3()
...       << dtOO.dtPoint3(1.00, +0.00, 1.00)
...       << dtOO.dtPoint3(1.10, +0.00, 0.00),
...     1
...   ).result()
... )

Create the input lists with the boundary curves.

>>> speHub = [hub0, hub1]
>>> speShroud = [shroud0]
>>> inOutCurves = [inlet, outlet]

Initialize the builder.

>>> from dtOOPythonApp.builder import analyticGeometry_layerRegion
>>> builder = analyticGeometry_layerRegion(
...   label = "test",
...   speHub = speHub,
...   speShroud = speShroud,
...   inOutCurves = inOutCurves,
...   layer_thickness = 0.2,
...   layer_supports = [0.33, 0.66]
... ).enableDebug()
>>> builder.build()

Build the multiple bounded volume of the layer region.

>>> unstrReg, surf = builder.getUnstructuredRegion(10)

Check the virtual class name.

>>> unstrReg.virtualClassName()
'multipleBoundedVolume'

This class is used to create the geometry of a flow channel consisting of five- or six- sided layer volumes on the hub and shroud walls, as well as a multiple bounded volume that expands inside the flow domain and connects to the layers. In this documentation, the region formed by the multiple bounded volume is referred to as the unstructured region.

The main method of this class is the constructor, from which the remaining methods are called. The rotational vector and the point of origin are initialized as rotVector_ and origin_.

The method calculateNormalAxis() is used to calculate the normal axis normalAxis_ on the flow domain cross section from the hub and shroud curves. Furthermore, the method returns the cross section bounding box speBb_ and its center point speCenter_.

The bounding curves of the layers are created using the method createLayerBounds(). This method is called twice to create the bounds of the hub and shroud wall layer faces. The return values of the two calls are stored in the lists hubLayerCurves_, hubRadZero_, and hubUnstructBounds_ for the hub layer, and shroudLayerCurves_, shroudRadZero_, and shroudUnstructBounds_ for the shroud layer.

The lists hubLayerCurves_ and shroudLayerCurves_ contain the bounding curves of the corresponding layer faces. Within createLayerBounds(), the method layerCurve() is called.

The lists hubRadZero_ and shroudRadZero_ contain Boolean values corresponding to the number of layers created on the hub or shroud. These Boolean values indicate which layers are located on a radius of zero. The method rz_xyz() is used to perform this check.

The lists hubUnstructBounds_ and shroudUnstructBounds_ contain the layer boundary curves that extend into the flow domain and form the interfaces between the unstructured multiple bounded volume and the layers.

The inlet and outlet curves of the flow domain cross section are shared between the hub and shroud layer regions and the unstructured region. By splitting these curves, the inlet boundary of the unstructured region is assigned to the variable interfaceUnstructBound_ and the outlet boundary to outletUnstructBound_.

The vector handler unstructVH_ acts as a container for all hub and shroud boundary curves of the unstructured region. The curves in hubUnstructBounds_ and shroudUnstructBounds_, as well as the curves interfaceUnstructBound_ and outletUnstructBound_, are stored in this vector handler.

From the bounding curves of the hub and shroud layers, layer faces are created and stored in hubLayers_ and shroudLayers_.

The layer volumes are created by rotating the layer faces around the rotation axis and are returned by the method getLayerList(). The method returns a list with the following structure:

layerList = List[
    List[
        List[analyticGeometry],
        List[bool]
    ]
]

The entries correspond to the following values:

  • layerList[0]: Hub layers

  • layerList[1]: Shroud layers

  • layerList[i][0]: List of layer volumes

  • layerList[i][1]: List of Boolean values indicating whether the corresponding layer is located on a radius of zero

The unstructured region is created in the method getUnstructuredRegion(). This method returns the multiple bounded volume of the unstructured region together with a list containing its boundary surfaces.

The build() method is used to visualize the created geometries in ParaView.

__init__(label: str, speHub: List[dtOOPythonSWIG.analyticGeometry], speShroud: List[dtOOPythonSWIG.analyticGeometry], inOutCurves: List[dtOOPythonSWIG.analyticGeometry], layer_thickness: float = 0, layer_supports: List[float] = [], rotVector: dtOOPythonSWIG.dtVector3 = dtOOPythonSWIG.dtVector3, origin: dtOOPythonSWIG.dtPoint3 = dtOOPythonSWIG.dtPoint3) None[source]

Constructor.

This method:

  • Creates layer boundary curves.

  • Creates layer faces.

  • Creates boundary curves of the unstructured region.

Parameters:
  • label (str) – Label.

  • speHub (List[analyticGeometry]) – Hub curves of the flow domain.

  • speShroud (List[analyticGeometry]) – Shroud curves of the flow domain.

  • inOutCurves (List[analyticGeometry]) – Inlet and outlet curves of the flow domain.

  • layer_thickness (float) – Thickness of mesh layers in unstructured domain.

  • layer_supports (List[float]) – Number and position of support points on channel curves for layer creation.

  • rotVector (dtVector3) – Rotation vector.

  • origin (dtPoint3) – Origin.

Return type:

None

The boundary curves of the channel are passed to the constructor through the lists speHub, speShroud, and inOutCurves. These lists contain the curves of the hub and shroud walls, as well as the inlet and outlet curves of the flow channel cross section.

The following figure shows the cross section and the corresponding curves.

_images/speCurves.png

Fig. 63 Special hub (speHub) and special shroud (speShroud) curves (black), together with the inlet (red) and outlet (orange) curves of the draft tube cone.

The rotation vector and the origin are stored in the variables rotVector_ and origin_.

The hub and shroud curves are passed to the method calculateNormalAxis(). This method creates and returns the bounding box speBb_ surrounding the curves. Furthermore, the center point speCenter_ and the normal axis normalAxis_ of the bounding box are calculated and returned.

The boundary curves of the layers are created using the method createLayerBounds(). This method is called once for the hub layers and once for the shroud layers.

As input, the wall curve lists speHub or speShroud and the inlet and outlet curves inOutCurves are passed to the method. The layer generation is defined by the layer thickness layer_thickness (\(t_{Layer}\)) and the list of support point positions along the spans of the wall curves layer_supports. The label parameter is used to assign physical names to the generated geometries for visualization.

The return values are the layer boundary curves hubLayerCurves_ and shroudLayerCurves_, the lists encoding whether a layer is located on a radius of zero (hubRadZero_ and shroudRadZero_), and the connecting curves to the unstructured region (hubUnstructBounds_ and shroudUnstructBounds_).

Each wall curve that is not located on a radius of zero generates one layer face. Each layer face consists of four boundary curves. The first boundary curve corresponds to the respective hub or shroud wall curve.

The second and fourth boundary curves extend from the start and end points of the wall curves into the flow channel. For the first and last layer faces at the hub and shroud, these curves correspond either to the inlet or outlet curves or to a wall curve located on a radius of zero. At the intersection points of two wall curves, boundary curves extending into the flow channel are constructed such that they follow the mean normal direction of both curves.

The third boundary curve connects the second and fourth boundary curves inside the flow channel. It is constructed from the end points of the second and fourth boundary curves together with additional support points. These support points are calculated by translating points on the hub and shroud curves in the normal direction of the curves. The positions of these points along the hub and shroud curves are defined by the list layer_supports.

The lists hubLayerCurves_ and shroudLayerCurves_ have the structure List[List[analyticGeometry]]. In this structure, each first level list contains the four boundary curves of one layer face stored in the corresponding second level list.

The arrangement of the boundary curves in the second level list is as follows:

  1. hubLayerCurves_[i][0]: Wall curve of the i-th special hub curve.

  2. hubLayerCurves_[i][1]: Downstream curve extending from the wall into the flow channel or, for the last layer, along the outlet or a wall curve located on a radius of zero.

  3. hubLayerCurves_[i][2]: Curve extending inside the flow channel.

  4. hubLayerCurves_[i][3]: Upstream curve extending from the wall into the flow channel or, for the first layer, along the inlet interface.

This ordering results in the following parameter directions of the layer volumes after rotation:

  • u: Circumferential direction

  • v: Streamwise direction

  • w: Direction from the wall toward the flow domain

The following figure shows the boundary curves of the layers in black and the layer faces in blue. As an example of the numbering convention of the boundary curves, the indices of the second level list in hubLayerCurves_[0] are shown.

_images/layers2d_numbering.png

Fig. 64 Two dimensional layer faces (blue) in the draft tube cone.

The lists containing Boolean values, hubRadZero_ and shroudRadZero_, contain a value of True for layers located on a radius of zero. These layers form the last layer face on the corresponding wall. Their second boundary curve is formed by a section of the subsequent boundary curve located on the radius of zero. In the figures above, this applies to the curve in speHub[1].

The curves in hubUnstructBounds_ and shroudUnstructBounds_ are copies of the third boundary curves of the layer faces. These curves are used to construct the multiple bounded volume of the unstructured region.

The inlet of the flow domain created in this class corresponds to the curve in inOutCurves[0]. A section of this curve is used as the inlet boundary of the unstructured region.

The curve is trimmed according to the layer thicknesses layer_thickness using the dtOO class trimmedCurve_uBounds. The resulting trimmed curve is stored in interfaceUnstructBound_.

To trim the outlet curve in inOutCurves[1], it must first be determined whether a layer exists on the last hub curve. No layer is created on the last hub curve if the hub extends to a radius of zero. In this case, hubRadZero_[-1] == True applies, and the first trim parameter is set to zero. Otherwise, the trim parameters on both the hub and shroud sides are determined using layer_thickness. The resulting trimmed curve is stored in outletUnstructBound_.

The object unstructVH_ of the dtOO class vectorHandlingAnalyticGeometry is instantiated to contain all boundary curves describing the contour of the unstructured region. The curves in hubUnstructBounds_ and shroudUnstructBounds_ are added to this object, while interfaceUnstructBound_ is prepended and outletUnstructBound_ is appended.

The faces of the hub and shroud layers are created by iterating over the lists hubLayerCurves_ and shroudLayerCurves_. During each iteration, the second level boundary curves are inserted into a vector handler object named layer_vhc.

The layer faces are then generated using the dtOO class bSplineSurface_bSplineCurveFillConstructOCC with layer_vhc as input. The resulting layer faces are stored in the lists hubLayers_ and shroudLayers_.

createLayerBounds(layerCurve, inOutCurves, thickness, supports, lab)[source]

Create boundary curves of the layer faces.

This method:

  • Iterates over the wall curves and checks if they are on a radius of zero.

  • Iterates over curves and combines them if they have a steady transition.

  • Iterates over curves and creates boundary curves of the layer faces.

  • Returns the lists with layer bounds and boundary curves for the unstructured region as well as a list telling which layers are on a radius of zero.

Parameters:
  • layerCurve (List[analyticGeometry]) – List of wall curves.

  • inOutCurves (List[analyticGeometry]) – List with inlet and outlet curves.

  • thickness (float) – Layer thickness.

  • supports (List[float]) – List with positions of support points in percent along the parametrized span of the wall curve.

  • lab (string) – label

Returns:

  • returnBounds (List[List[analyticGeometry]]) – Boundary curves of each layer on the wall curves.

  • on_rad_zero (List[Bool]) – Information for each layer, telling if the radius is on zero.

  • layerParallel (List[analyticGeometry]) – Inner boundary curves of the layers, used for the multiple bounded volume.

This method takes a list of wall curves layerCurve (either hub or shroud) together with the inlet and outlet curves inOutCurves as input.

Furthermore, the layer thickness layer_thickness and the list of support point positions supports are passed to the method. supports defines both the number of support points and their positions on each wall curve, for the creation of the third bounding curves, in the method layerCurve().

The label lab is used to assign names to the generated geometries.

The following figure shows the hub curves of the draft tube example stored in layerCurve (black) together with their numbering in the list. layerCurve[2] and the inlet curve inOutCurves[0] (red) are trimmed.

_images/createLayerBounds0.png

Fig. 65 Hub curves of the draft tube cone example in layerCurve (black) and the inlet curve in boundsGlob[0] (red).

In a first loop checks are performed, which of the curves in layerCurve get a layer region. This is only the case for curves which are not located on a radius of zero. The following figure shows the activity diagram of the first loop.

_images/createLayerBounds_activity0.png

Fig. 66 Activity diagram of the first loop in createLayerBounds().

Initialize Lists

A copy of inOutCurves is created and assigned to boundsGlob. This list contains the global boundary curves that form part of the boundary curves of the first and last layer faces.

The layer faces are constructed from four boundary curves. The following empty lists are prepared to store the layer boundary curves. The numbering first, second, third, and fourth corresponds to the definition given in the constructor documentation __init__().

  • layerStreamOrtho: List containing the second and fourth boundary curves, which extend from the wall into the flow domain.

  • layerParallel: List containing the third boundary curves, which extend approximately parallel to the wall.

  • returnBounds: List containing all boundary curves of the layer faces.

  • on_rad_zero: List tracking which curves in layerCurve are located on a radius of zero.

Iterate over Curves

In the first loop, a check is performed to determine which curves in layerCurve are located on a radius of zero. This check is carried out using the method rz_xyz(), which takes a point as input and performs a coordinate transformation from Cartesian coordinates into a cylindrical coordinate system defined by the origin origin_ and the rotation axis rotAxis_.

The method returns the radius and axial position of the point in cylindrical coordinates.

The check is performed on the radii of the start and end points of each curve using the method inXYZTolerance of the class analyticGeometry. This method returns True if the radius lies within the tolerance of zero. Two cases are handeled.

The curve is on a radius of zero:

onRotAxis_0 and onRotAxis_1

If the check returns True for both points, the curve is considered to lie on a radius of zero. In this case, the outlet curve in boundsGlob[-1] is replaced by the current curve. This replacement is necessary because the curve forms the second boundary curve of the last layer face on the corresponding wall.

The last entry of the list on_rad_zero is then set to True.

A curve extending from the layer thickness position to the end of the curve located on the rotation axis is created and assigned to the variable unstructOnRotAxis. This curve is required as a boundary curve of the unstructured region.

The curve located on the radius of zero is then removed from the list of layer curves, and the loop is terminated.

The curve is not on a radius of zero:

else

If the curve is not located on a radius of zero, the list on_rad_zero is extended with a value of False.

The following figure shows the hub curves together with their assigned Boolean values in on_rad_zero and the global layer boundaries stored in boundsGlob.

_images/createLayerBounds1.png

Fig. 67 Hub curves of the draft tube cone example together with their assigned Boolean values in the on_rad_zero list. The curves that are part of the global layer boundaries are shown in red.

In a second loop, curves with a continuous transition at their connection points are combined within a specified tolerance range.

The following figure shows the activity diagram of this loop.

_images/createLayerBounds_activity1.png

Fig. 68 Activity diagram of the second loop in createLayerBounds().

Itreate over Curves

In the loop, the tangent vectors, at the transition points, of two consecutive curves v0 and v1 are calculated. This transition point corresponds to the end point of v0 and the start point of v1.

Using the angle between the tangent vectors v0_firstDer and v1_firstDer, a continuity condition is_steady is formulated. This condition evaluates to True if the angular deviation between the two curves is less than or equal to two degrees.

If the condition evaluates to True, the curves are combined and stored in the variable current_curve, which is then used in the next iteration. Furthermore, the corresponding flag in the on_rad_zero list is removed.

If the condition evaluates to False, the current curve is appended to the list speCurve and the consecutive curve is assigned to current_curve.

After the loop has finished, all curves for which layer faces are generated are stored in speCurve.

The boundary curves for the layers are generated in the third loop, which iterates over speCurve. The following figure shows the activity diagram of this loop.

_images/createLayerBounds_activity2.png

Fig. 69 Activity diagram of the third loop in createLayerBounds(). Orange action blocks correspond to the creation of the second and fourth boundary curves, while blue action blocks correspond to the creation of the third boundary curves.

Three different conditions may apply for each curve within the loop.

  1. The first layer face along the wall

    i == 0
    

    The fourth boundary curve of the first layer face is formed by the inlet curve stored in boundsGlob[0]. This boundary curve is created by trimming the inlet curve from its shared point with the layer curve speCurve[i] to the layer thickness specified by layer_thickness.

    The connection point must correspond to the start of the parameter span (0 %) of the global boundary curve. Depending on whether hub or shroud wall layers are created, this is not always the case.

    To ensure that both curves share the same start point, the distance between their start points is computed and checked against the geometric tolerance. The distance is calculated using the method distance of the dtOO class dtLinearAlgebra. The tolerance check is performed using analyticGeometry.inXYZTolerance.

    If the distance exceeds the tolerance, the global boundary curve is reversed.

    The resulting trimmed curve is appended to the list layerStreamOrtho.

  2. The last layer face along the wall

    i == len(speCurve)
    

    The second boundary curve of the last layer face is formed by the second global boundary boundsGlob[-1]. This boundary can either be on the the outlet curve of the layered region or on a curve located on the radius of zero.

    The layer boundary is created similarly to case 1. In this case, the distance between the end point of the wall curve speCurve[i-1] and the start point of the global boundary curve is used to orient the global boundary curve correctly.

    The third layer boundary curve, extending approximately parallel to the wall, is created using the method layerCurve(). The resulting curve is appended to the list layerParallel.

    The list newLayer is created. This list contains the four boundary curves of the last layer face.

  3. Regular layer face

    else
    

    In this case, the wall curve in each iteration is speCurve[i-1]. For each wall curve, the second and third layer boundary curves are created. The second boundary curve is generated directly within the loop, while the third boundary curve is created using the method layerCurve(). The fourth boundary curve is taken from the second boundary curve generated in the previous iteration.

    Get Cuves v0 and v1

    The second layer boundary curve is constructed so it extends in the mean normal direction \(\mathbf{v_{mean}}\) between the curves speCurve[i-1] and speCurve[i] at their shared point \(P_0\). The curves are assigned to the variables v0 and v1.

    Caluclate the direction of the second boundary curve

    The mean normal direction is calculated as follows:

    \[\mathbf{v_{mean}} = \frac{\mathbf{n_0} + \mathbf{n_1}}{\|\mathbf{n_0} + \mathbf{n_1}\|}\]

    The normal directions of the curves (\(\mathbf{n_0}\) and \(\mathbf{n_1}\)) at the shared point are calculated as the cross products of the normal axis of the channel cross section normalAxis_ (\(\mathbf{n_{global}}\)) and the tangential directions of the curves at the shared point (\(\mathbf{t_0}\) and \(\mathbf{t_1}\)).

    \[\mathbf{n} = \frac{\mathbf{t} \times \mathbf{n_{global}}}{\|\mathbf{t} \times \mathbf{n_{global}}\|}\]

    The resulting vector \(\mathbf{v_{mean}}\) is stored in the variable layerVec.

    The following figure illustrates the generation of the second layer boundary curves.

    _images/createLayerBounds2.png

    Fig. 70 Creation of the second and fourth layer boundary curves (blue) extending from the wall curves into the flow domain.

    Calculate a Vector Pointing Into the Center

    The vector insideVec is created by subtracting the global center point speCenter_ from the shared point of the two wall curves. This results in a vector pointing from the shared point toward the interior of the flow domain.

    Calculate the Normal Vector, Check the Direction and Calculate the Length

    The normal vector normalVec of curve v0 at the shared point is defined with the length specified with thickness (\(t_{Layer}\)). By calculating the dot product of the vectors normalVec and insideVec, it can be determined whether normalVec points toward the interior or exterior of the flow domain. If the dot product is negative, the direction of normalVec is reversed by multiplying it with -1.

    The length of the layer boundary curve is calculated from the length of normalVec and the angle between normalVec and layerVec (see Fig. 70).

    Create the Layer Boundary

    The layer boundary curve is constructed between the points \(P_0\) and \(P_1\). The point \(P_1\) is calculated from the point \(P_0\) by adding the direction vector layerVec (\(\mathbf{v_{mean}}\)) multiplied by the required layer thickness.

    \[P_1 = P_0 + \mathbf{v_{mean}} * t_{Layer} / cos(\lambda)\]

    The resulting curve is stored in the list layerStreamOrtho.

    Create third Boundary Curve

    The third boundary curve is generated using the method layerCurve(). The method takes the list layerStreamOrtho, the current wall curve v0, and the current iteration index i as input arguments.

    The generation of the curve is controlled by the layer thickness thickness and the support point positions defined in supports. The returned curve ext is stored in the list layerParallel.

    The creation of the third layer boundary curve is illustrated in the following figure.

    _images/createLayerBounds3.png

    Fig. 71 Creation of the third layer boundary curve (blue) extending into the flow domain.

    Append List of Boundary Curves

    The boundary curves of the current layer face are stored in the list newLayer. In this list, the boundary curves are ordered according to the numbering convention used throughout this documentation, with the wall curve v0 forming the first entry.

    The second entry contains the curve in layerStreamOrtho generated in the current iteration. The fourth entry contains the curve in layerStreamOrtho generated in the previous iteration. The third entry contains the curve stored in layerParallel.

    The following figure shows all boundary curves surrounding the layer faces together with their orientations. For the first layer face, the numbering of the boundary curves is shown explicitly.

    _images/createLayerBounds4.png

    Fig. 72 All layer boundary curves surrounding the layer face (blue).

    The list newLayer is appended to the list returnBounds.

After the loop has concluded, the curve unstructOnRotAxis is appended to the list layerParallel if it exists.

The method returns the lists returnBounds, on_rad_zero, and layerParallel.

layerCurve(layerStreamOrtho, i, curve, thickness, supports, lab)[source]

Create third boundary curve extending paralell to the wall.

This method:

  • Creates third layer bounding curve from the end points of the second and third bounding curves and support points.

Parameters:
  • layerStreamOrtho (List[analyticGeometry]) – Boundary curves of the layer faces orthogonal to the wall curve.

  • i (int) – Iterator, iD of the wall curve.

  • curve (analyticGeometry) – Wall curve

  • thickness (float) – Layer thickness

  • supports (List[float]) – List with positions of support points in percent along wall curve

  • lab (string) – label

Returns:

ext – Created layer curve inside the layer region

Return type:

analyticGeometry

The inputs to this method are the list of second and fourth layer boundary curves layerStreamOrtho, the wall curve curve for which the third boundary curve is created, and the iteration index i of this curve within the loop in createLayerBounds().

The generation of the boundary curve is controlled by the layer thickness thickness and the number and positions of support points specified in supports.

The following figure illustrates the creation of the third layer boundary curve.

_images/layerCurve.png

Fig. 73 Creation of the third layer boundary curve (blue) using the method layerCurve().

Get second and fourth Boundary Curves

The iteration index i is used to retrieve the second and fourth boundary curves of the current layer from layerStreamOrtho. These curves are assigned to the variables bound0 and bound1.

Calculate Offset Direction

Using the method calculateNormalAxis(), the center point of the bounding box surrounding the two boundary curves and the wall curve is calculated and stored in layerCenter.

This point is used to define the vector insideVec, which points from the point located at 50 % of the parameter range of curve toward the interior of the layer face.

The vector normalVec is created to point in the normal direction of the wall curve at 50 % of its parameter span. It is calculated as the cross product of the tangent vector of the curve at this point and the global normal axis normalAxis_.

Using the dot product of normalVec and insideVec, the offset direction from the wall curve is determined through the variable direction, which is assigned either 1 or -1.

Create Boundary Curve

A container object of the dtOO class vectorDtPoint3 is created. The end point of the fourth layer boundary curve bound0 is appended to this container.

By iterating over supports, the support points \(P_s\) are generated. Each entry in supports contains a floating point value defining a relative parameter position along the wall curve.

For each support value, a base point \(P_0\) is calculated on the wall curve.

The support point is then created by offsetting \(P_0\) in the normal direction of the wall curve at \(P_0\).

The normal direction is defined as the cross product between the tangent direction \(\mathbf{t}\) at \(P_0\) and the global normal axis normalAxis_ (\(\mathbf{n_{global}}\)).

The offset length is prescribed by layer_thickness (\(t_{Layer}\)). The value of direction (\(k\)) ensures that the support points are generated inside the flow domain.

The following equation describes the calculation of a support point:

\[P_s = P_0 + \frac{\mathbf{t} \times \mathbf{n_{global}}}{\|\mathbf{t} \times \mathbf{n_{global}}\|} * t_{Layer} * k\]

The generated support points are appended to the point container.

After all support points have been generated, the end point of the second layer boundary curve bound1 is appended to the container.

The third layer boundary curve is then created as a bSplineCurve_pointConstructOCC object using the points stored in the container.

The method returns the generated curve.

rz_xyz(pp: dtOOPythonSWIG.dtPoint3) dtOOPythonSWIG.dtPoint2[source]

Transform a point in cartesian coordinates into cylindric coordinates.

This method:

  • Transforms a point in the xyz-coordinates into cylindric coordinates.

  • Returns radius and z-position of the point.

Parameters:

pp (dtPoint3) – Point in xyz-coordinates.

Returns:

  • dtPoint2 – dtPoint2 object containing the radius and z-position of pp

  • The point pp in carthesian coordinates is reparametrized in cylindirc

  • coordinates based on the origin point origin_ and the rotational vector

  • rotVector_.

  • Returns the radius rr and the z-coordinate zz in a dtPoint2

  • object.

static calculateNormalAxis(curves)[source]

Calculate the bounding box and normal axis of curves in one plane.

This method:

  • Creates a bounding box around the curves.

  • Calculates the normal axis on the bounding box.

  • Calculates the center of the bounding box.

  • Returns normal axis, center and bounding box.

Parameters:

curves (List[analyticGeometry]) – List of curves.

Returns:

  • normalAxis (dtVector3) – Normal axis of the bounding box.

  • bbCenter (dtPoint3) – Center point of the bounding box.

  • bb (pairDtPoint3) – Bounding box points.

build() None[source]

Plot the instantiated geometries in paraview if debug is enabeled.

Parameters:

None

Return type:

None

This method allows the instantiated geometries to be plotted in ParaView, by adding them to the analytic geometry container. If the code is run in paraview, the geometries can be found with the FindAndShow method.

getLayerList(nSlices: int) List[List[List[dtOOPythonSWIG.analyticGeometry] | List[bool]]][source]

Create the layer volumes and return the layer data.

This method:

  • Rotates the hub and shroud layer faces to create volumes.

  • Returns the generated layer data in structured lists.

Parameters:

nSlices (int) – Number of rotationally periodic slices.

Returns:

layerList – List containing the generated layer volumes and information about whether a layer is located on a radius of zero.

The entries correspond to the following values:

  • layerList[0]: Hub layers

  • layerList[1]: Shroud layers

  • layerList[i][0]: List of layer volumes

  • layerList[i][1]: List of Boolean values indicating whether the corresponding layer is located on a radius of zero

Return type:

List[List[List[analyticGeometry] | List[bool]]]

The layer faces stored in hubLayers_ and shroudLayers_ are rotated around rotVector_. The rotation angle is defined by the number of slices as:

\[{360^\circ}/{n_{Slices}}\]

The generated layer volumes are stored in the lists hubLayer3d and shroudLayer3d.

The following figure shows the resulting volumes of the draft tube cone.

_images/layers3d.png

Fig. 74 Volumes of the draft tube cone. Layer faces (blue), inlet (red), and outlet (orange).

The hub and shroud layer volumes together with the lists hubRadZero_ and shroudRadZero_ are returned in the following format:

layerList = List[
    List[
        List[analyticGeometry],
        List[bool]
    ]
]

The entries correspond to the following values:

  • layerList[0]: Hub layers

  • layerList[1]: Shroud layers

  • layerList[i][0]: List of layer volumes

  • layerList[i][1]: List of Boolean values indicating whether the corresponding layer is located on a radius of zero

getUnstructuredRegion(nSlices: int) Tuple[dtOOPythonSWIG.analyticGeometry, List[dtOOPythonSWIG.analyticGeometry]][source]

Create and return the unstructured region together with its bounding surfaces.

This method:

  • Creates the boundary surfaces of the unstructured region that connect to the layer volumes.

  • Creates the periodic boundary surfaces of the unstructured region as multiple bounded surfaces.

  • Creates the unstructured region as a multiple bounded volume.

  • Returns the multiple bounded volume together with its boundary surfaces.

Parameters:

nSlices (int) – Number of rotationally periodic slices.

Returns:

  • multBoundedVol (multipleBoundedVolume) – Unstructured region located between the hub and shroud layers.

  • boundSurf (vectorHandlingAnalyticGeometry) – Vector handler containing the boundary surfaces of the multiple bounded volume.

The unstructured region is created as an object of the dtOO class multipleBoundedVolume. The multiple bounded volume is defined by its boundary surfaces.

Create Boundary Surfaces through the Rotation of Curves

The inlet and outlet surfaces, together with the surfaces connecting the multiple bounded volume to the layer volumes, are created from the curves stored in the vector handler unstructVH_.

The surfaces are generated using the dtOO class rectangularTrimmedSurface_curveRotateConstructOCC. This class creates surfaces by rotating curves around the rotation vector rotVector_ over the angle rotAngle defined as:

\[{360^\circ}/{n_{Slices}}\]

Conditional statements are used to assign labels to the generated surfaces. Due to the ordering of curves in unstructVH_, the first and last curves define the inlet and outlet surfaces of the unstructured region. These surfaces receive the labels interface_unstruct and outlet_unstruct.

The remaining surfaces connect the unstructured region to the layer regions and are labeled as para followed by their position in the vector handler.

Using the method degenerated of the dtOO class analyticSurface, a check is performed to determine whether any of the rotated surfaces are degenerated. Degenerated surfaces occur when the corresponding curve lies on a radius of zero.

Only non degenerated surfaces are appended to the vectorHandlingAnalyticGeometry object boundSurf.

The following figure shows the boundary surfaces created from the curves stored in unstructVH_.

_images/boundingSurfs.png

Fig. 75 Boundary surfaces of the multiple bounded volume with inlet (red), outlet (orange), and layer connection surfaces (blue). The periodic multiple bounded surfaces are not shown.

Create Periodic Faces as Multiple Boundes Surfaces

The periodic surfaces of the unstructured region slice are created as multiple bounded surfaces. These surfaces are generated using the dtOO class multipleBoundedSurface, which takes a set of boundary curves together with a surrounding bounding box as input.

The bounding box is created from the minimum and maximum vertices stored in speBb_. Based on these vertices, a bounding box m2d is generated for the first multiple bounded surface, extending 0.1 units beyond speBb_ in all directions.

The first periodic surface mbs1 is created from m2d and the boundary curves stored in unstructVH_ using the class multipleBoundedSurface. The surface is assigned the label periodicUnstruct_0 and appended to boundSurf.

To create the second periodic surface, a rotational transformation is applied to both the bounding box and the boundary curves.

For this purpose, a dtTransformer object is initialized. The transformation configuration is defined in the jsonPrimitive object cfg, where the rotation vector, origin, and rotation angle are set to rotVector_, origin_, and rotAngle, respectively.

The resulting rotation object is stored in rot.

By applying rot to m2d, the rotated bounding box m2d_rot is created. By iterating over unstructVH_ and applying the same rotational transformation, the rotated boundary curves are generated and stored in unstructVH_rot.

The second multiple bounded surface is created analogously to the first one using m2d_rot and unstructVH_rot. This surface is assigned the label periodicUnstruct_1 and appended to boundSurf.

Create Unstructured Region as Multiple Bounded Volume

The unstructured region itself is finally created using the class multipleBoundedVolume. Its bounding volume is defined as an infinityMap3dTo3d object, while the vector handler boundSurf is provided as the collection of boundary surfaces.

Returns

The method returns both the multiple bounded volume and the vector handler boundSurf containing all generated boundary surfaces.

class dtOOPythonApp.builder.map3dTo3dGmsh_gridFromLayers.map3dTo3dGmsh_gridFromLayers(mv: dtOOPythonSWIG.analyticGeometry, bs: List[dtOOPythonSWIG.analyticGeometry], label: str, layers: List[List[List[dtOOPythonSWIG.analyticGeometry] | List[bool]]], nElementsLayer: int, firstElement: float, elementSize_sw: float, elementSize_circ: float, charLengthMin: float = 0.05, charLengthMax: float = 0.1)[source]

Create mesh topology as map3dTo3dGmsh.

This class:

  • Creates a map3dTo3dGmsh topology object.

  • Adds the unstructured region to the topology.

  • Adds layer volumes to the topology.

  • Manages layer faces in the topology.

  • Applies mesh settings to the edges.

  • Applies gradings and mesh rules.

  • Renames faces.

  • Applies mesh settings to topology.

label_

Label.

Type:

str

layerList_

Layer lists for hub and shroud with 3d regions and bool list.

Type:

List[List[List[analyticGeometry] | List[bool]]]

nLayers_

Number of elements normal to the walls in the layer volumes.

Type:

int

firstElement_

Size of first element on the walls.

Type:

float

elementSizeSw_

Element size in streamwise direction.

Type:

float

elementSizeCirc_

Element size in circumferential direction.

Type:

float

unstructured_

Multi bounded volume of the unstructured region.

Type:

analyticGeometry

unstructuredSurfaces_

Bounding faces of the mult bounded volume.

Type:

List[analyticGeometry]

map3dTo3dGmshJson_

JSON structure for map3dTo3dGmsh.

Type:

jsonPrimitive

Examples

None

The class is used to create the mesh topology of a flow channel consisting of five- or six-sided layer volumes on the hub and shroud walls and a multiple bounded volume inside the flow domain, connecting to the layer volumes.

The layer volumes are meshed transfinite and the multiple bounded volume is meshed unstructured.

In the constructor, the input parameters are instantiated. The multiple bounded volume is instantiated as unstructured_. The list with its bounding surfaces is instantiated as unstructuredSurfaces_.

The layer list is instantiated as layerList. Its structure is as follows:

layerList = List[
    List[
        List[analyticGeometry],
        List[bool]
    ]
]

The entries correspond to the following values:

  • layerList[0]: Hub layers

  • layerList[1]: Shroud layers

  • layerList[i][0]: List of layer volumes.

  • layerList[i][1]: List of Boolean values indicating whether the corresponding layer is located on a radius of zero.

The layers are meshed with a grading extending from the wall faces into the flow domain. The number of elements in the grading is defined as nLayers_. The size of the first element on the wall is specified with firstElement_.

The number of elements in streamwise and circumferential direction is set with elementSizeSw_ and elementSizeCirc_. These parameters correspond to maximal element sizes on the hub and shroud walls.

The size of the elements in the unstructured region is set with the minimal and maximal characteristic lengths charLengthMin and charLengthMax.

The topology settings are defined with a jsonPrimitive object instantiated as map3dTo3dGmshJson_. Here, the characteristic lengths of the unstructured mesh elements are applied.

With the build() method, the mesh settings are applied to the topology. The methods detectFirstAndSecond() and getCommonEdgesByPhysicalFaces() are used to organize the faces and edges of the layer volumes.

The mesh topology is appended to the bounded volume container at the end of the build() method.

build() None[source]

Build part.

This method is the main method of the class.

  • Creates a map3dTo3dGmsh topology object.

  • Adds the unstructured region to the topology.

  • Adds layer volumes to the topology.

  • Manages layer faces in the topology.

  • Applies mesh settings to the edges.

  • Applies gradings and mesh rules.

  • Renames faces.

  • Applies mesh settings to the topology.

Parameters:

None

Return type:

None

The topology object m3Gmsh is created with the settings in map3dTo3dGmsh_.

The labeled vector handling objects aG and aF are created to handle analytic geometries and functions in this method.

The bounding faces of the unstructured region in unstructuredSurfaces_ are labeled in the getter method getUnstructuredRegion of the class analyticGeometry_layerRegion. The labels are as follows:

  • "periodicUnstruct_0" : First periodic surface

  • "periodicUnstruct_1" : Second periodic surface

  • "interface_unstruct" : Inlet of the flow domain’s unstructured region

  • "outlet_unstruct" : Outlet of the flow domain’s unstructured region

  • "para" + str(i) : Connecting faces to the layer volumes

The bounding faces that are not labeled with the string para are pushed into aG by iterating over the list.

Fig. 76 shows the face outlet_unstruct in orange and interface_unstruct in red. The faces labeled with para are equal to the wall parallel faces of the layer volumes (purple). The periodic faces of the unstructured region are not shown.

_images/layersMeshFaces.png

Fig. 76 Faces in the layered flow domain.

The multiple bounded volume of the unstructured region is added to the topology and allocated in unstrct3d.

In a nested loop over layerList_, the layer volumes of the hub and shroud are added to the topology. The faces of the layers are added to aG. The activities inside the loop are illustrated in the following figure.

_images/gridLayers_activity0.png

Fig. 77 Activities for adding the layer volumes to the topology.

Loop over Hub and Shroud

i_hs in range(len(layerList_))

The first level loop iterates over the hub and shroud data in layerList_. According to the iterator i_hs, the label variable is set to the strings hub or shroud.

Loop over Layers

i_l in range(len(layerList[i_hs][0]))

The second level loop iterates over the hub or shroud layers in layerList_[i_hs]. The iterator is i_l.

With the method detectFirstAndSecond(), the faces of each layer are identified. The method takes the layer volume as a map3dTo3d object and the parameter direction as an integer input. By calling the function once for each parameter direction, all faces of the layer volume are returned. The returned faces are allocated to the following parameters:

  • ortho0 and ortho1 : Faces orthogonal to the wall (Fig. 76 dark blue)

  • periodic0 and periodic1 : Periodic faces on the flow domain segment (Fig. 76 light blue (periodic0 not shown))

  • channel : Wall faces on hub and shroud (Fig. 76 green)

  • parallel : Faces extending parallel to the wall (Fig. 76 purple)

Here, ortho0 is the upstream face of each layer volume and ortho1 is the downstream face. The faces ortho0 and ortho1 are labeled as follows:

  • ortho0 : "ortho_"+label+str(i_l)

  • ortho1 : "ortho_"+label+str(i_l)+1

The layer volumes are added to the topology m3dGmsh and receive the region ID rID.

The labeling of the other faces depends on whether the layer volume is five- or six-sided. A layer is five-sided if it is located on the radius of zero. This is checked with the list in layerList_[i_hs][1]. This differentiation is necessary, because different meshing strategies have to be applied.

The layer is six sided:

The layer is six sided when layerList_[i_hs][1][i_l] == False applies. In this case, the naming of the faces is as follows:

  • periodic1 : "periodic0_"+label+str(i_l)

  • periodic0 : "periodic1_"+label+str(i_l)

  • channel : "channel_"+label+str(i_l)

  • parallel : "parallel_"+label+str(i_l)

The mesh settings are set to transfinite and recursive.

The layer is five sided:

If the layer is five sided, the string 5s is added to the face names:

  • periodic1 : "periodic05s_"+label+str(i_l)

  • periodic0 : "periodic15s_"+label+str(i_l)

  • channel : "channel5s_"+label+str(i_l)

  • parallel : "parallel5s_"+label+str(i_l)

In this case, the layer cannot be meshed completely transfinite recursive. Its mesh settings have to be applied directly to the edges.

The labeled faces are pushed into aG. ortho0 is pushed into aG in every iteration. ortho1 is only pushed in the last iteration i_l == len(layerList_[i_hs][0])-1 if the last layer is not on a radius of zero layerList_[i_hs][1][i_l] == False.

Apply Mesh Sizing

With an observer of the class bVOAnalyticGeometryToFace, the labeled faces in aG are added to the topology m3dGmsh.

The mesh settings are applied to the edges of the layer volumes. The following figure shows the edges on which mesh settings are applied.

_images/layersMeshSetting.png

Fig. 78 Edges in the flow domain on which mesh settings are applied. channelToParallelLines (green), swLines (magenta), and circLines (blue). On grey edges no mesh settings are applied.

Apply Gradings on the Walls

The grading on the hub and shroud layers is set on the edges extending from the channel to parallel faces. The edges are stored in channelToParallelLines. By iterating over these edges, the grading is applied with the method setGrading. The first input of this method is the direction of the grading, and the second one is an identifier for the grading function. The number of elements is set to nLayers_.

While iterating over the edges, the sum of their edge lengths is calculated. Using the number of edges in channelToParallelLines, the mean edge length is calculated. By dividing this value by nLayers_, the mesh size meshSizeAtPoints at the connection face between the layer and the unstructured volume is estimated.

To set the number of elements on the edges in the streamwise (Fig. 78 (magenta)) and circumferential directions (Fig. 78 (blue)), an iteration over the layer list is performed. The following figure illustrates the processes in an activity diagram.

_images/gridLayers_activity1.png

Fig. 79 Activities for the mesh settings in the streamwise and circumferential directions. Pink action blocks correspond to operations on the streamwise edges, blue action blocks correspond to operations on circumferential edges.

Prepare List

The list lChannel_circ = [0,0] is prepared. The two values in this list are used in the loop to store the maximum lengths of the circumferential edges on the hub and shroud walls.

Loop over Hub And Shroud

i_hs in range(len(layerList_))

Similarly to the loop in Fig. 77, a nested loop over the two levels of layerList_ is performed. The first level loop iterates over the hub and shroud layers. The string value of label is set accordingly.

Loop over Layers

i_l in range(len(layerList_[i_hs][0]))

The second level loop iterates over the specific layers in the hub or shroud set.

Edges in Streamwise Direction

The length lChannel_sw of the wall edge of the current layer in the streamwise direction is calculated. The edge is returned as the common edge between the channel and the periodic0 faces with the method getCommonEdgesByPhysicalFaces().

With this length, the number of elements nE is calculated by dividing the length through the element size elementSizeSW_. By rounding nE to the next highest integer value, it is ensured that elementSizeSW_ is the maximal element size on the wall face in the streamwise direction.

The handling of six- and five-sided layers differs here. This is checked with the value in layerList_[i_hs][1][i_l].

Layer is six sided

layerList_[i_hs][1][i_l] == False

The streamwise edges (Fig. 78 (magenta)) extending between the ortho faces of the layer are returned by the method getDtGmshEdgeTagListByFromToPhysical of the Gmsh model.

Layer is five sided

layerList_[i_hs][1][i_l] == True

The four edges are returned by the method getCommonEdgesByPhysicalFaces(). Here, the edges of the channel or the parallel faces are compared with the periodic0 and periodic1 faces. The common edges of these faces are stored in the list swLines.

The meshing of the four sided faces ortho, periodic0, and periodic1 of the layer is set to transfinite with a recombine.

Apply Mesh Settings on Edges in Streamwise Direction

By iterating over swLines, the number of elements nE is set on the edges.

Edges in Cricumferential Direction

The length l_ortho of the upstream circumferential edge of the layer volume is returned. If the length is greater than the value stored in lChannel_circ, the value replaces the current entry in the list.

If the iteration is at the last layer and the layer is not located on a radius of zero, the length l_ortho is calculated and compared for the downstream circumferential edge.

Apply Mesh Settings on Edges in Circumferential Direction

After the second level loop for a layer region has concluded, the number of elements according to the maximal edge length is set on the circumferential edges.

The number of elements nE is calculated with the maximal edge length lChannel_circ[i_hs] and the element size elementSizeCirc_. By rounding the value of nE to the next higher integer, it is ensured that the specified element size represents a maximum size along the circumferential direction of the layer wall.

The circumferential edges circLines (Fig. 78 (blue)) extend between the periodic faces. By iterating over circLines, the number of elements is set.

Create Observers

The observer bVOSetPrescribedMeshSizeAtPoints is applied. This observer is used to set the mesh size of the unstructured region at the connection points with the layer volumes to the value calculated in meshSizeAtPoints.

The object of the grading function theRef is created with the dtOO class scaTanhGradingOneDCompound. It is labeled aF_grading and pushed into aF.

An observer of the class bVOSetPrescribedElementSize is created. This observer combines the analytic grading function specified in theRef with the _type identifier and the size of the first element in the grading firstElement_.

The mesh rules are applied with the observer bVOMeshRule. The rules dtMeshFreeGradingGEdge, dtMeshGFace, and dtMeshGRegion are used for all edges, surfaces, and volumes.

The observer of the class bVOFaceToPatchRule is used to rename the faces. This is done so that the naming of the face regions is consistent with the setup rules of the simulation.

The faces are renamed with the label label_ and a string for the region. The following names are assigned to the faces:

  • label_ + '_hub' : hub walls

  • label_ + '_shroud' : shroud walls

  • label_ + '_inlet' : inlet surfaces

  • label_ + '_outlet' : outlet surfaces

  • label_ + '_periodic0' : first periodic segment faces

  • label_ + '_periodic1' : second periodic segment faces

With an if-condition, it is checked whether the last hub wall extends to a radius of zero. If this is the case (see Fig. 76), the hub layer regions are not part of the outlet.

If the last hub wall is not on zero, the last ortho face of the hub regions is added as an outlet face.

With the observer of the class bVOWriteMSH, the settings for the created .msh file are defined.

The observer bVOOrientCellVolumes is applied with the setting "_positive" : true.

Returns

The method appendBoundedVolume is used to append the topology object m3dGmsh to the container objects in the main class.

A mesh resulting from this topology is shown in the following figure.

_images/layersMesh.png

Fig. 80 Mesh of a draft tube cone resulting from the described topology.

detectFirstAndSecond(channel: dtOOPythonSWIG.map3dTo3d, direction: int) Tuple[dtOOPythonSWIG.map2dTo3d, dtOOPythonSWIG.map2dTo3d][source]

Detect first and second faces in a volume’s parameter direction.

This method returns the faces of a map3dTo3d object at 0 and 100 percent of the u-, v-, or w-paramter.

Parameters:
  • channel (map3dTo3d) – Volume.

  • direction (int) –

    Direction in uvw

    • 1 -> U

    • 2 -> V

    • 3 -> W

Returns:

  • first (map2dTo3d) – first segment in direction

  • second (map2dTo3d) – second segment in direction

getCommonEdgesByPhysicalFaces(m3dGmsh, face0: str, face1: str)[source]

Return the common edges between two faces.

This method:

  • Iterates over the edges on both faces.

  • Finds faces with the same tag.

  • Returns them in a list.

Parameters:
  • channel (map3dTo3d) – Volume.

  • face0 (str) – Pyhsical name of first face

  • face1 (str) – Pyhsical name of second face

Returns:

commonEdges – List of edges on both faces

Return type:

List[dtGmshEdge]