Source code for Mordicus.Modules.Mines.OperatorCompressors.HyperReduction

# -*- coding: utf-8 -*-
from Mordicus.Core.Containers.Meshes.MeshBase import MeshBase
from Mordicus.Core.Containers.CollectionProblemData import CollectionProblemData

import numpy as np 

import pdb


[docs]def selection( basis: np.ndarray ) -> list: """Function to perform DEIM like selection of unknown to keep for the RID construction. Unknown can be nodal or integrated values Arguments: basis {np.ndarray} -- The full reduced order basis Returns: list -- the unknown rank to keep """ n_dof, n_modes = basis.shape rid_ddl = [] V = basis.copy() rk_max = np.argmax( np.abs(V[:,0]) ) rid_ddl.append( rk_max ) norm0 = abs(V[rk_max,0]) V[:,0] /= norm0 V[rk_max, 0] = 0. j_cum = [0] for m in range(1,n_modes): v_red = V[np.ix_(rid_ddl, [m,])] u_red = basis[np.ix_(rid_ddl, j_cum)] v_tmp = u_red.T.dot( v_red ) utu = u_red.T.dot(u_red) try: sol = np.linalg.solve( utu, v_tmp) except np.linalg.LinAlgError: print("Becarefull the reduce integration domain construction seems badly conditionned") continue x = np.zeros((V.shape[1],1)) x[:sol.shape[0], [0,]] = sol q = -1.*V.dot(x) + 1.*V[:,[m]] rk_max = np.argmax( np.abs(q) ) q /= np.abs(q[rk_max]) rid_ddl.append(rk_max) j_cum.append( m ) return rid_ddl
[docs]def BuildReducedIntegrationOperator(collectionProblemData: CollectionProblemData, mesh: MeshBase, extend=0, listNameDualVarOutput = []): """[summary] Arguments: collectionProblemData {CollectionProblemData} -- [description] mesh {MeshBase} -- [description] Keyword Arguments: extend {int} -- the number of additional layers to keep (default: {0}) listNameDualVarOutput {list} -- the list of dual variable to use in addition to nodal ones (default: {[]}) """ print("Compute Reduced Integration Domain ... ") ## Step 1. Select dofs reducedOrderBasis = collectionProblemData.GetReducedOrderBasis("U").transpose() rid_ddl = selection(reducedOrderBasis) print("DOFs selection done") ## Step 2. Select dual variable rid_dual = {} for name in listNameDualVarOutput: reducedOrderBasis = collectionProblemData.GetReducedOrderBasis(name).transpose() rid_dual[name] = selection(reducedOrderBasis) nn = mesh.GetNumberOfNodes() selected_nodes = set([ dof % nn for dof in rid_ddl ]) print("Identify the associated Reduced Integration Domain") ## Build reduced mesh elem_to_keep = [] for node_rk in selected_nodes: elem_to_keep += mesh.GetElemAttach(node_rk) ## Integration point to element for key, value in rid_dual.items(): nb_comp = collectionProblemData.GetSolutionsNumberOfComponents(key) selected_ip =set([ int(ip/nb_comp) for ip in value ]) elem_to_keep += [ mesh.GetElemContaining( ip_rank ) for ip_rank in selected_ip ] elem_to_keep = set(elem_to_keep) for _ in range( extend ): dirty_list = [] for elem in elem_to_keep: for node in mesh.GetElement( elem ): dirty_list += mesh.GetElemAttach(node) new_elems = set(dirty_list) - elem_to_keep print(f"{len(new_elems)} elements added in the RID") elem_to_keep = set( list(elem_to_keep) + list(new_elems) ) operatorCompressionData = {} operatorCompressionData["dofs"] = rid_ddl operatorCompressionData["rid"] = elem_to_keep collectionProblemData.SetOperatorCompressionData( operatorCompressionData )