# This file was automatically generated by SWIG (https://www.swig.org).
# Version 4.1.1
#
# Do not make changes to this file unless you know what you are doing - modify
# the SWIG interface file instead.

from sys import version_info as _swig_python_version_info
# Import the low-level C/C++ module
if __package__ or "." in __name__:
    from . import _masterelement
else:
    import _masterelement

try:
    import builtins as __builtin__
except ImportError:
    import __builtin__

def _swig_repr(self):
    try:
        strthis = "proxy of " + self.this.__repr__()
    except __builtin__.Exception:
        strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)


def _swig_setattr_nondynamic_instance_variable(set):
    def set_instance_attr(self, name, value):
        if name == "this":
            set(self, name, value)
        elif name == "thisown":
            self.this.own(value)
        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
            set(self, name, value)
        else:
            raise AttributeError("You cannot add instance attributes to %s" % self)
    return set_instance_attr


def _swig_setattr_nondynamic_class_variable(set):
    def set_class_attr(cls, name, value):
        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
            set(cls, name, value)
        else:
            raise AttributeError("You cannot add class attributes to %s" % cls)
    return set_class_attr


def _swig_add_metaclass(metaclass):
    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
    def wrapper(cls):
        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
    return wrapper


class _SwigNonDynamicMeta(type):
    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)


