#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Base module for math utility functions
"""
import numpy as np
[docs]
def numericalOrder(nSteps, err):
"""
Compute numerical order from two vectors containing the error and the number of time-steps.
Parameters
----------
nSteps : np.1darray or list
Different number of steps to compute the error.
err : np.1darray
Diffenrent error values associated to the number of steps.
Returns
-------
beta : float
Order coefficient computed through linear regression.
rmse : float
The root mean square error of the linear regression.
"""
nSteps = np.asarray(nSteps)
x, y = np.log10(1/nSteps), np.log10(err)
# Compute regression coefficients and rmse
xMean = x.mean()
yMean = y.mean()
sX = ((x-xMean)**2).sum()
sXY = ((x-xMean)*(y-yMean)).sum()
beta = sXY/sX
alpha = yMean - beta*xMean
yHat = alpha + beta*x
rmse = ((y-yHat)**2).sum()**0.5
rmse /= x.size**0.5
return beta, rmse
[docs]
def lduFactorization(A:np.ndarray):
"""
Perform LDU factorization on a square matrix A.
Parameters
----------
A : np.2darray
The square matrix to factorize (n x n).
Returns
-------
L : np.2darray
Lower triangular matrix with ones on the diagonal.
D : np.2darray
Diagonal matrix.
U : np.2darray
Upper triangular matrix with ones on the diagonal.
"""
# Ensure A is a square matrix
n, m = A.shape
assert n == m, "Matrix A must be square."
# Initialize L, D, U matrices
L = np.eye(n)
D = np.zeros((n, n))
U = np.eye(n)
# Decompose A into L, D, U
for i in range(n):
# Compute D[i, i] as the diagonal element
D[i, i] = A[i, i] - np.sum(L[i, :i] * D[:i, :i].diagonal() * U[:i, i])
for j in range(i + 1, n):
# Compute elements for L below the diagonal
L[j, i] = (A[j, i] - np.sum(L[j, :i] * D[:i, :i].diagonal() * U[:i, i])) / D[i, i]
# Compute elements for U above the diagonal
U[i, j] = (A[i, j] - np.sum(L[i, :i] * D[:i, :i].diagonal() * U[:i, j])) / D[i, i]
return L, D, U