Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F63079207
generic_approximant.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, May 17, 15:35
Size
11 KB
Mime Type
text/x-python
Expires
Sun, May 19, 15:35 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
17729355
Attached To
R6746 RationalROMPy
generic_approximant.py
View Options
# Copyright (C) 2018 by the RROMPy authors
#
# This file is part of RROMPy.
#
# RROMPy is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RROMPy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with RROMPy. If not, see <http://www.gnu.org/licenses/>.
#
from
abc
import
abstractmethod
import
numpy
as
np
from
copy
import
copy
import
scipy.sparse.linalg
as
spla
from
rrompy.utilities.types
import
Np1D
,
Np2D
,
DictAny
,
N2FSExpr
from
rrompy.utilities.types
import
HFEng
,
HSEng
,
Tuple
,
List
from
rrompy.utilities
import
purgeDict
__all__
=
[
'GenericApproximant'
]
class
GenericApproximant
:
"""
ABSTRACT
ROM approximant computation for parametric problems.
Args:
HFEngine: HF problem solver. Should have members:
- energyNormMatrix: assemble sparse matrix (in CSC format)
associated to weighted H10 norm;
- problemData: list of HF problem data (excluding k);
- setProblemData: set HF problem data and k to prescribed values;
- getLSBlocks: get algebraic system blocks.
HSEngine: Hilbert space general purpose engine. Should have members:
- norm: compute Hilbert norm of expression represented as complex
numpy vector;
- plot: plot Hilbert expression represented as complex numpy vector.
mu0(optional): Default parameter. Defaults to 0.
approxParameters(optional): Dictionary containing values for main
parameters of approximant. Recognized keys are:
- 'POD': whether to compute POD of snapshots; defaults to True.
Defaults to empty dict.
Attributes:
HFEngine: HF problem solver.
HSEngine: Hilbert space general purpose engine.
mu0: Default parameter.
w: Weight for norm computation.
approxParameters: Dictionary containing values for main parameters of
approximant. Recognized keys are in parameterList.
parameterList: Recognized keys of approximant parameters:
- 'POD': whether to compute POD of snapshots.
POD: Whether to compute POD of snapshots.
energyNormMatrix: Sparse matrix (in CSC format) assoociated to
w-weighted H10 norm.
uHF: High fidelity solution with wavenumber lastSolvedHF as numpy
complex vector.
lastSolvedHF: Wavenumber corresponding to last computed high fidelity
solution.
solLifting: Lifting of Dirichlet boundary data as numpy vector.
uApp: Last evaluated approximant as numpy complex vector.
lastApproxParameters: List of parameters corresponding to last
computed approximant.
As: List of sparse matrices (in CSC format) representing coefficients
of linear system matrix wrt mu.
bs: List of numpy vectors representing coefficients of linear system
RHS wrt mu.
"""
def
__init__
(
self
,
HFEngine
:
HFEng
,
HSEngine
:
HSEng
,
mu0
:
complex
=
0
,
approxParameters
:
DictAny
=
{}):
self
.
HFEngine
=
HFEngine
self
.
HSEngine
=
HSEngine
self
.
_HFEngine0
=
copy
(
HFEngine
)
if
not
hasattr
(
self
,
"parameterList"
):
self
.
parameterList
=
[]
self
.
parameterList
+=
[
"POD"
]
self
.
solLifting
=
self
.
HFEngine
.
liftDirichletData
()
self
.
mu0
=
mu0
self
.
approxParameters
=
approxParameters
self
.
energyNormMatrix
=
self
.
HFEngine
.
energyNormMatrix
()
self
.
As
,
self
.
bs
=
self
.
HFEngine
.
getLSBlocks
()
def
name
(
self
)
->
str
:
"""Approximant label."""
return
self
.
__class__
.
__name__
@property
def
approxParameters
(
self
):
"""Value of approximant parameters."""
return
self
.
_approxParameters
@approxParameters.setter
def
approxParameters
(
self
,
approxParams
):
if
not
hasattr
(
self
,
"approxParameters"
):
self
.
_approxParameters
=
{}
approxParameters
=
purgeDict
(
approxParams
,
self
.
parameterList
,
dictname
=
self
.
name
()
+
".approxParameters"
)
keyList
=
list
(
approxParameters
.
keys
())
if
"POD"
in
keyList
:
self
.
POD
=
approxParameters
[
"POD"
]
elif
hasattr
(
self
,
"POD"
):
self
.
POD
=
self
.
POD
else
:
self
.
POD
=
True
@property
def
POD
(
self
):
"""Value of POD."""
return
self
.
_POD
@POD.setter
def
POD
(
self
,
POD
):
if
hasattr
(
self
,
"POD"
):
PODold
=
self
.
POD
else
:
PODold
=
-
1
self
.
_POD
=
POD
self
.
_approxParameters
[
"POD"
]
=
self
.
POD
if
PODold
!=
self
.
POD
:
self
.
resetSamples
()
def
solveHF
(
self
,
mu
:
complex
=
None
):
"""
Find high fidelity solution with original parameters and arbitrary
parameter.
Args:
mu: Target parameter.
"""
if
mu
is
None
:
mu
=
self
.
mu0
if
(
not
hasattr
(
self
,
"lastSolvedHF"
)
or
not
np
.
isclose
(
self
.
lastSolvedHF
,
mu
)):
A
,
b
=
self
.
buildLS
(
mu
)
self
.
uHF
=
spla
.
spsolve
(
A
,
b
)
self
.
lastSolvedHF
=
mu
return
self
.
uHF
def
buildLS
(
self
,
mu
:
complex
,
As
:
List
[
Np2D
]
=
None
,
bs
:
List
[
Np1D
]
=
None
)
->
Tuple
[
Np2D
,
Np1D
]:
"""
Build linear system from polynomial blocks.
Args:
mu: Parameter value.
As: Matrix blocks. If None, set to self.As. Defaults to None.
bs: RHS blocks. If None, set to self.bs. Defaults to None.
Returns:
Matrix and RHS of system.
"""
if
As
is
None
:
As
=
self
.
As
if
bs
is
None
:
bs
=
self
.
bs
A
=
copy
(
As
[
0
])
b
=
copy
(
bs
[
0
])
for
j
in
range
(
1
,
len
(
As
)):
A
=
A
+
np
.
power
(
mu
,
j
)
*
As
[
j
]
for
j
in
range
(
1
,
len
(
bs
)):
b
=
b
+
np
.
power
(
mu
,
j
)
*
bs
[
j
]
return
A
,
b
@abstractmethod
def
resetSamples
(
self
):
"""Reset samples. (ABSTRACT)"""
pass
@abstractmethod
def
setupApprox
(
self
):
"""
Setup approximant. (ABSTRACT)
Any specialization should include something like
self.computeDerivatives()
if not self.checkComputedApprox():
...
self.lastApproxParameters = copy(self.approxParameters)
"""
pass
def
checkComputedApprox
(
self
)
->
bool
:
"""
Check if setup of new approximant is not needed.
Returns:
True if new setup is not needed. False otherwise.
"""
return
(
hasattr
(
self
,
"lastApproxParameters"
)
and
self
.
approxParameters
==
self
.
lastApproxParameters
)
@abstractmethod
def
evalApprox
(
self
,
mu
:
complex
)
->
Np1D
:
"""
Evaluate approximant at arbitrary parameter. (ABSTRACT)
Any specialization should include something like
self.setupApprox()
self.uApp = ...
Args:
mu: Target parameter.
Returns:
Approximant as numpy complex vector.
"""
pass
@abstractmethod
def
getPoles
(
self
)
->
Np1D
:
"""
Obtain approximant poles.
Returns:
Numpy complex vector of poles.
"""
pass
def
HFNorm
(
self
,
mu
:
complex
,
normType
:
N2FSExpr
=
"H10"
)
->
float
:
"""
Compute norm of HF solution at arbitrary wavenumber.
Args:
mu: Target parameter.
normType(optional): Target norm identifier. Must be recognizable
by HSEngine norm command. If None, set to w. Defaults to None.
Returns:
Target norm of HFsolution.
"""
self
.
solveHF
(
mu
)
return
self
.
HSEngine
.
norm
(
self
.
uHF
,
normType
)
def
approxNorm
(
self
,
mu
:
complex
,
normType
:
N2FSExpr
=
"H10"
)
->
float
:
"""
Compute norm of (translated) approximant at arbitrary wavenumber.
Args:
mu: Target parameter.
normType(optional): Target norm identifier. Must be recognizable
by HSEngine norm command. If None, set to w. Defaults to None.
Returns:
Target norm of approximant.
"""
self
.
evalApprox
(
mu
)
return
self
.
HSEngine
.
norm
(
self
.
uApp
,
normType
)
def
approxError
(
self
,
mu
:
complex
,
normType
:
N2FSExpr
=
"H10"
)
->
float
:
"""
Compute norm of approximant at arbitrary wavenumber.
Args:
mu: Target parameter.
normType(optional): Target norm identifier. Must be recognizable
by HSEngine norm command. If None, set to w. Defaults to None.
Returns:
Target norm of (approximant - HFsolution).
"""
self
.
solveHF
(
mu
)
self
.
evalApprox
(
mu
)
return
self
.
HSEngine
.
norm
(
self
.
uApp
-
self
.
uHF
,
normType
)
def
getHF
(
self
,
mu
:
complex
)
->
Np1D
:
"""
Get HF solution at arbitrary wavenumber.
Args:
mu: Target parameter.
Returns:
HFsolution as numpy complex vector.
"""
self
.
solveHF
(
mu
)
return
self
.
uHF
def
getApp
(
self
,
mu
:
complex
)
->
Np1D
:
"""
Get approximant at arbitrary wavenumber.
Args:
mu: Target parameter.
Returns:
Approximant as numpy complex vector.
"""
self
.
evalApprox
(
mu
)
return
self
.
uApp
def
plotHF
(
self
,
mu
:
complex
,
name
:
str
=
"u"
,
**
figspecs
):
"""
Do some nice plots of the HF solution at arbitrary wavenumber.
Args:
mu: Target parameter.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
"""
self
.
solveHF
(
mu
)
self
.
HSEngine
.
plot
(
self
.
uHF
,
name
=
name
,
**
figspecs
)
def
plotApp
(
self
,
mu
:
complex
,
name
:
str
=
"u"
,
**
figspecs
):
"""
Do some nice plots of approximant at arbitrary wavenumber.
Args:
mu: Target parameter.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
"""
self
.
evalApprox
(
mu
)
self
.
HSEngine
.
plot
(
self
.
uApp
,
name
=
name
,
**
figspecs
)
def
plotErr
(
self
,
mu
:
complex
,
name
:
str
=
"u"
,
**
figspecs
):
"""
Do some nice plots of approximation error at arbitrary wavenumber.
Args:
mu: Target parameter.
name(optional): Name to be shown as title of the plots. Defaults to
'u'.
figspecs(optional key args): Optional arguments for matplotlib
figure creation.
"""
self
.
evalApprox
(
mu
)
self
.
solveHF
(
mu
)
self
.
HSEngine
.
plot
(
self
.
uApp
-
self
.
uHF
,
name
=
name
,
**
figspecs
)
Event Timeline
Log In to Comment