import ooflib.SWIG.engine.element
import ooflib.SWIG.common.coord
import ooflib.SWIG.engine.csubproblem
import ooflib.SWIG.common.doublevec
import ooflib.SWIG.common.lock
import ooflib.SWIG.engine.equation
import ooflib.SWIG.engine.fieldindex
import ooflib.SWIG.engine.planarity
import ooflib.SWIG.engine.flux
import ooflib.SWIG.engine.outputval
import ooflib.SWIG.engine.nodalequation
import ooflib.SWIG.engine.femesh
import ooflib.SWIG.common.cmicrostructure
import ooflib.SWIG.common.pixelgroup
import ooflib.SWIG.common.pixelattribute
import ooflib.SWIG.common.timestamp
import ooflib.SWIG.engine.field
import ooflib.SWIG.engine.freedom
import ooflib.SWIG.engine.pointdata
import ooflib.SWIG.engine.node
import ooflib.SWIG.engine.material
import ooflib.SWIG.common.abstractimage
import ooflib.SWIG.common.ccolor
import ooflib.SWIG.engine.property
import ooflib.SWIG.engine.meshiterator
import ooflib.SWIG.engine.linearizedsystem
import ooflib.SWIG.engine.sparsemat
import ooflib.SWIG.engine.edge
import ooflib.SWIG.engine.mastercoord
import ooflib.SWIG.engine.elementnodeiterator
import ooflib.SWIG.engine.gausspoint
class ProtoNode(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined")
    __repr__ = _swig_repr

    def index(self):
        return _masterelement.ProtoNode_index(self)

    def mapping(self):
        return _masterelement.ProtoNode_mapping(self)

    def func(self):
        return _masterelement.ProtoNode_func(self)

    def corner(self):
        return _masterelement.ProtoNode_corner(self)

    def nedges(self):
        return _masterelement.ProtoNode_nedges(self)

    def getedge(self, i):
        return _masterelement.ProtoNode_getedge(self, i)

    def mastercoord(self):
        return _masterelement.ProtoNode_mastercoord(self)
    __swig_destroy__ = _masterelement.delete_ProtoNode

# Register ProtoNode in _masterelement:
_masterelement.ProtoNode_swigregister(ProtoNode)

def masterElementList():
    return _masterelement.masterElementList()
class MasterElement(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")

    def __init__(self, *args, **kwargs):
        raise AttributeError("No constructor defined")

    def id(self):
        return _masterelement.MasterElement_id(self)

    def nnodes(self):
        return _masterelement.MasterElement_nnodes(self)

    def nmapnodes(self):
        return _masterelement.MasterElement_nmapnodes(self)

    def nfuncnodes(self):
        return _masterelement.MasterElement_nfuncnodes(self)

    def ninteriorfuncnodes(self):
        return _masterelement.MasterElement_ninteriorfuncnodes(self)

    def ninteriormapnodes_only(self):
        return _masterelement.MasterElement_ninteriormapnodes_only(self)

    def nexteriormapnodes_only(self):
        return _masterelement.MasterElement_nexteriormapnodes_only(self)

    def nsides(self):
        return _masterelement.MasterElement_nsides(self)

    def name(self):
        return _masterelement.MasterElement_name(self)

    def description(self):
        return _masterelement.MasterElement_description(self)

    def ncorners(self):
        return _masterelement.MasterElement_ncorners(self)

    def outOfBounds(self, arg2):
        return _masterelement.MasterElement_outOfBounds(self, arg2)

    def onBoundary(self, arg2):
        return _masterelement.MasterElement_onBoundary(self, arg2)

    def onBoundary2(self, arg2, arg3):
        return _masterelement.MasterElement_onBoundary2(self, arg2, arg3)

    def buildInterfaceElement(self, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10):
        return _masterelement.MasterElement_buildInterfaceElement(self, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)

    def map_order(self):
        return _masterelement.MasterElement_map_order(self)

    def fun_order(self):
        return _masterelement.MasterElement_fun_order(self)

    def build(self, skelel, arg3, arg4):
        return _masterelement.MasterElement_build(self, skelel, arg3, arg4)

    def nSCpoints(self):
        return _masterelement.MasterElement_nSCpoints(self)

    def getSCpoint(self, arg2):
        return _masterelement.MasterElement_getSCpoint(self, arg2)

    def get_protonode(self, n):
        return _masterelement.MasterElement_get_protonode(self, n)

    def __repr__(self):
        return _masterelement.MasterElement___repr__(self)

# Register MasterElement in _masterelement:
_masterelement.MasterElement_swigregister(MasterElement)
# -*- python -*-

# This software was produced by NIST, an agency of the U.S. government,
# and by statute is not subject to copyright in the United States.
# Recipients of this software assume all responsibilities associated
# with its operation, modification and maintenance. However, to
# facilitate maintenance we ask that before distributing modified
# versions of this software, you first contact the authors at
# oof_manager@nist.gov. 

from ooflib.common import enum
from ooflib.common import debug
from ooflib.common.IO import xmlmenudump

# Global function that gets the master element array from C.  While
# doing so, it does some precomputation in MasterElement.__init__().

_masterElementDict = {}

def getMasterElementDict():
## TODO: Each time this is called, it fetches the list of master
## elements from C++ and checks to see if there are any new ones.
## This seems inefficient.  If we just required all MasterElement
## classes to register themselves when first imported, we could
## wrap them and put them in _masterElementDict then, and not have
## to fetch the list all the time.
    lst = masterElementList()
    for me in lst:
# This is where the singleton instance of each MasterElement
# type is created in Python.  The C++ singletons when the
# python wrapper files were loaded, by the *init() calls in
# the SRC/engine/elements/*.spy files.
        if me.name() not in _masterElementDict:
# Make lists of nodes that have to be created -- these are
# in a dictionary indexed by the edge number, plus a
# special entry indexed by the string 'interior'.  Corner
# nodes are entirely omitted from the indexing scheme
# because they're created automatically.
            me.protodic = {'interior':[]}
            for i in range(me.nsides()):
                me.protodic[i] = []
            for i in range(me.nnodes()):
                proto = me.get_protonode(i)
                n = proto.nedges() # number of edges this node is on
                if n == 0:
                    me.protodic['interior'].append(proto)
                elif n == 1:
                    edgeno = proto.getedge(0)
                    me.protodic[edgeno].append(proto)

            _masterElementDict[me.name()] = me
    return _masterElementDict

# Export this function to restricted namespace.
from ooflib.common import utils
utils.OOFdefine('getMasterElementDict', getMasterElementDict)

########################

_masterElementEnumDict = {}
_enumunsorted = {}

def getMasterElementEnums():
# Create and update Enum classes for MasterElement types.  There
# is a separate enum class for each element geometry (number of
# sides).  This function returns a dictionary containing the
# classes, keyed by the number of sides of the elements.
    edict = getMasterElementDict()
    for name, el in edict.items():
        try:
            enumclass = _masterElementEnumDict[el.ncorners()]
        except KeyError:
            n = el.ncorners()
            utils.OOFexec('from ooflib.common import enum')
            utils.OOFexec(f'class Element{n}(enum.EnumClass()):pass')
            enumclass = utils.OOFeval(f'Element{n}')
            enumclass.tip = f"{n} cornered finite elements."
            enumclass.discussion = xmlmenudump.loadFile(
                f"DISCUSSIONS/engine/enum/element{n}.xml")
            enumclass.xrefs = ["Section-Concepts-Mesh-Geometry"]
            _masterElementEnumDict[n] = enumclass
            enumclass._sorted = 1
        if name not in enumclass.names:
            enum.addEnumName(enumclass, name, el.description())
            enumclass._sorted = 0
    for enumclass in _masterElementEnumDict.values():
        if not enumclass._sorted:
            enumclass.names.sort(key=melcomparisionkey)
            enumclass._sorted = 1
    return _masterElementEnumDict

def getMasterElementGeometries():
    keys = sorted(list(getMasterElementEnums().keys()))
    return keys

def getMasterElementEnumClasses():
# Returns a sorted list of the MasterElement enum classes.
    return [_masterElementEnumDict[g] for g in getMasterElementGeometries()]

def getMasterElementFromEnum(elementenum):
    edict = getMasterElementDict()
    return edict[elementenum.name]

def getMasterElementsFromEnumClass(enumclass):
    edict = getMasterElementDict()
    return [edict[name] for name in enumclass.names]

def melcomparisionkey(elem):
# For sorting MasterElement names to determine their position in the GUI.
    edict = getMasterElementDict()
    el = edict[elem]
    return (el.nnodes(), el.nmapnodes(), el.nfuncnodes())


cvar = _masterelement.cvar

