# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
from typing import Dict
from Muscat.MeshContainers.Filters.FilterObjects import ElementFilter
import Muscat.MeshContainers.ElementsDescription as ED
__cache__:Dict = {}
__cacheSize__:int = 1
numberingAlgorithm:str = "CppBase" # option are "CppBase" or "NumpyBase" or "DictBase"
numberingAlgorithmBackUp:str = "NumpyBase" # option are "NumpyBase" or "DictBase"
[docs]
def GetNumberingFromCache(mesh, space, elementFilter=None, discontinuous=False, fromConnectivity=False):
return None
key = (id(mesh), id(space), id(elementFilter), discontinuous, fromConnectivity)
return __cache__.get(key, None)
[docs]
def SetNumberingToCache(obj, mesh, space, elementFilter=None, discontinuous=False, fromConnectivity=False):
if len(__cache__) >= __cacheSize__:
for k in __cache__:
del __cache__[k]
break
key = (id(mesh), id(space), id(elementFilter), discontinuous, fromConnectivity)
__cache__[key] = obj
[docs]
def ComputeDofNumbering(mesh, space, dofs=None, fromConnectivity=False, elementFilter=None, discontinuous=False):
if dofs is None:
cachedData = GetNumberingFromCache(mesh=mesh, space=space, fromConnectivity=fromConnectivity, elementFilter=elementFilter, discontinuous=discontinuous)
if cachedData is not None:
return cachedData
global numberingAlgorithm
res = None
if numberingAlgorithm == "CppBase":
try:
from Muscat.FE.Numberings.NativeDofNumbering import NativeDofNumbering
res = NativeDofNumbering()
except:
numberingAlgorithm = "NumpyBase"
print("Warning CppBase Numbering non available (missing compilation) Using NumpyBase")
if numberingAlgorithm == "NumpyBase":
from Muscat.FE.Numberings.DofNumberingNumpy import DofNumberingNumpy
res = DofNumberingNumpy()
elif numberingAlgorithm == "DictBase":
from Muscat.FE.Numberings.DofNumberingDict import DofNumberingDict
res = DofNumberingDict()
elif res == None:
raise (Exception(f"Numbering algorithm of type {numberingAlgorithm} not available "))
discontinuous = discontinuous or not space.hasSharedShapeFunctions
if fromConnectivity:
if dofs is not None or elementFilter is not None or discontinuous:
raise (Exception("cant take dofs, sign, discontinuous or elementFilter different from the default values"))
# check the compatibility of the spaces, this is not perfect, the user is responsible of putting the shape function in the same order
# as the nodes of the reference element
for k in mesh.elements.keys():
space[k].Create()
if space[k].fromConnectivityCompatible == True or space[k].GetNumberOfShapeFunctions() == ED.numberOfNodes[k]:
continue
raise Exception(f"Incompatible case! Can't use a non compatible space {(type(space[k]))} and fromConnectivity at the same time")
res.ComputeNumberingFromConnectivity(mesh, space)
SetNumberingToCache(res, mesh=mesh, space=space, fromConnectivity=fromConnectivity, elementFilter=elementFilter, discontinuous=discontinuous)
return res
elif discontinuous:
if dofs is not None:
res = dofs
res.ComputeNumberingNoSharedDof(mesh=mesh, space=space, elementFilter=elementFilter)
SetNumberingToCache(res, mesh=mesh, space=space, fromConnectivity=fromConnectivity, elementFilter=elementFilter, discontinuous=discontinuous)
return res
else:
if dofs is not None:
res = dofs
res.ComputeNumberingGeneral(mesh=mesh, space=space, elementFilter=elementFilter)
SetNumberingToCache(res, mesh=mesh, space=space, fromConnectivity=fromConnectivity, elementFilter=elementFilter, discontinuous=discontinuous)
return res
[docs]
def CheckIntegrity(GUI: bool = False):
import Muscat.FE.DofNumbering as DN
from Muscat.MeshTools.MeshCreationTools import CreateCube
res2 = CreateCube([2, 2, 2], [-1.0, -1.0, -1.0], [2./46, 2./46, 2./46])
from Muscat.FE.Spaces.FESpaces import LagrangeSpaceGeo, LagrangeSpaceP0, LagrangeSpaceP1, LagrangeSpaceP2, ConstantSpaceGlobal, FESpace
from Muscat.FE.Spaces.FESpaces import GetListOfAvailableFESpaces, GetFESpaceByName
spacesToTest:Dict[str,FESpace] = {"ConstantSpaceGlobal": ConstantSpaceGlobal, "LagrangeSpaceGeo": LagrangeSpaceGeo,
"LagrangeSpaceP0": LagrangeSpaceP0, "LagrangeSpaceP1": LagrangeSpaceP1, "LagrangeSpaceP2": LagrangeSpaceP2}
spacesToTest:Dict[str,FESpace] = {k.name:k for k in GetListOfAvailableFESpaces()}
from Muscat.FE.Spaces.IPSpaces import GenerateSpaceForIntegrationPointInterpolation
from Muscat.FE.IntegrationRules import GetIntegrationRuleByName
irule = GetIntegrationRuleByName(ruleName="LagrangeIsoParamQuadrature")
gaussSpace = GenerateSpaceForIntegrationPointInterpolation(irule)
spacesToTest["gaussSpace"] = gaussSpace
import time
def printData(numbering, st):
for k, v in res2.elements.items():
print(k, numbering.get(k, None))
print(f"numbering.size = {numbering.size}")
print(f" time : {time.time()-st}")
for spaceName, space in spacesToTest.items():
print("*************************** {} {}*******************************************".format(DN.numberingAlgorithm, spaceName))
# on a tag
print(f"vvvvvvvvvvv {spaceName} tag vvvvvvvvvvvvvvv")
st = time.time()
numbering = DN.ComputeDofNumbering(res2, space, elementFilter=ElementFilter(eTag="X0"))
printData(numbering, st)
# all
print("----------------------{} all -----------------------------".format(spaceName))
st = time.time()
numbering = DN.ComputeDofNumbering(res2, space)
printData(numbering, st)
if space is LagrangeSpaceGeo:
# from connectivity
print("----------------------{} from connectivity -----------------------------".format(spaceName))
st = time.time()
numbering = DN.ComputeDofNumbering(res2, space, fromConnectivity=True)
printData(numbering, st)
# 3D using filter
print("----------------------{} 3D filter-----------------------------".format(spaceName))
st = time.time()
numbering = DN.ComputeDofNumbering(res2, space, elementFilter=ElementFilter(dimensionality=3))
printData(numbering, st)
return "ok"
[docs]
def CheckIntegrityUsingAlgo(algo, GUI=False):
import Muscat.FE.DofNumbering as DN
tmpAlgo = DN.numberingAlgorithm
DN.numberingAlgorithm = algo
try:
res = DN.CheckIntegrity(GUI)
DN.numberingAlgorithm = tmpAlgo
return res
except:
DN.numberingAlgorithm = tmpAlgo
raise
if __name__ == '__main__':
print(CheckIntegrity(True)) # pragma: no cover