def apply_chords(im, spacing=0, axis=0, trim_edges=True): r""" Adds chords to the void space in the specified direction. The chords are separated by 1 voxel plus the provided spacing. Parameters ---------- im : ND-array An image of the porous material with void marked as True. spacing : int (default = 0) Chords are automatically separated by 1 voxel and this argument increases the separation. axis : int (default = 0) The axis along which the chords are drawn. trim_edges : bool (default = True) Whether or not to remove chords that touch the edges of the image. These chords are artifically shortened, so skew the chord length distribution Returns ------- An ND-array of the same size as ```im``` with True values indicating the chords. See Also -------- apply_chords_3D """ if spacing < 0: raise Exception('Spacing cannot be less than 0') dims1 = sp.arange(0, im.ndim) dims2 = sp.copy(dims1) dims2[axis] = 0 dims2[0] = axis im = sp.moveaxis(a=im, source=dims1, destination=dims2) im = sp.atleast_3d(im) ch = sp.zeros_like(im, dtype=bool) if im.ndim == 2: ch[:, ::2+spacing, ::2+spacing] = 1 if im.ndim == 3: ch[:, ::4+2*spacing, ::4+2*spacing] = 1 chords = im*ch chords = sp.squeeze(chords) if trim_edges: temp = clear_border(spim.label(chords == 1)[0]) > 0 chords = temp*chords chords = sp.moveaxis(a=chords, source=dims1, destination=dims2) return chords
def __call__(self,params): indices = self.slice(params) axis = tuple([idim for idim in range(self.ndim) if idim not in indices]) toret = self.mesh.sum(axis=axis) toret /= toret.max() x = [self.nodes[i] for i in indices] if len(x) == 1: x = x[0] sindices = sorted(indices) return x,scipy.moveaxis(toret,range(len(indices)),[sindices.index(ind) for ind in indices])
def ComputeDetJacobian(self, vec_x, vec_xi): dnn_xi = self.ShapeFunctionDerivative(vec_xi) self.JacobianMatrix = sp.moveaxis( [sp.dot(dnn, vec_x) for dnn in dnn_xi], 2, 0 ) #shape = (vec_x.shape[0] = Nel, len(vec_xi)=nb_pg, nb_dir_derivative, vec_x.shape[2] = dim) # sp.moveaxis([sp.dot(dnn,vec_x) for dnn in dnn_xi], 2,0) # self.JacobianMatrix = [linalg.norm(sp.dot(dnn,vec_x)) for dnn in dnn_xi] #dx_dxi avec x tangeant à l'élément (repère local élémentaire) self.detJ = self.JacobianMatrix.reshape( len(vec_x), -1) #In 1D, the jacobian matrix is a scalar
def GetLocalFrame(self, vec_x, vec_xi, localFrame=None): #linear local frame if len(vec_x.shape) == 2: vec_x = sp.array([vec_x]) dnn_xi = self.ShapeFunctionDerivative(vec_xi) listX = [sp.dot(dnn, vec_x)[0] for dnn in dnn_xi] lastAxis = len(listX[0].shape) - 1 listX = [ X / linalg.norm(X, axis=lastAxis).reshape(-1, 1) for X in listX ] if localFrame is None: return sp.moveaxis(self.__GetLocalFrameFromX(listX, None), 2, 0) else: rep_pg = self.interpolateLocalFrame( localFrame, vec_xi) #interpolation du repère local aux points de gauss return sp.moveaxis( self.__GetLocalFrameFromX(listX, rep_pg), 2, 0) #shape = (Nel, len(listX), dim:listvec, dim:coordinates)
def GetLocalFrame(self, vec_x, vec_xi, localFrame=None): #linear local frame if len(vec_x.shape) == 2: vec_x = sp.array([vec_x]) listX = [ vec_x[..., 1, 0:3] - vec_x[..., 0, 0:3] ] #only 1 element in the list because frame doesn't change over the element (in general nppg elements in list) lastAxis = len(listX[0].shape) - 1 listX = [ X / linalg.norm(X, axis=lastAxis).reshape(-1, 1) for X in listX ] if localFrame is None: return sp.moveaxis( self._element1D__GetLocalFrameFromX(listX, None), 2, 0) else: rep_pg = self.interpolateLocalFrame( localFrame, vec_xi) #interpolation du repère local aux points de gauss return sp.moveaxis([ self._element1D__GetLocalFrameFromX(listX, rep_pg)[0] for xi in vec_xi ], 2, 0) #shape = (Nel, len(listX), dim:listvec, dim:coordinates)
def ComputeDetJacobian(self, vec_x, vec_xi): """ Calcul le Jacobien aux points de gauss dans le cas d'un élément isoparamétrique (c'est à dire que les mêmes fonctions de forme sont utilisées) vec_x est un tabeau de dimension 3 où les lignes de vec_x[el] donnent les coordonnées de chacun des noeuds de l'éléments el vec_xi est un tableau de dimension 2 dont les lignes donnent les coordonnées dans le repère de référence des points où on souhaite avoir le jacobien (en général pg) Calcul le jacobien dans self.JacobianMatrix où self.Jacobien[el,k] est le jacobien de l'élément el au point de gauss k sous la forme [[dx/dxi, dy/dxi, ...], [dx/deta, dy/deta, ...], ...] Calcul également le déterminant du jacobien pour le kième point de gauss de l'élément el dans self.detJ[el,k] """ dnn_xi = self.ShapeFunctionDerivative(vec_xi) self.JacobianMatrix = sp.moveaxis( [sp.dot(dnn, vec_x) for dnn in dnn_xi], 2, 0 ) #shape = (vec_x.shape[0] = Nel, len(vec_xi)=nb_pg, nb_dir_derivative, vec_x.shape[2] = dim) if self.JacobianMatrix.shape[-2] == self.JacobianMatrix.shape[-1]: # self.detJ = [abs(linalg.det(J)) for J in self.JacobianMatrix] self.detJ = abs(linalg.det(self.JacobianMatrix)) else: #l'espace réel est dans une dimension plus grande que l'espace de l'élément de référence if sp.shape(self.JacobianMatrix)[-2] == 1: self.detJ = linalg.norm(JacobianMatrix, axis=3) else: #On doit avoir sp.shape(JacobianMatrix)[-2]=2 (l'elm de ref est défini en 2D) et sp.shape(JacobianMatrix)[-1]=3 (l'espace réel est 3D) J = self.JacobianMatrix self.detJ = sp.sqrt(abs(J[...,0,1]*J[...,1,2]-J[...,0,2]*J[...,1,1])**2 +\ abs(J[...,0,2]*J[...,1,0]-J[...,1,2]*J[...,0,0])**2 +\ abs(J[...,0,0]*J[...,1,1]-J[...,1,0]*J[...,0,1])**2 )