pymor.algorithms.loewner¶
Module Contents¶
- pymor.algorithms.loewner.complete_conjugate_pairs(nodes, *data)[source]¶
Complete nodes and associated data with complex conjugate pairs.
For each node whose complex conjugate is missing, append its conjugate and the elementwise conjugates of the corresponding entries in each array in
data. Existing entries retain their order; new entries are appended in input-node order. For example, complete samples and weights together with:nodes, samples, weights = complete_conjugate_pairs(nodes, samples, weights)
Note
Nodes are compared using exact equality. Already supplied conjugate data are not checked for consistency. Real nodes are not duplicated, and input arrays are not modified.
- Parameters:
nodes – Nonempty one-dimensional
NumPy arrayof sampling nodes.data – Zero or more
NumPy arrayspassed as positional arguments, e.g. samples, derivatives, quadrature weights or tangential directions. Each array must have shape(len(nodes), ...); trailing dimensions are preserved.
- Returns:
completed_nodes – One-dimensional
NumPy arraycontaining the original and appended nodes.completed_data – Completed
NumPy arraysin input order, returned as separate entries in(completed_nodes, *completed_data), not a nested tuple. With no data arguments, the return value is(completed_nodes,).
- pymor.algorithms.loewner.loewner_matrices(left_nodes, right_nodes, left_terms, right_terms, derivative_terms=None)[source]¶
Construct Loewner and shifted Loewner matrices from pairwise terms.
For distinct left and right nodes, the entries are
\[\mathbb{L}_{ij} = \frac{A_{ij} - B_{ij}}{\mu_i - \lambda_j}, \qquad (\mathbb{L}_s)_{ij} = \frac{\mu_i A_{ij} - \lambda_j B_{ij}}{\mu_i - \lambda_j}.\]The shifted matrix is computed as \((\mathbb{L}_s)_{ij} = \mu_i\mathbb{L}_{ij} + B_{ij}\). At coincident nodes, this gives the Hermite value \(\mu_i D_{ij} + B_{ij}\), where \(D_{ij}\) is the supplied derivative term.
- Parameters:
left_nodes – Nonempty one-dimensional
NumPy arrayof left interpolation nodes \(\mu_i\), of shape(n_left,).right_nodes – Nonempty one-dimensional
NumPy arrayof right interpolation nodes \(\lambda_j\), of shape(n_right,).left_terms –
NumPy arraycontaining \(A_{ij}\). Together withright_terms, must broadcast to shape(n_left, n_right, ...).right_terms –
NumPy arraycontaining \(B_{ij}\), broadcastable withleft_termsas above.derivative_terms – Optional
NumPy arraycontaining \(D_{ij}\), broadcastable to the pairwise term shape. Required at coincident nodes, where the left and right terms must agree. Seeloewner_matrixfor the derivative and coincidence conventions.
- Returns:
L – Loewner matrix as a
NumPy arrayof shape(n_left, n_right, ...).Ls – Shifted Loewner matrix as a
NumPy arrayof the same shape asL.
- pymor.algorithms.loewner.loewner_matrix(left_nodes, right_nodes, left_terms, right_terms, derivative_terms=None)[source]¶
Construct a Loewner matrix from pairwise terms.
The returned array contains the divided differences
\[\mathbb{L}_{ij} = \frac{A_{ij} - B_{ij}}{\mu_i - \lambda_j}.\]Scalar, matrix-valued and tangentially projected terms are supported through broadcasting. Use
loewner_quadrupleto assemble pairwise terms directly from transfer function data.Note
Coincident nodes are detected using exact equality. Nearly coincident nodes are treated by divided differences and may suffer from cancellation.
- Parameters:
left_nodes – Nonempty one-dimensional
NumPy arrayof left interpolation nodes \(\mu_i\), of shape(n_left,).right_nodes – Nonempty one-dimensional
NumPy arrayof right interpolation nodes \(\lambda_j\), of shape(n_right,).left_terms –
NumPy arraycontaining \(A_{ij}\). Together withright_terms, must broadcast to shape(n_left, n_right, ...). For scalar function samples, a column of left values of shape(n_left, 1)can be supplied.right_terms –
NumPy arraycontaining \(B_{ij}\), broadcastable withleft_termsas above. For scalar function samples, a row of right values of shape(1, n_right)can be supplied.derivative_terms – Optional
NumPy arrayof derivative terms with respect to the complex argument, broadcastable to the pairwise term shape. Required when a left and right node coincide. At these entries, the left and right terms must agree and the supplied derivative replaces the divided difference. Other derivative entries are ignored.
- Returns:
L –
NumPy arrayof shape(n_left, n_right, ...)containing the Loewner matrix. Trailing dimensions of the broadcast terms are retained, not flattened into blocks.
- pymor.algorithms.loewner.loewner_matrix_nd(sampling_values, samples, interpolation_indices)[source]¶
Construct a higher-dimensional Loewner matrix for Cartesian scalar data.
Assemble the Loewner matrix used in the parametric AAA algorithm of [CRBG23]. The interpolation nodes form a Cartesian subgrid of the sampling grid. For one variable, this reduces to
loewner_matrixwith interpolation nodes on the right and all remaining nodes on the left.- Parameters:
sampling_values – Nonempty list or tuple of nonempty one-dimensional
NumPy arrays, one per variable. The first variable is typically the complex frequency; subsequent variables are parameters. Interpolation and non-interpolation node values must not coincide in any variable.samples –
NumPy arrayof scalar samples with shapetuple(map(len, sampling_values)).samples[i, j, ...]corresponds to the nodes(sampling_values[0][i], sampling_values[1][j], ...). Matrix-valued samples must be projected to scalar data before calling this function.interpolation_indices – List or tuple of nonempty one-dimensional integer
NumPy arrays, one per variable. Each array selects interpolation nodes from the correspondingsampling_valuesarray and must contain distinct, valid indices. For one variable, at least one sampling node must remain outside the interpolation set.
- Returns:
L – Two-dimensional
NumPy arrayof shape(N - K, K), whereNandKare the numbers of points in the full sampling grid and the Cartesian interpolation grid, respectively. Columns follow the supplied interpolation-index order. Rows correspond to all sampling-grid points outside the Cartesian interpolation grid. Both grids are flattened in NumPy C order, with the last variable varying fastest.
- pymor.algorithms.loewner.loewner_quadruple(left_nodes, right_nodes, left_values, right_values, *, left_directions=None, right_directions=None, derivatives=None, force_real=False)[source]¶
Construct a Loewner quadruple from partitioned transfer function samples.
Assemble the Loewner matrix, shifted Loewner matrix and left and right interpolation data as in [ALI17]. Supports SISO data, full-block MIMO data and tangential MIMO data. No sampling, partitioning or conjugate completion is performed.
Note
In the tangential case, before realification,
\[V_i = \ell_i^T H(\mu_i), \qquad W_j = H(\lambda_j)r_j, \qquad \mathbb{L}_{ij} = \frac{V_i r_j - \ell_i^T W_j}{\mu_i - \lambda_j}.\]Directions are neither normalised nor conjugated internally. For full-block MIMO data, rows are ordered by left node then output, and columns by right node then input. For a square quadruple, the descriptor-system sign convention is \(E=-L\), \(A=-L_s\), \(B=V\) and \(C=W\).
- Parameters:
left_nodes – Nonempty one-dimensional
NumPy arrayof left interpolation nodes \(\mu_i\), of shape(n_left,).right_nodes – Nonempty one-dimensional
NumPy arrayof right interpolation nodes \(\lambda_j\), of shape(n_right,).left_values –
NumPy arraycontaining transfer function values atleft_nodes. Shape(n_left,)for SISO data or(n_left, p, m)for a system withpoutputs andminputs. With tangential directions, already projected valuesVof shape(n_left, m)are also accepted.right_values –
NumPy arraycontaining transfer function values atright_nodes. Shape(n_right,)for SISO data or(n_right, p, m)for MIMO data. With tangential directions, already projected valuesWof shape(p, n_right)are also accepted.left_directions – Optional
NumPy arrayof left tangential directions of shape(n_left, p). Requiresright_directions. Each row stores a direction \(\ell_i^T\), applied without complex conjugation.right_directions – Optional
NumPy arrayof right tangential directions of shape(n_right, m). Requiresleft_directions. Each row stores a direction \(r_j^T\), used as a column when multiplying a transfer function value.derivatives – Optional
NumPy arrayof unprojected transfer function derivatives with respect to the complex argument atleft_nodes, with the shape(n_left, p, m)for MIMO data. Required when a left and right node coincide. Entries at other nodes are ignored. Tangential projections of these derivatives are performed internally.force_real – If
True, transform the quadruple to real arrays using unitary conjugate-pair transformations. Each node set must already contain unique complex conjugate pairs, and values, used derivatives and directions at conjugate nodes must be conjugates. Values and directions at real nodes must be real. No conjugate data are appended.
- Returns:
L – Loewner matrix as a
NumPy array. Shape(n_left * p, n_right * m)for full-block MIMO data, or(n_left, n_right)for SISO or tangential data.Ls – Shifted Loewner matrix as a
NumPy arrayof the same shape asL.V – Left interpolation data as a
NumPy array. Shape(n_left * p, m)for full-block MIMO data,(n_left, m)for tangential data, or(n_left, 1)for SISO data.W – Right interpolation data as a
NumPy array. Shape(p, n_right * m)for full-block MIMO data,(p, n_right)for tangential data, or(1, n_right)for SISO data.
- Raises:
AccuracyError – If
force_real=Truecannot produce real matrices up to roundoff.
- pymor.algorithms.loewner.partition_frequencies(nodes, samples, partitioning='even-odd', ordering='regular', force_real=True)[source]¶
Partition frequency samples into left and right Loewner data sets.
- Parameters:
nodes – One-dimensional
NumPy arrayof complex sampling nodes of shape(n,).samples –
NumPy arrayof sampled values of shape(n, ...), aligned withnodes. Used to determine sample norms whenorderingis'magnitude'.partitioning –
Partitioning rule or a tuple
(left_indices, right_indices)of index arrays. Available rules are:'even-odd': assign alternating entries to the left and right sets.'half-half': assign the first half to the left set and the remainder to the right set. For an odd number of entries, the left set receives one extra entry.
Explicit index arrays are returned without validation or reordering;
orderingandforce_realare ignored in this case.ordering –
Ordering applied before a partitioning rule:
'regular': preserve the input order; no sorting by frequency is performed.'magnitude': order by increasing sample norm.'random': use a reproducible random ordering with seed zero.
force_real – If
True, keep complex conjugate nodes in the same set. The nodes and samples must already be closed under conjugation. Real nodes and nodes in the upper half-plane are ordered and partitioned separately; the corresponding lower half-plane nodes are then appended to each set. IfFalse, all nodes are ordered and partitioned together.
- Returns:
left_indices – One-dimensional
NumPy arrayof indices intonodesandsamplesfor the left set.right_indices – One-dimensional
NumPy arrayof indices intonodesandsamplesfor the right set.
- pymor.algorithms.loewner.sample_transfer_function(sampling_values, fom, *, derivative=False)[source]¶
Sample a
TransferFunctionor its derivative on a Cartesian grid.- Parameters:
sampling_values – A one-dimensional
NumPy arrayor a sequence of such arrays. The first array contains Laplace-variable values; subsequent arrays contain parameter values.fom – A
TransferFunctionor a model with atransfer_functionattribute.derivative – If
True, sample the derivative with respect to the complex frequency argument.
- Returns:
samples – Sample data of shape
tuple(map(len, sampling_values)) + (dim_output, dim_input). A single frequency array produces shape(n, dim_output, dim_input).