# -*- coding: utf-8 -*-# noinspection PyUnresolvedReferencesr""".. _docs-mesh:Mesh====We define an abstract mesh based on an abstract manifold by calling ``ph.mesh`` method, .. autofunction:: src.mesh.meshAs an example,>>> mesh = ph.mesh(manifold)The output, ``mesh``, is an instance of :class:`Mesh`. And similarly, it is abstract at this stage. .. autoclass:: src.mesh.Mesh :members: m, n, manifoldYou can print a list of defined meshes by>>> ph.list_meshes() # doctest: +ELLIPSISExisting meshes:..."""fromtools.frozenimportFrozenfromsrc.configimport_mesh_default_sym_reprfromsrc.configimport_check_sym_reprfromsrc.configimport_parse_lin_reprfromsrc.configimport_mesh_default_lin_reprfromsrc.spaces.mainimportset_meshfromsrc.configimport_mesh_partition_sym_repr,_mesh_partition_lin_repr_global_meshes=dict()# all meshes are cached, and all sym_repr and lin_repr are different.
[docs]defmesh(manifold,sym_repr=None,lin_repr=None):"""Generate an abstract mesh over an abstract manifold. It is actually a wrapper of the ``__init__`` method of :class:`Mesh`. Parameters ---------- manifold : :class:`Manifold` The abstract manifold this mesh is built on. sym_repr : {None, str}, optional The symbolic representation of the mesh. If it is ``None``, we will use a pre-set symbolic representation. The default is ``None``. lin_repr : {None, str}, optional The linguistic representation of the mesh. If it is ``None``, we will use a pre-set linguistic representation. The default is ``None``. Returns ------- mesh : :class:`Mesh` The abstract mesh instance. """returnMesh(manifold,sym_repr=sym_repr,lin_repr=lin_repr,)
[docs]classMesh(Frozen):# Mesh -def__init__(self,manifold,sym_repr=None,lin_repr=None):self._objective=None# when initializing, it has no objective instance. And when we generate an objective of this# abstract mesh, we store the last objective one with this attribute.assertmanifold.__class__.__name__=='Manifold',f"I need a manifold."self._manifold=manifoldassertmanifold._covered_by_meshisNone,f"we already made an abstract mesh for this manifold."manifold._covered_by_mesh=selfifsym_reprisNone:number_existing_meshes=len(_global_meshes)base_repr=_mesh_default_sym_reprifnumber_existing_meshes==0:sym_repr=base_reprelse:sym_repr=base_repr+r'_{'+str(number_existing_meshes)+'}'else:passsym_repr=_check_sym_repr(sym_repr)iflin_reprisNone:base_repr=_mesh_default_lin_reprnumber_existing_meshes=len(_global_meshes)ifnumber_existing_meshes==0:lin_repr=base_reprelse:lin_repr=base_repr+str(number_existing_meshes)assertsym_reprnotin_global_meshes, \
f"Manifold symbolic representation is illegal, pls specify a symbolic representation other than " \
f"{set(_global_meshes.keys())}"for_in_global_meshes:_m=_global_meshes[_]assertlin_repr!=_m._lin_reprlin_repr,pure_lin_repr=_parse_lin_repr('mesh',lin_repr)self._sym_repr=sym_reprself._lin_repr=lin_reprself._pure_lin_repr=pure_lin_repr_global_meshes[sym_repr]=selfiflen(_global_meshes)==1:# we just initialize the first meshset_mesh(self)# we set it as the default meshself._boundary=Noneself._interface=Noneself._inclusion=Noneself._freeze()@propertydefndim(self):""""""returnself._manifold.ndim@propertydefn(self):"""The dimensions of the manifold."""returnself.ndim@propertydefm(self):"""The dimensions of the embedding space."""returnself._manifold.mdef__repr__(self):""""""super_repr=super().__repr__().split('object')[-1]return'<Mesh '+self._sym_repr+super_repr# this will be unique.@propertydefmanifold(self):"""The manifold this mesh is built on."""returnself._manifold# it is regarded as an operator, so do not use @propertydefboundary(self):"""Give a mesh of dimensions (n-1) on the boundary manifold."""ifself._boundaryisNone:manifold_boundary=self.manifold.boundary()ifmanifold_boundary.__class__.__name__=='Manifold':self._boundary=Mesh(manifold_boundary,sym_repr=r'\eth'+self._sym_repr,lin_repr=r'boundary-of-'+self._pure_lin_repr)self._boundary._inclusion=selfelifmanifold_boundary.__class__.__name__=='NullManifold':self._boundary=NullMesh(manifold_boundary)else:raiseNotImplementedError()returnself._boundarydefinclusion(self):"""Give the mesh of dimensions (n+1) on the inclusion manifold."""returnself._inclusiondefboundary_partition(self,*sym_reprs,config_name=None):"""Define boundary sections by partition the mesh boundary into sections defined by `*sym_reprs`."""ifself._boundaryisNone:_=self.boundary()else:pass_boundary=self.manifold.boundary()sub_manifolds=_boundary.partition(*sym_reprs,config_name=config_name)forsub_manifoldinsub_manifolds:sr0,sr1=_mesh_partition_sym_reprifsub_manifold._covered_by_meshisNone:self.__class__(sub_manifold,sym_repr=sr0+sub_manifold._sym_repr+sr1,lin_repr=_mesh_partition_lin_repr+sub_manifold._pure_lin_repr,)# it will be automatically saved to _global_meshes.else:pass
classNullMesh(Frozen):"""A mesh that is constructed upon a null manifold."""def__init__(self,null_manifold):self._null_manifold=null_manifoldself._freeze()@propertydefndim(self):returnself._null_manifold.ndim