示例#1
0
文件: element.py 项目: kinnala/sp.fem
    def evalbasis(self, mesh, qps, tind=None):
        # initialize power basis
        self._pbasisNinit(self.dim, self.maxdeg)
        N = len(self._pbasis)

        # construct Vandermonde matrix and invert it
        V = self._evaldofs(mesh, tind=tind)
        V = np.linalg.inv(V)

        # initialize
        u = const_cell(0*qps[0], N)
        du = const_cell(0*qps[0], N, self.dim)
        ddu = const_cell(0*qps[0], N, self.dim, self.dim)

        # loop over new basis
        for jtr in range(N):
            # loop over power basis
            for itr in range(N):
                if self.dim==2:
                    u[jtr] += V[:, itr, jtr][:, None]\
                              * self._pbasis[itr](qps[0], qps[1])
                    du[jtr][0] += V[:, itr, jtr][:, None]\
                                  * self._pbasisdx[itr](qps[0], qps[1])
                    du[jtr][1] += V[:, itr, jtr][:,None]\
                                  * self._pbasisdy[itr](qps[0], qps[1])
                    ddu[jtr][0][0] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxx[itr](qps[0], qps[1])
                    ddu[jtr][0][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxy[itr](qps[0], qps[1])
                    ddu[jtr][1][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdyy[itr](qps[0], qps[1])
                else:
                    raise NotImplementedError("!")
            ddu[jtr][1][0] = ddu[jtr][0][1]
        return u, du, ddu
示例#2
0
    def inorm(self, form, interp, intorder=None):
        # evaluate norm on all elements
        tind = range(self.mesh.t.shape[1])

        if not isinstance(interp, dict):
            raise Exception("The input solution vector(s) must be in a "
                            "dictionary! Pass e.g. {0:u} instead of u.")

        if intorder is None:
            intorder = 2*self.elem_u.maxdeg

        # check and fix parameters of form
        oldparams = inspect.getargspec(form).args
        paramlist = ['u', 'du', 'ddu', 'x', 'h']
        fform = self.fillargs(form, paramlist)

        X, W = get_quadrature(self.mesh.refdom, intorder)

        # mappings
        x = self.mapping.F(X, tind) # reference facet to global facet

        # jacobian at quadrature points
        detDF = self.mapping.detDF(X, tind)

        Nbfun_u = self.dofnum_u.t_dof.shape[0]
        dim = self.mesh.p.shape[0]

        # interpolate the solution vectors at quadrature points
        zero = 0.0*x[0]
        w, dw, ddw = ({} for i in range(3))
        for k in interp:
            w[k] = zero
            dw[k] = const_cell(zero, dim)
            ddw[k] = const_cell(zero, dim, dim)
            for j in range(Nbfun_u):
                jdofs = self.dofnum_u.t_dof[j, :]
                w[k] += interp[k][jdofs][:, None]\
                        * self.u[j]
                for a in range(dim):
                    dw[k][a] += interp[k][jdofs][:, None]\
                                * self.du[j][a]
                    for b in range(dim):
                        ddw[k][a][b] += interp[k][jdofs][:, None]\
                                        * self.ddu[j][a][b]

        # compute the mesh parameter from jacobian determinant
        h = np.abs(detDF)**(1.0/self.mesh.dim())

        return np.dot(fform(w, dw, ddw, x, h)**2*np.abs(detDF), W)
示例#3
0
文件: element.py 项目: mfkiwl/sp.fem
 def plot_lagmult(self,
                  mesh,
                  dofnum,
                  sol,
                  minval,
                  maxval,
                  lambdaeval,
                  nref=2,
                  cbar=True):
     """Draw plate obstacle lagrange multiplier on refined mesh."""
     print "Plotting on a refined mesh. This is slowish due to loop over elements..."
     import copy
     import spfem.mesh as fmsh
     plt.figure()
     totmaxval = 0
     for itr in range(mesh.t.shape[1]):
         m = fmsh.MeshTri(
             np.array([[
                 mesh.p[0, mesh.t[0, itr]], mesh.p[0, mesh.t[1, itr]],
                 mesh.p[0, mesh.t[2, itr]]
             ],
                       [
                           mesh.p[1, mesh.t[0, itr]],
                           mesh.p[1, mesh.t[1, itr]], mesh.p[1, mesh.t[2,
                                                                       itr]]
                       ]]), np.array([[0], [1], [2]]))
         M = copy.deepcopy(m)
         m.refine(nref)
         qps = {}
         qps[0] = np.array([m.p[0, :]])
         qps[1] = np.array([m.p[1, :]])
         u, _, _, d4u = self.evalbasis(M, qps, [0])
         newu = u[0].flatten() * 0.0
         #newd4u = d4u[0].flatten()*0.0
         newd4u = const_cell(0 * qps[0], self.dim, self.dim)
         for jtr in range(len(u)):
             newu += sol[dofnum.t_dof[jtr, itr]] * u[jtr].flatten()
             newd4u[0][0] += sol[dofnum.t_dof[
                 jtr, itr]] * d4u[jtr][0][0].flatten()
             newd4u[0][1] += sol[dofnum.t_dof[
                 jtr, itr]] * d4u[jtr][0][1].flatten()
             newd4u[1][0] += sol[dofnum.t_dof[
                 jtr, itr]] * d4u[jtr][1][0].flatten()
             newd4u[1][1] += sol[dofnum.t_dof[
                 jtr, itr]] * d4u[jtr][1][1].flatten()
         tmp = lambdaeval(newu, newd4u, qps, M.param())
         #print tmp.shape
         if np.max(tmp) > totmaxval:
             totmaxval = np.max(tmp)
         m.plot(tmp.flatten(),
                nofig=True,
                smooth=True,
                zlim=(minval, maxval))
         plt.hold('on')
     print "Maximum value: " + str(totmaxval)
     if cbar:
         plt.colorbar()
示例#4
0
文件: element.py 项目: mfkiwl/sp.fem
    def evalbasis(self, mesh, qps, tind=None):
        # initialize power basis
        self._pbasisNinit(self.dim, self.maxdeg)
        N = len(self._pbasis)

        # construct Vandermonde matrix and invert it
        V = self._evaldofs(mesh, tind=tind)
        V = np.linalg.inv(V)

        # initialize
        u = const_cell(0 * qps[0], N)
        du = const_cell(0 * qps[0], N, self.dim)
        ddu = const_cell(0 * qps[0], N, self.dim, self.dim)
        d4u = const_cell(0 * qps[0], N, self.dim, self.dim)

        # loop over new basis
        for jtr in range(N):
            # loop over power basis
            for itr in range(N):
                if self.dim == 2:
                    u[jtr] += V[:, itr, jtr][:, None]\
                              * self._pbasis[itr](qps[0], qps[1])
                    du[jtr][0] += V[:, itr, jtr][:, None]\
                                  * self._pbasisdx[itr](qps[0], qps[1])
                    du[jtr][1] += V[:, itr, jtr][:,None]\
                                  * self._pbasisdy[itr](qps[0], qps[1])
                    ddu[jtr][0][0] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxx[itr](qps[0], qps[1])
                    ddu[jtr][0][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxy[itr](qps[0], qps[1])
                    ddu[jtr][1][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdyy[itr](qps[0], qps[1])
                    d4u[jtr][0][0] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxxxx[itr](qps[0], qps[1])
                    d4u[jtr][1][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdyyyy[itr](qps[0], qps[1])
                    d4u[jtr][0][1] += V[:, itr, jtr][:, None]\
                                      * self._pbasisdxxyy[itr](qps[0], qps[1])
                else:
                    raise NotImplementedError("!")
            ddu[jtr][1][0] = ddu[jtr][0][1]
            d4u[jtr][1][0] = d4u[jtr][0][1]
        return u, du, ddu, d4u
示例#5
0
import copy
m1defo = copy.deepcopy(m1)
m2defo = copy.deepcopy(m2)

m1defo.p[0, :] += X[a1.dofnum_u.n_dof[0, :]]
m1defo.p[1, :] += X[a1.dofnum_u.n_dof[1, :]]
m2defo.p[0, :] += Y[a2.dofnum_u.n_dof[0, :]]
m2defo.p[1, :] += Y[a2.dofnum_u.n_dof[1, :]]

m1defo.draw()
plt.hold('on')
m2defo.draw(nofig=True)

import spfem.utils as spu
Du1 = spu.const_cell(0.0, 2, 2)
Du2 = spu.const_cell(0.0, 2, 2)
Du1[0][0], Du1[0][1] = spu.gradient(X[a1.dofnum_u.n_dof[0, :]], m1)
Du1[1][0], Du1[1][1] = spu.gradient(X[a1.dofnum_u.n_dof[1, :]], m1)
Du2[0][0], Du2[0][1] = spu.gradient(Y[a2.dofnum_u.n_dof[0, :]], m2)
Du2[1][0], Du2[1][1] = spu.gradient(Y[a2.dofnum_u.n_dof[1, :]], m2)

S1 = C1(Eps(Du1))
S2 = C2(Eps(Du2))

smax = np.max((np.max(S1[1][1]), np.max(S1[1][1])))
smin = np.min((np.min(S2[1][1]), np.min(S2[1][1])))

m1.plot(C1(Eps(Du1))[1, 1], zlim=(smin, smax))
plt.hold('on')
m2.plot(C2(Eps(Du2))[1, 1], nofig=True, zlim=(smin, smax))
示例#6
0
    def fasm(self, form, find=None, interior=False, intorder=None,
             normals=True, interp=None):
        """Facet assembly."""
        if find is None:
            if interior:
                find = self.mesh.interior_facets()
            else:
                find = self.mesh.boundary_facets()

        if intorder is None:
            intorder = self.elem_u.maxdeg + self.elem_v.maxdeg

        nv = self.mesh.p.shape[1]
        nt = self.mesh.t.shape[1]
        ne = find.shape[0]

        # check and fix parameters of form
        oldparams = inspect.getargspec(form).args
        if interior:
            if 'u1' in oldparams or 'du1' in oldparams:
                paramlist = ['u1', 'u2', 'v1', 'v2',
                             'du1', 'du2', 'dv1', 'dv2',
                             'x', 'h', 'n', 'w']
                bilinear = True
            else:
                paramlist = ['v1', 'v2', 'dv1', 'dv2',
                             'x', 'h', 'n', 'w']
                bilinear = False
        else:
            if 'u' in oldparams or 'du' in oldparams:
                paramlist = ['u', 'v', 'du', 'dv', 'x', 'h', 'n', 'w']
                bilinear = True
            else:
                paramlist = ['v', 'dv', 'x', 'h', 'n', 'w']
                bilinear = False
        fform = self.fillargs(form, paramlist)

        X, W = get_quadrature(self.mesh.brefdom, intorder)

        # boundary element indices
        tind1 = self.mesh.f2t[0, find]
        tind2 = self.mesh.f2t[1, find]

        # mappings
        x = self.mapping.G(X, find=find) # reference facet to global facet
        Y1 = self.mapping.invF(x, tind=tind1) # global facet to ref element
        Y2 = self.mapping.invF(x, tind=tind2) # global facet to ref element

        Nbfun_u = self.dofnum_u.t_dof.shape[0]
        Nbfun_v = self.dofnum_v.t_dof.shape[0]

        detDG = self.mapping.detDG(X, find)

        # compute normal vectors
        n = {}
        if normals:
            # normals based on tind1 only
            n = self.mapping.normals(Y1, tind1, find, self.mesh.t2f)

        # compute the mesh parameter from jacobian determinant
        if self.mesh.dim() > 1.0:
            h = np.abs(detDG)**(1.0/(self.mesh.dim() - 1.0))
        else: # exception for 1D mesh (no boundary h defined)
            h = None

        # interpolate some previous discrete function at quadrature points
        w = {}
        if interp is not None:
            if not isinstance(interp, dict):
                raise Exception("The input solution vector(s) must be in a "
                                "dictionary! Pass e.g. {0:u} instead of u.")
            for k in interp:
                w[k] = 0.0*x[0]
                for j in range(Nbfun_u):
                    phi, _ = self.elem_u.gbasis(self.mapping, Y1, j, tind1)
                    w[k] += interp[k][self.dofnum_u.t_dof[j, tind1], None]*phi

        # bilinear form
        if bilinear:
            # initialize sparse matrix structures
            ndata = Nbfun_u*Nbfun_v*ne
            if interior:
                data = np.zeros(4*ndata)
                rows = np.zeros(4*ndata)
                cols = np.zeros(4*ndata)
            else:
                data = np.zeros(ndata)
                rows = np.zeros(ndata)
                cols = np.zeros(ndata)

            for j in range(Nbfun_u):
                u1, du1 = self.elem_u.gbasis(self.mapping, Y1, j, tind1)
                if interior:
                    u2, du2 = self.elem_u.gbasis(self.mapping, Y2, j, tind2)
                    if j == 0:
                        # these are zeros corresponding to the shapes of u,du
                        z = const_cell(0, *cell_shape(u2))
                        dz = const_cell(0, *cell_shape(du2))
                for i in range(Nbfun_v):
                    v1, dv1 = self.elem_v.gbasis(self.mapping, Y1, i, tind1)
                    if interior:
                        v2, dv2 = self.elem_v.gbasis(self.mapping, Y2, i, tind2)

                    # compute entries of local stiffness matrices
                    if interior:
                        ixs1 = slice(ne*(Nbfun_v*j + i),
                                     ne*(Nbfun_v*j + i + 1))
                        ixs2 = slice(ne*(Nbfun_v*j + i) + ndata,
                                     ne*(Nbfun_v*j + i + 1) + ndata)
                        ixs3 = slice(ne*(Nbfun_v*j + i) + 2*ndata,
                                     ne*(Nbfun_v*j + i + 1) + 2*ndata)
                        ixs4 = slice(ne*(Nbfun_v*j + i) + 3*ndata,
                                     ne*(Nbfun_v*j + i + 1) + 3*ndata)

                        data[ixs1] = np.dot(fform(u1, z, v1, z,
                                                  du1, dz, dv1, dz,
                                                  x, h, n, w)*np.abs(detDG), W)
                        rows[ixs1] = self.dofnum_v.t_dof[i, tind1]
                        cols[ixs1] = self.dofnum_u.t_dof[j, tind1]

                        data[ixs2] = np.dot(fform(z, u2, z, v2,
                                                  dz, du2, dz, dv2,
                                                  x, h, n, w)*np.abs(detDG), W)
                        rows[ixs2] = self.dofnum_v.t_dof[i, tind2]
                        cols[ixs2] = self.dofnum_u.t_dof[j, tind2]

                        data[ixs3] = np.dot(fform(z, u2, v1, z,
                                                  dz, du2, dv1, dz,
                                                  x, h, n, w)*np.abs(detDG), W)
                        rows[ixs3] = self.dofnum_v.t_dof[i, tind1]
                        cols[ixs3] = self.dofnum_u.t_dof[j, tind2]

                        data[ixs4] = np.dot(fform(u1, z, z, v2,
                                                  du1, dz, dz, dv2,
                                                  x, h, n, w)*np.abs(detDG), W)
                        rows[ixs4] = self.dofnum_v.t_dof[i, tind2]
                        cols[ixs4] = self.dofnum_u.t_dof[j, tind1]
                    else:
                        ixs = slice(ne*(Nbfun_v*j + i), ne*(Nbfun_v*j + i + 1))
                        data[ixs] = np.dot(fform(u1, v1, du1, dv1,
                                                 x, h, n, w)*np.abs(detDG), W)
                        rows[ixs] = self.dofnum_v.t_dof[i, tind1]
                        cols[ixs] = self.dofnum_u.t_dof[j, tind1]

            return coo_matrix((data, (rows, cols)),
                              shape=(self.dofnum_v.N, self.dofnum_u.N)).tocsr()

        # linear form
        else:
            if interior:
                # could not find any use case
                raise Exception("No interior support in linear facet form.")
            # initialize sparse matrix structures
            data = np.zeros(Nbfun_v*ne)
            rows = np.zeros(Nbfun_v*ne)
            cols = np.zeros(Nbfun_v*ne)

            for i in range(Nbfun_v):
                v1, dv1 = self.elem_v.gbasis(self.mapping, Y1, i, tind1)

                # find correct location in data,rows,cols
                ixs = slice(ne*i, ne*(i + 1))

                # compute entries of local stiffness matrices
                data[ixs] = np.dot(fform(v1, dv1, x, h, n, w)*np.abs(detDG), W)
                rows[ixs] = self.dofnum_v.t_dof[i, tind1]
                cols[ixs] = np.zeros(ne)

            return coo_matrix((data, (rows, cols)),
                              shape=(self.dofnum_v.N, 1)).toarray().T[0]
示例#7
0
    def fnorm(self, form, interp, intorder=None, interior=False, normals=True):
        if interior:
            # evaluate norm on all interior facets
            find = self.mesh.interior_facets()
        else:
            # evaluate norm on all boundary facets
            find = self.mesh.boundary_facets()

        if not isinstance(interp, dict):
            raise Exception("The input solution vector(s) must be in a "
                            "dictionary! Pass e.g. {0:u} instead of u.")

        if intorder is None:
            intorder = 2*self.elem_u.maxdeg

        # check and fix parameters of form
        oldparams = inspect.getargspec(form).args
        if 'u1' in oldparams or 'du1' in oldparams or 'ddu1' in oldparams:
            if interior is False:
                raise Exception("The supplied form contains u1 although "
                                "no interior=True is given.")
        if interior:
            paramlist = ['u1', 'u2', 'du1', 'du2', 'ddu1', 'ddu2',
                         'x', 'n', 't', 'h']
        else:
            paramlist = ['u', 'du', 'ddu', 'x', 'n', 't', 'h']
        fform = self.fillargs(form, paramlist)

        X, W = get_quadrature(self.mesh.brefdom, intorder)

        # indices of elements at different sides of facets
        tind1 = self.mesh.f2t[0, find]
        tind2 = self.mesh.f2t[1, find]

        # mappings
        x = self.mapping.G(X, find=find) # reference facet to global facet
        detDG = self.mapping.detDG(X, find)

        # compute basis function values at quadrature points
        u1, du1, ddu1 = self.elem_u.evalbasis(self.mesh, x, tind=tind1)
        if interior:
            u2, du2, ddu2 = self.elem_u.evalbasis(self.mesh, x, tind=tind2)

        Nbfun_u = self.dofnum_u.t_dof.shape[0]
        dim = self.mesh.p.shape[0]

        n = {}
        t = {}
        if normals:
            Y = self.mapping.invF(x, tind=tind1) # global facet to ref element
            n = self.mapping.normals(Y, tind1, find, self.mesh.t2f)
            if len(n) == 2: # TODO fix for 3D and other than triangles?
                t[0] = -n[1]
                t[1] = n[0]

        # interpolate the solution vectors at quadrature points
        zero = np.zeros((len(find), len(W)))
        w1, dw1, ddw1 = ({} for i in range(3))
        if interior:
            w2, dw2, ddw2 = ({} for i in range(3))
        for k in interp:
            w1[k] = zero
            dw1[k] = const_cell(zero, dim)
            ddw1[k] = const_cell(zero, dim, dim)
            if interior:
                w2[k] = zero
                dw2[k] = const_cell(zero, dim)
                ddw2[k] = const_cell(zero, dim, dim)
            for j in range(Nbfun_u):
                jdofs1 = self.dofnum_u.t_dof[j, tind1]
                jdofs2 = self.dofnum_u.t_dof[j, tind2]
                w1[k] += interp[k][jdofs1][:, None] * u1[j]
                if interior:
                    w2[k] += interp[k][jdofs2][:, None] * u2[j]
                for a in range(dim):
                    dw1[k][a] += interp[k][jdofs1][:, None]\
                                 * du1[j][a]
                    if interior:
                        dw2[k][a] += interp[k][jdofs2][:, None]\
                                     * du2[j][a]
                    for b in range(dim):
                        ddw1[k][a][b] += interp[k][jdofs1][:, None]\
                                         * ddu1[j][a][b]
                        if interior:
                            ddw2[k][a][b] += interp[k][jdofs2][:, None]\
                                             * ddu2[j][a][b]

        h = np.abs(detDG)**(1.0/(self.mesh.dim()-1.0))

        if interior:
            return np.dot(fform(w1, w2, dw1, dw2, ddw1, ddw2,
                                x, n, t, h)**2*np.abs(detDG), W), find
        else:
            return np.dot(fform(w1, dw1, ddw1,
                                x, n, t, h)**2*np.abs(detDG), W), find
示例#8
0
import copy
m1defo=copy.deepcopy(m1)
m2defo=copy.deepcopy(m2)

m1defo.p[0,:]+=X[a1.dofnum_u.n_dof[0,:]]
m1defo.p[1,:]+=X[a1.dofnum_u.n_dof[1,:]]
m2defo.p[0,:]+=Y[a2.dofnum_u.n_dof[0,:]]
m2defo.p[1,:]+=Y[a2.dofnum_u.n_dof[1,:]]

m1defo.draw()
plt.hold('on')
m2defo.draw(nofig=True)

import spfem.utils as spu
Du1=spu.const_cell(0.0,2,2)
Du2=spu.const_cell(0.0,2,2)
Du1[0][0],Du1[0][1]=spu.gradient(X[a1.dofnum_u.n_dof[0,:]],m1)
Du1[1][0],Du1[1][1]=spu.gradient(X[a1.dofnum_u.n_dof[1,:]],m1)
Du2[0][0],Du2[0][1]=spu.gradient(Y[a2.dofnum_u.n_dof[0,:]],m2)
Du2[1][0],Du2[1][1]=spu.gradient(Y[a2.dofnum_u.n_dof[1,:]],m2)

S1=C1(Eps(Du1))
S2=C2(Eps(Du2))

smax=np.max((np.max(S1[1][1]),np.max(S1[1][1])))
smin=np.min((np.min(S2[1][1]),np.min(S2[1][1])))

m1.plot(C1(Eps(Du1))[1,1],zlim=(smin,smax))
plt.hold('on')
m2.plot(C2(Eps(Du2))[1,1],nofig=True,zlim=(smin,smax))