Source code for Mordicus.Modules.Safran.BasicAlgorithms.LPEQP

# -*- coding: utf-8 -*-

import os
from mpi4py import MPI
if MPI.COMM_WORLD.Get_size() > 1: # pragma: no cover
    os.environ["OMP_NUM_THREADS"] = "1"
    os.environ["OPENBLAS_NUM_THREADS"] = "1"
    os.environ["MKL_NUM_THREADS"] = "1"
    os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
    os.environ["NUMEXPR_NUM_THREADS"] = "1"
import numpy as np




[docs]def LPEQP(integrationWeights, integrands, integrals, normIntegrals, tolerance): """ Linear Programming Empirical Quadrature Procedure [1]. Parameters ---------- integrationWeights : np.ndarray of size (numberOfIntegrationPoints,), dtype = float. Weights of the truth quadrature integrands : np.ndarray of size (numberOfIntegrands,numberOfIntegrationPoints), dtype = float. Functions we look to integrated accurately with fewer integration points. Usually, the integrands are already reduced, and numberOfIntegrands is the product of the number of reduced integrand modes and the number of modes of the ReducedOrderBasis integrals : np.ndarray of size (numberOfIntegrands,), dtype = float. High-fidelity integral computed using the truth integration scheme normIntegrals : float np.linalg.norm(integrals), already computed in mordicus use tolerance : float upper bound for the accuracy of the reduced integration scheme on the provided integrands Returns ------- np.ndarray of size (numberOfReducedIntegrationPoints,), dtype = int indices of the kepts integration points (reducedIntegrationPoints) np.ndarray of size (numberOfReducedIntegrationPoints,), dtype = float weights associated to the kepts integration points (reducedIntegrationWeights) References ---------- [1] M. Yano and A. T. Patera. An LP empirical quadrature procedure for reduced basis treatment of parametrized nonlinear PDEs, 2017. URL: https://www.researchgate.net/publication/323633428_An_LP_empirical _quadrature_procedure_for_reduced_basis_treatment_of_parametrized_nonli near_PDEs. """ # optimization options optimStatus = {} optimStatus[0] = "Optimization proceeding nominally" optimStatus[1] = "Iteration limit reached" optimStatus[2] = "Problem appears to be infeasible" optimStatus[3] = "Problem appears to be unbounded" optimStatus[4] = "Numerical difficulties encountered" #method = 'revised simplex' method = 'interior-point' options = {} options['interior-point'] = {\ 'maxiter': 100, 'tol': 1e-06, 'disp':\ False, 'alpha0': 0.99995, 'beta': 0.1, 'sparse': False,\ 'lstsq': False, 'sym_pos': False, 'cholesky': False, 'pc': True,\ 'ip': False, 'permc_spec': 'MMD_AT_PLUS_A', 'presolve': True} options['revised simplex'] = {\ 'maxiter': 100, 'tol': 1e-06, 'disp': False} # problem definition c = np.ones(integrationWeights.shape[0]) A_ub = np.vstack((integrands, -integrands)) b_ub = np.hstack((tolerance*normIntegrals + integrals,\ tolerance*normIntegrals - integrals)) # optimization call optimRes = CallOptimizer(c, A_ub, b_ub, method, options[method]) # provide result if optimization successful x = optimRes['x'] print("Optimization status =", optimStatus.get(optimRes['status'], "key not known")) if optimRes['status'] < 2: # return the solution only if the sparsity is at least 15% totalWeights = np.sum(x) indices = x>1.e-7*totalWeights reducedIntegrationPoints, reducedIntegrationWeights = np.where(indices)[0], x[indices] if len(reducedIntegrationPoints) > 0.15*len(integrationWeights): print(str(100*len(reducedIntegrationPoints)/len(integrationWeights))+"% of nonzero integration weights") return np.array([]), np.array([]) else: return reducedIntegrationPoints, reducedIntegrationWeights else:# pragma: no cover # return an empty solution return np.array([]), np.array([])
[docs]def CallOptimizer(c, A_ub, b_ub, method, options): """ Exemple of scipy optimizer wrapper (here linprog) Parameters ---------- c : 1-D array The coefficients of the linear objective function to be minimized. A_ub : 2-D array The inequality constraint matrix. Each row of ``A_ub`` specifies the coefficients of a linear inequality constraint on ``x``. b_ub : 1-D array The inequality constraint vector. Each element represents an upper bound on the corresponding value of ``A_ub @ x``. method : str, optional The algorithm used to solve the standard form problem. options : dict, optional A dictionary of solver options. Returns ------- res : OptimizeResult see the class `scipy.optimize.OptimizeResult` """ from scipy.optimize import linprog as lp return lp(c = c, A_ub = A_ub, b_ub = b_ub, method = method,\ options = options)
if __name__ == "__main__":# pragma: no cover from Mordicus import RunTestFile RunTestFile(__file__)