Skip to content
Snippets Groups Projects
Verified Commit 13ed4609 authored by Paul Dechamps's avatar Paul Dechamps :speech_balloon:
Browse files

(feat) Added abstract class for interpolators

parent 26bac6aa
No related branches found
No related tags found
1 merge request!1BLASTER v1.0
Pipeline #51033 passed
...@@ -70,7 +70,7 @@ class SolversInterface: ...@@ -70,7 +70,7 @@ class SolversInterface:
else: else:
raise RuntimeError('Incorrect interpolator specified in config.') raise RuntimeError('Incorrect interpolator specified in config.')
self.interpolator = interp(self.cfg, self.getnDim()) self.interpolator = interp(self.getnDim(), **self.cfg)
# Initialize transfer quantities # Initialize transfer quantities
self.deltaStarExt = [[np.zeros(0) for iReg in range(3)]\ self.deltaStarExt = [[np.zeros(0) for iReg in range(3)]\
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2024 University of Liège
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Abstract interpolator class
# Paul Dechamps
class Interpolator:
"""
Abstract interpolator class
Attributes:
----------
ndim : int
Number of dimensions (must be 2 or 3).
"""
def __init__(self, _ndim):
"""
Initialize the Interpolator.
Parameters:
----------
ndim : int
Number of dimensions (must be 2 or 3).
"""
if _ndim != 2 and _ndim != 3:
raise ValueError('Number of dimensions must be 2 or 3 but {} was given'.format(ndim))
self.ndim = _ndim
def inviscidToViscous(self, iDict, vDict):
"""
Interpolate data from the inviscid mesh to the viscous mesh.
Parameters:
----------
iDict : list
List blDataStructure objects for the inviscid part.
vDict : list
List blDataStructure objects for the viscous part.
"""
raise NotImplementedError('inviscidToViscous method not implemented')
def viscousToInviscid(self, iDict, vDict):
"""
Interpolate data from the viscous mesh to the inviscid mesh.
Parameters:
----------
iDict : list
List blDataStructure objects for the inviscid part.
vDict : list
List blDataStructure objects for the viscous part.
"""
raise NotImplementedError('viscousToInviscid method not implemented')
import numpy as np # Copyright 2024 University of Liège
class MatchingInterpolator: #
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Matching interpolator class
# Paul Dechamps
from blast.interfaces.interpolators.blInterpolator import Interpolator
class MatchingInterpolator(Interpolator):
""" """
Matching Interpolator for inviscid and viscous data. Matching Interpolator for inviscid and viscous data.
Attributes: Attributes:
---------- ----------
cfg : dict _sections : list
Configuration dictionary. List of boundary layers sections.
nDim : int
Number of dimensions.
""" """
def __init__(self, cfg, ndim): def __init__(self, ndim, **kwargs):
""" """
Initialize the MatchingInterpolator. Initialize the MatchingInterpolator.
Parameters: Parameters:
---------- ----------
_cfg : dict ndim : int
Configuration dictionary.
_nDim : int
Number of dimensions. Number of dimensions.
kwargs : dict
Optional arguments.
Optional arguments:
-------------------
sections : list
List of sections for 3D cases.
""" """
self._cfg = cfg super().__init__(ndim)
self._ndim = ndim self._sections = kwargs.get('sections')
if self.ndim == 2 and len(self._sections) > 1:
raise RuntimeError('Multiple sections are not supported in 2D')
def inviscidToViscous(self, iDict, vDict): def inviscidToViscous(self, iDict, vDict):
""" """
...@@ -35,11 +59,11 @@ class MatchingInterpolator: ...@@ -35,11 +59,11 @@ class MatchingInterpolator:
vDict : dict vDict : dict
Viscous data dictionary. Viscous data dictionary.
""" """
if self._ndim == 2: if self.ndim == 2:
for iReg in range(len(iDict)): for iReg in range(len(iDict)):
vDict[0][iReg].updateVars(iDict[iReg].V, iDict[iReg].M, iDict[iReg].Rho) vDict[0][iReg].updateVars(iDict[iReg].V, iDict[iReg].M, iDict[iReg].Rho)
elif self._ndim == 3: elif self.ndim == 3:
for iSec, ysec in enumerate(self._cfg['sections']): for iSec, ysec in enumerate(self._sections):
for iReg in range(2): for iReg in range(2):
print(iDict[iReg].nodesCoord[iDict[iReg].nodesCoord[:,1] == ysec]) print(iDict[iReg].nodesCoord[iDict[iReg].nodesCoord[:,1] == ysec])
print(iDict[iReg].V[iDict[iReg].nodesCoord[:,1] == ysec]) print(iDict[iReg].V[iDict[iReg].nodesCoord[:,1] == ysec])
...@@ -56,8 +80,8 @@ class MatchingInterpolator: ...@@ -56,8 +80,8 @@ class MatchingInterpolator:
vDict : dict vDict : dict
Viscous data dictionary. Viscous data dictionary.
""" """
if self._ndim == 2: if self.ndim == 2:
for iReg in range(2): for iReg in range(2):
iDict[iReg].blowingVel = vDict[0][iReg].blowingVel iDict[iReg].blowingVel = vDict[0][iReg].blowingVel
else: else:
raise RuntimeError('Incorrect number of dimensions', self._ndim) raise RuntimeError('Incorrect number of dimensions', self.ndim)
\ No newline at end of file \ No newline at end of file
# Copyright 2024 University of Liège
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# RBF interpolator class
# Paul Dechamps
from blast.interfaces.interpolators.blInterpolator import Interpolator
import numpy as np import numpy as np
from scipy.interpolate import RBFInterpolator from scipy.interpolate import RBFInterpolator
class RbfInterpolator: class RbfInterpolator(Interpolator):
""" """
Radial Basis Function (RBF) Interpolator for inviscid and viscous data. Radial Basis Function (RBF) Interpolator for inviscid and viscous data.
Attributes: Attributes:
---------- ----------
_cfg : dict _neighbors : int
Configuration dictionary. Number of neighbors to use for interpolation.
_ndim : int _rbftype : str
Number of dimensions (2 or 3). Type of RBF kernel to use.
_smoothing : float
Smoothing factor.
_degree : int
Degree of the polynomial kernel.
_sym : list
List of symmetry planes.
""" """
def __init__(self, cfg, ndim): def __init__(self, ndim, **kwargs):
""" """
Initialize the RbfInterpolator. Initialize the RbfInterpolator.
Parameters: Parameters:
---------- ----------
cfg : dict
Configuration dictionary.
ndim : int ndim : int
Number of dimensions (must be 2 or 3). Number of dimensions (must be 2 or 3).
kwargs : dict
Optional arguments.
Optional arguments:
-------------------
nneighbors : int
Number of neighbors to use for interpolation. Default is 10.
rbftype : str
Type of RBF kernel to use. Default is 'linear'.
smoothing : float
Smoothing factor. Default is 0.0.
degree : int
Degree of the polynomial kernel. Default is 0.
""" """
self._cfg = cfg super().__init__(ndim)
if ndim != 2 and ndim != 3: self._neighbors = kwargs.get('neighbors', 10)
raise ValueError('Number of dimensions must be 2 or 3 but {} was given'.format(ndim)) self._rbftype = kwargs.get('rbftype', 'linear')
self._ndim = ndim self._smoothing = kwargs.get('smoothing', 0.0)
self._degree = kwargs.get('degree', 0)
self._sym = kwargs.get('Sym', [])
def inviscidToViscous(self, iDict, vDict): def inviscidToViscous(self, iDict, vDict):
""" """
...@@ -48,9 +84,9 @@ class RbfInterpolator: ...@@ -48,9 +84,9 @@ class RbfInterpolator:
M = np.zeros(reg.nodesCoord.shape[0]) M = np.zeros(reg.nodesCoord.shape[0])
rho = np.zeros(reg.nodesCoord.shape[0]) rho = np.zeros(reg.nodesCoord.shape[0])
for iDim in range(3): for iDim in range(3):
v[:,iDim] = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self._ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].V[:,iDim], reg.nodesCoord[:,:(self._ndim if 'vAirfoil' in reg.name else 1)]) v[:,iDim] = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self.ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].V[:,iDim], reg.nodesCoord[:,:(self.ndim if 'vAirfoil' in reg.name else 1)])
M = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self._ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].M, reg.nodesCoord[:,:(self._ndim if 'vAirfoil' in reg.name else 1)]) M = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self.ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].M, reg.nodesCoord[:,:(self.ndim if 'vAirfoil' in reg.name else 1)])
rho = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self._ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].Rho, reg.nodesCoord[:,:(self._ndim if 'vAirfoil' in reg.name else 1)]) rho = self.__rbfToSection(iDict[iReg].nodesCoord[:,:(self.ndim if iDict[iReg].name == 'iWing' else 1)], iDict[iReg].Rho, reg.nodesCoord[:,:(self.ndim if 'vAirfoil' in reg.name else 1)])
vDict[iSec][iReg].updateVars(v, M, rho) vDict[iSec][iReg].updateVars(v, M, rho)
def viscousToInviscid(self, iDict, vDict): def viscousToInviscid(self, iDict, vDict):
...@@ -64,22 +100,21 @@ class RbfInterpolator: ...@@ -64,22 +100,21 @@ class RbfInterpolator:
vDict : dict vDict : dict
Viscous data dictionary. Viscous data dictionary.
""" """
if self._ndim == 2: if self.ndim == 2:
for iReg, reg in enumerate(iDict): for iReg, reg in enumerate(iDict):
iDict[iReg].blowingVel = self.__rbfToSection(vDict[0][iReg].elemsCoordTr[:,:(self._ndim-1 if 'vAirfoil' in reg.name else 1)], vDict[0][iReg].blowingVel, reg.elemsCoordTr[:,:(self._ndim-1 if reg.name == 'iWing' else 1)]) iDict[iReg].blowingVel = self.__rbfToSection(vDict[0][iReg].elemsCoordTr[:,:(self.ndim-1 if 'vAirfoil' in reg.name else 1)], vDict[0][iReg].blowingVel, reg.elemsCoordTr[:,:(self.ndim-1 if reg.name == 'iWing' else 1)])
elif self._ndim == 3: elif self.ndim == 3:
for iReg, reg in enumerate(iDict): for iReg, reg in enumerate(iDict):
viscElemsCoord = np.zeros((0,3)) viscElemsCoord = np.zeros((0,3))
viscBlowing = np.zeros(0) viscBlowing = np.zeros(0)
for iSec, sec in enumerate(vDict): for iSec, sec in enumerate(vDict):
viscElemsCoord = np.row_stack((viscElemsCoord, sec[iReg].elemsCoord[:,:3])) viscElemsCoord = np.row_stack((viscElemsCoord, sec[iReg].elemsCoord[:,:3]))
viscBlowing = np.concatenate((viscBlowing, sec[iReg].blowingVel)) viscBlowing = np.concatenate((viscBlowing, sec[iReg].blowingVel))
if 'Sym' in self._cfg: for s in self._sym:
for s in self._cfg['Sym']: dummy = viscElemsCoord.copy()
dummy = viscElemsCoord.copy() dummy[:,1] = (dummy[:,1] - s)*(-1) + s
dummy[:,1] = (dummy[:,1] - s)*(-1) + s viscElemsCoord = np.row_stack((viscElemsCoord, dummy))
viscElemsCoord = np.row_stack((viscElemsCoord, dummy)) viscBlowing = np.concatenate((viscBlowing, viscBlowing))
viscBlowing = np.concatenate((viscBlowing, viscBlowing))
reg.blowingVel = self.__rbfToSection(viscElemsCoord, viscBlowing, reg.elemsCoord[:,:3]) reg.blowingVel = self.__rbfToSection(viscElemsCoord, viscBlowing, reg.elemsCoord[:,:3])
def __rbfToSection(self, x, var, xs): def __rbfToSection(self, x, var, xs):
...@@ -103,5 +138,5 @@ class RbfInterpolator: ...@@ -103,5 +138,5 @@ class RbfInterpolator:
if np.all(var == var[0]): if np.all(var == var[0]):
varOut = RBFInterpolator(x, var, neighbors=1, kernel='linear', smoothing=0.0, degree=0)(xs) varOut = RBFInterpolator(x, var, neighbors=1, kernel='linear', smoothing=0.0, degree=0)(xs)
else: else:
varOut = RBFInterpolator(x, var, neighbors=self._cfg['neighbors'], kernel=self._cfg['rbftype'], smoothing=self._cfg['smoothing'], degree=self._cfg['degree'])(xs) varOut = RBFInterpolator(x, var, neighbors=self._neighbors, kernel=self._rbftype, smoothing=self._smoothing, degree=self._degree)(xs)
return varOut return varOut
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment