Example #1
0
def elastic3d_displacement(x, p, lamb=1.0, mu=1.0, **kwargs):
  ''' 
  Returns a collection of weight matrices that estimates displacements 
  at `x` based on displacements at `p`. If `x` is in `p` then the 
  results will be an appropriately shaped identity matrix.

  Parameters
  ----------
  x : (N,3) array
    target points.
  
  p : (M,3) array
    observation points.  
  
  lamb : float
    first Lame parameter
  
  mu : float
    second Lame parameter
    
  **kwargs :
    additional arguments passed to `weight_matrix`

  Returns
  -------
  out : (3,3) list of sparse matrices
    A collection of matrices which return the displacements at `p` 
    based on the displacements at `x`.

  '''
  D_xx = weight_matrix(x, p, (0, 0, 0), **kwargs)
  D_yy = weight_matrix(x, p, (0, 0, 0), **kwargs)
  D_zz = weight_matrix(x, p, (0, 0, 0), **kwargs)
  return {'xx':D_xx, 'yy':D_yy, 'zz':D_zz}
Example #2
0
def elastic3d_body_force(x, p, lamb=1.0, mu=1.0, **kwargs):
  ''' 
  Returns a collection of weight matrices used to calculate body 
  force in a three-dimensional homogeneous elastic medium.

  Parameters
  ----------
  x : (N, 3) array
    target points.
  
  p : (M, 3) array
    observation points.  
  
  lamb : float
    first Lame parameter
  
  mu : float
    second Lame parameter
    
  **kwargs :
    additional arguments passed to `weight_matrix`

  Returns
  -------
  out : (3, 3) list of sparse matrices
    A collection of matrices which return the body force at `x` 
    exerted by the material, when dotted with the displacements at 
    `p`.

  '''
  coeffs_xx = [lamb + 2*mu,      mu,       mu]
  diffs_xx =  [  (2, 0, 0), (0, 2, 0),  (0, 0, 2)]
  coeffs_xy = [lamb + mu]
  diffs_xy =  [(1, 1, 0)]
  coeffs_xz = [lamb + mu]
  diffs_xz =  [(1, 0, 1)]
  coeffs_yx = [lamb + mu]
  diffs_yx =  [(1, 1, 0)]
  coeffs_yy = [     mu, lamb + 2*mu,      mu]
  diffs_yy =  [(2, 0, 0),   (0, 2, 0), (0, 0, 2)]
  coeffs_yz = [lamb + mu]
  diffs_yz =  [(0, 1, 1)]
  coeffs_zx = [lamb + mu]
  diffs_zx =  [(1, 0, 1)]
  coeffs_zy = [lamb + mu]
  diffs_zy =  [(0, 1, 1)]
  coeffs_zz = [     mu,      mu, lamb + 2*mu]
  diffs_zz =  [(2, 0, 0), (0, 2, 0),   (0, 0, 2)]
  D_xx = weight_matrix(x, p, diffs_xx, coeffs=coeffs_xx, **kwargs)
  D_xy = weight_matrix(x, p, diffs_xy, coeffs=coeffs_xy, **kwargs)
  D_xz = weight_matrix(x, p, diffs_xz, coeffs=coeffs_xz, **kwargs)
  D_yx = weight_matrix(x, p, diffs_yx, coeffs=coeffs_yx, **kwargs)
  D_yy = weight_matrix(x, p, diffs_yy, coeffs=coeffs_yy, **kwargs)
  D_yz = weight_matrix(x, p, diffs_yz, coeffs=coeffs_yz, **kwargs)
  D_zx = weight_matrix(x, p, diffs_zx, coeffs=coeffs_zx, **kwargs)
  D_zy = weight_matrix(x, p, diffs_zy, coeffs=coeffs_zy, **kwargs)
  D_zz = weight_matrix(x, p, diffs_zz, coeffs=coeffs_zz, **kwargs)
  return {'xx':D_xx, 'xy':D_xy, 'xz':D_xz, 
          'yx':D_yx, 'yy':D_yy, 'yz':D_yz, 
          'zx':D_zx, 'zy':D_zy, 'zz':D_zz}
Example #3
0
def elastic2d_surface_force(x, nrm, p, lamb=1.0, mu=1.0, **kwargs):
    ''' 
  Returns a collection of weight matrices that estimate surface
  traction forces at *x* resulting from displacements at *p*.

  Parameters
  ----------
  x : (N,2) array
    target points which reside on a surface.
  
  nrm : (N,2) array
    surface normal vectors at each point in *x*.

  p : (M,2) array
    observation points.  
  

  lamb : float
    first Lame parameter
  
  mu : float
    second Lame parameter
    
  **kwargs :
    additional arguments passed to *weight_matrix*

  Returns
  -------
  out : (2,2) list of sparse matrices
    A collection of matrices [[D_xx,D_xy],[D_yx,D_yy]] which return 
    the surface traction force [t_x,t_y] at *x* exerted by the 
    material, when dotted with the displacements [u_x,u_y] at *p*.

  '''
    # x component of traction force resulting from x displacement
    coeffs_xx = [nrm[:, 0] * (lamb + 2 * mu), nrm[:, 1] * mu]
    diffs_xx = [(1, 0), (0, 1)]
    # x component of traction force resulting from y displacement
    coeffs_xy = [nrm[:, 0] * lamb, nrm[:, 1] * mu]
    diffs_xy = [(0, 1), (1, 0)]
    # y component of traction force resulting from x displacement
    coeffs_yx = [nrm[:, 0] * mu, nrm[:, 1] * lamb]
    diffs_yx = [(0, 1), (1, 0)]
    # y component of force resulting from displacement in the y direction
    coeffs_yy = [nrm[:, 0] * mu, nrm[:, 1] * (lamb + 2 * mu)]
    diffs_yy = [(1, 0), (0, 1)]
    # make the differentiation matrices that enforce the free surface boundary
    # conditions.
    D_xx = weight_matrix(x, p, diffs_xx, coeffs=coeffs_xx, **kwargs)
    D_xy = weight_matrix(x, p, diffs_xy, coeffs=coeffs_xy, **kwargs)
    D_yx = weight_matrix(x, p, diffs_yx, coeffs=coeffs_yx, **kwargs)
    D_yy = weight_matrix(x, p, diffs_yy, coeffs=coeffs_yy, **kwargs)
    return [[D_xx, D_xy], [D_yx, D_yy]]
Example #4
0
def elastic2d_body_force(x, p, lamb=1.0, mu=1.0, **kwargs):
    ''' 
  Returns a collection of weight matrices used to calculate body 
  force in a two-dimensional homogeneous elastc medium.

  Parameters
  ----------
  x : (N,2) array
    Target points.
  
  p : (M,2) array
    Observation points.  
  
  lamb : float, optional
    First Lame parameter
  
  mu : float, optional
    Specond Lame parameter
    
  **kwargs :
    additional arguments passed to *weight_matrix*

  Returns
  -------
  out : (2,2) list of sparse matrices
    A collection of matrices [[D_xx,D_xy],[D_yx,D_yy]] which return 
    the body force [f_x,f_y] at *x* exerted by the material, when 
    dotted with the displacements [u_x,u_y] at *p*.

  '''
    # x component of force resulting from displacement in the x direction.
    coeffs_xx = [lamb + 2 * mu, mu]
    diffs_xx = [(2, 0), (0, 2)]
    # x component of force resulting from displacement in the y direction.
    coeffs_xy = [lamb + mu]
    diffs_xy = [(1, 1)]
    # y component of force resulting from displacement in the x direction.
    coeffs_yx = [lamb + mu]
    diffs_yx = [(1, 1)]
    # y component of force resulting from displacement in the y direction.
    coeffs_yy = [lamb + 2 * mu, mu]
    diffs_yy = [(0, 2), (2, 0)]
    # make the differentiation matrices that enforce the PDE on the
    # interior nodes.
    D_xx = weight_matrix(x, p, diffs_xx, coeffs=coeffs_xx, **kwargs)
    D_xy = weight_matrix(x, p, diffs_xy, coeffs=coeffs_xy, **kwargs)
    D_yx = weight_matrix(x, p, diffs_yx, coeffs=coeffs_yx, **kwargs)
    D_yy = weight_matrix(x, p, diffs_yy, coeffs=coeffs_yy, **kwargs)
    return [[D_xx, D_xy], [D_yx, D_yy]]
Example #5
0
def elastic3d_displacement(x, p, lamb=1.0, mu=1.0, **kwargs):
    ''' 
  Returns a collection of weight matrices that estimates displacements 
  at *x* based on displacements at *p*. If *x* is in *p* then the 
  results will be an appropriately shaped identity matrix.

  Parameters
  ----------
  x : (N,3) array
    target points.
  
  p : (M,3) array
    observation points.  
  
  lamb : float
    first Lame parameter
  
  mu : float
    second Lame parameter
    
  **kwargs :
    additional arguments passed to *weight_matrix*

  Returns
  -------
  out : (3,3) list of sparse matrices
    A collection of matrices which return the displacements at *p* 
    based on the displacements at *x*.

  '''
    D_xx = weight_matrix(x, p, (0, 0, 0), **kwargs)
    D_xy = csr_matrix((x.shape[0], p.shape[0]))
    D_xz = csr_matrix((x.shape[0], p.shape[0]))
    D_yx = csr_matrix((x.shape[0], p.shape[0]))
    D_yy = weight_matrix(x, p, (0, 0, 0), **kwargs)
    D_yz = csr_matrix((x.shape[0], p.shape[0]))
    D_zx = csr_matrix((x.shape[0], p.shape[0]))
    D_zy = csr_matrix((x.shape[0], p.shape[0]))
    D_zz = weight_matrix(x, p, (0, 0, 0), **kwargs)
    return [[D_xx, D_xy, D_xz], [D_yx, D_yy, D_yz], [D_zx, D_zy, D_zz]]
Example #6
0
# identify nodes associated with the different boundary types
slit_top, = (smpid == 199).nonzero()
slit_bot, = (smpid == 99).nonzero()
# edges of the annulus minus the cut
boundary, = ((smpid >= 0) & (smpid != 199) & (smpid != 99)).nonzero()
interior, = (smpid == -1).nonzero()

# do not build stencils which cross this line
bnd_vert = np.array([[0.0, 0.0],
                     [10 * np.cos(gap / 2.0), 10 * np.sin(gap / 2.0)]])
bnd_smp = np.array([[0, 1]])
weight_kwargs = {'vert': bnd_vert, 'smp': bnd_smp, 'n': 20}
# build lhs
# enforce laplacian on interior nodes
A_interior = weight_matrix(nodes[interior], nodes, [[2, 0], [0, 2]],
                           **weight_kwargs)

# find boundary normal vectors
normals = simplex_outward_normals(vert, smp)[smpid[boundary]]
n1 = scipy.sparse.diags(normals[:, 0], 0)
n2 = scipy.sparse.diags(normals[:, 1], 0)
# enforce free surface boundary conditions
A_boundary = (
    n1 * weight_matrix(nodes[boundary], nodes, [1, 0], **weight_kwargs) +
    n2 * weight_matrix(nodes[boundary], nodes, [0, 1], **weight_kwargs))

# These next two matrices are really just identity matrices padded with zeros
A_slit_top = weight_matrix(nodes[slit_top], nodes, [0, 0], **weight_kwargs)
A_slit_bot = weight_matrix(nodes[slit_bot], nodes, [0, 0], **weight_kwargs)

# stack all the matrices
Example #7
0
File: fd.m.py Project: cossatot/RBF
d_z[groups['boundary:sides']] = 0.0
d_z[groups['boundary:bottom']] = 0.0
d_z[groups['pinned']] = 0.0

d = np.hstack((d_x, d_y, d_z))

# solve the system using an ILU decomposition and GMRES
u = gmres_ilu_solve(G, d)
u = np.reshape(u,(3, -1))
u_x, u_y, u_z = u

# Calculate strain and stress from displacements
D_x = weight_matrix(
    nodes, 
    nodes, 
    (1, 0, 0), 
    n=stencil_size, 
    basis=basis, 
    order=poly_order)

D_y = weight_matrix(
    nodes, 
    nodes, 
    (0, 1, 0), 
    n=stencil_size, 
    basis=basis, 
    order=poly_order)

D_z = weight_matrix(
    nodes, 
    nodes, 
Example #8
0
# build the "right hand side" vectors for roller constraints
b_roller_n = np.zeros_like(roller_idx) # enforce zero normal displacement
b_roller_p1 = np.zeros_like(roller_idx) # enforce zero parallel traction
b_roller_p2 = np.zeros_like(roller_idx) # enforce zero parallel traction
# stack it all together and solve
A = vstack((A_body_x,A_body_y,A_body_z,
            A_surf_x,A_surf_y,A_surf_z,
            A_roller_n,A_roller_p1,A_roller_p2)).tocsr()
b = np.hstack((b_body_x,b_body_y,b_body_z,
               b_surf_x,b_surf_y,b_surf_z,
               b_roller_n,b_roller_p1,b_roller_p2))
u = spsolve(A,b,permc_spec='MMD_ATA')
u = np.reshape(u,(3,-1))
u_x,u_y,u_z = u
# Calculate strain from displacements
D_x = weight_matrix(nodes,nodes,(1,0,0),n=n)
D_y = weight_matrix(nodes,nodes,(0,1,0),n=n)
D_z = weight_matrix(nodes,nodes,(0,0,1),n=n)
e_xx = D_x.dot(u_x)
e_yy = D_y.dot(u_y)
e_zz = D_z.dot(u_z)
e_xy = 0.5*(D_y.dot(u_x) + D_x.dot(u_y))
e_xz = 0.5*(D_z.dot(u_x) + D_x.dot(u_z))
e_yz = 0.5*(D_z.dot(u_y) + D_y.dot(u_z))
# Calculate stress from Hooks law
s_xx = (2*mu + lamb)*e_xx + lamb*e_yy + lamb*e_zz
s_yy = lamb*e_xx + (2*mu + lamb)*e_yy + lamb*e_zz
s_zz = lamb*e_xx + lamb*e_yy + (2*mu + lamb)*e_zz
s_xy = 2*mu*e_xy
s_xz = 2*mu*e_xz
s_yz = 2*mu*e_yz
Example #9
0
File: fd.k.py Project: cossatot/RBF
                                  mu=mu,
                                  n=stencil_size,
                                  order=order,
                                  basis=basis)
D_xx = add_rows(D_xx, components['xx'], idx['boundary:all'])
D_xy = add_rows(D_xy, components['xy'], idx['boundary:all'])
D_yx = add_rows(D_xy, components['yx'], idx['boundary:all'])
D_yy = add_rows(D_yy, components['yy'], idx['boundary:all'])

# the ghost node components are left as zero

D = sp.vstack((sp.hstack((D_xx, D_xy)), sp.hstack((D_yx, D_yy)))).tocsc()

L = weight_matrix(nodes,
                  nodes,
                  diffs=[[6, 0], [0, 6]],
                  n=stencil_size,
                  basis=rbf.basis.phs7,
                  order=6)
L = sp.block_diag((L, L))
I = sp.eye(L.shape[0])
R = np.linalg.inv((I + 1e-14 * L.T.dot(L)).A)


def f(t, z):
    ''' 
  Function used for time integration. This calculates the time 
  derivative of the current state vector. 
  '''
    u, v = z.reshape((2, -1))
    dudt = v
    h = Binv.dot(u)
Example #10
0
# add ghost nodes
ghost_nodes = make_ghost_nodes(nodes,smpid,boundary,vert,smp)
nodes = np.vstack((nodes,ghost_nodes))
# ghost node indices
ghost = N + np.arange(len(boundary))

# do not build stencils which cross this line
bnd_vert = np.array([[0.0,0.0],[5.0,0.0]])
bnd_smp = np.array([[0,1]])

weight_kwargs = {'vert':bnd_vert,'smp':bnd_smp,'n':20,'order':2}

# build lhs
# enforce laplacian on interior nodes
A_interior = weight_matrix(nodes[interior],nodes,
                           [[2,0],[0,2]],
                           **weight_kwargs)
A_ghost = weight_matrix(nodes[boundary],nodes,
                        [[2,0],[0,2]],
                        **weight_kwargs)

# find boundary normal vectors
normals = simplex_outward_normals(vert,smp)[smpid[boundary]]
n1 = scipy.sparse.diags(normals[:,0],0)
n2 = scipy.sparse.diags(normals[:,1],0)
# enforce free surface boundary conditions
A_boundary = (n1*weight_matrix(nodes[boundary],nodes,[1,0],**weight_kwargs) +
              n2*weight_matrix(nodes[boundary],nodes,[0,1],**weight_kwargs))

# These next two matrices are really just identity matrices padded with zeros
A_slit_top = weight_matrix(nodes[slit_top],nodes,[0,0],**weight_kwargs)
Example #11
0
# generate nodes
nodes, groups, normals = min_energy_nodes(N_nominal,
                                          vert,
                                          smp,
                                          boundary_groups=boundary_groups,
                                          boundary_groups_with_ghosts=['free'],
                                          include_vertices=True)

N = nodes.shape[0]

# create the "left hand side" matrix.
# create the component which evaluates the PDE
A_interior = weight_matrix(nodes[groups['interior']],
                           nodes,
                           n=n,
                           diffs=[[2, 0], [0, 2]],
                           basis=basis,
                           order=order)

# use the ghost nodes to evaluate the PDE at the free boundary nodes
A_ghost = weight_matrix(nodes[groups['boundary:free']],
                        nodes,
                        n=n,
                        diffs=[[2, 0], [0, 2]],
                        basis=basis,
                        order=order)

# create the component for the fixed boundary conditions. This is
# essentially an identity operation and so we only need a stencil size
# of 1
A_fixed = weight_matrix(nodes[groups['boundary:fixed']],
Example #12
0
from rbf.geometry import contains
import matplotlib.pyplot as plt
from scipy.integrate import ode
from scipy.interpolate import griddata

# define the problem domain
vert = np.array([[0.0, 0.0], [2.0, 0.0], [2.0, 1.0], [1.0, 1.0], [1.0, 2.0],
                 [0.0, 2.0]])
smp = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]])
times = np.linspace(0.0, 2.0, 5)  # output times
N = 50000  # total number of nodes
nodes, smpid = menodes(N, vert, smp)  # generate nodes
interior = np.nonzero(smpid == -1)[0].tolist()  # identify boundary nodes
boundary = np.nonzero(smpid >= 0)[0].tolist()  # identify boundary nodes
# create differentiation matrices for the interior and boundary nodes
D = weight_matrix(nodes[interior], nodes, [(2, 0), (0, 2)], n=30)
# create initial and boundary conditions
r = np.sqrt((nodes[interior, 0] - 0.5)**2 + (nodes[interior, 1] - 0.5)**2)
u_init = 1.0 / (1 + (r / 0.05)**4)  # initial u in the interior
dudt_init = np.zeros(len(interior))  # initial velocity in the interior
u_bnd = np.zeros(len(boundary))  # boundary conditions
# Make state vector containing the initial displacements and velocities
v = np.hstack([u_init, dudt_init])


def f(t, v):
    ''' 
  Function used for time integration. This calculates the time 
  derivative of the current state vector. 
  '''
    v = v.reshape((2, -1))
Example #13
0
# define the problem domain
vert = np.array([[0.762,0.057],[0.492,0.247],[0.225,0.06 ],[0.206,0.056],
                 [0.204,0.075],[0.292,0.398],[0.043,0.609],[0.036,0.624],
                 [0.052,0.629],[0.373,0.63 ],[0.479,0.953],[0.49 ,0.966],
                 [0.503,0.952],[0.611,0.629],[0.934,0.628],[0.95 ,0.622],
                 [0.941,0.607],[0.692,0.397],[0.781,0.072],[0.779,0.055]])
smp = np.array([[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],
                [9,10],[10,11],[11,12],[12,13],[13,14],[14,15],[15,16],
                [16,17],[17,18],[18,19],[19,0]])
dt = 0.000025 # time step size
N = 100000 # total number of nodes
nodes,smpid = menodes(N,vert,smp) # generate nodes
boundary, = (smpid>=0).nonzero() # identify boundary nodes
interior, = (smpid==-1).nonzero() # identify interior nodes
D = weight_matrix(nodes[interior],nodes,[[2,0],[0,2]],n=30)
r = np.linalg.norm(nodes-np.array([0.49,0.46]),axis=1)
u_prev = 1.0/(1 + (r/0.01)**4) # create initial conditions
u_curr = 1.0/(1 + (r/0.01)**4)
fig,axs = plt.subplots(2,2,figsize=(7,7))
axs = [axs[0][0],axs[0][1],axs[1][0],axs[1][1]]
for i in range(15001):
  u_next = dt**2*D.dot(u_curr) + 2*u_curr[interior] - u_prev[interior]
  u_prev[:] = u_curr
  u_curr[interior] = u_next
  if i in [0,5000,10000,15000]:  
    ax = axs[[0,5000,10000,15000].index(i)]
    p = ax.scatter(nodes[:,0],nodes[:,1],s=3,c=np.array(u_curr,copy=True),
                   edgecolor='none',cmap='viridis',vmin=-0.1,vmax=0.1)
    for s in smp: ax.plot(vert[s,0],vert[s,1],'k-')
    ax.set_aspect('equal')
Example #14
0
# performed well for me and they do not require the user
# to tune a shape parameter. Use higher order
# polyharmonic splines for higher order PDEs.

order = 2  # Order of the added polynomials. This should be at least as
# large as the order of the PDE being solved (2 in this
# case). Larger values may improve accuracy

# generate nodes
nodes, smpid = menodes(N, vert, smp)
edge_idx, = (smpid >= 0).nonzero()
interior_idx, = (smpid == -1).nonzero()
# create "left hand side" matrix
A_int = weight_matrix(nodes[interior_idx],
                      nodes,
                      diffs=[[2, 0], [0, 2]],
                      n=n,
                      basis=basis,
                      order=order)
A_edg = weight_matrix(nodes[edge_idx], nodes, diffs=[0, 0])
A = vstack((A_int, A_edg))
# create "right hand side" vector
d_int = -1 * np.ones_like(interior_idx)
d_edg = np.zeros_like(edge_idx)
d = np.hstack((d_int, d_edg))
# find the solution at the nodes
u_soln = spsolve(A, d)
# interpolate the solution on a grid
xg, yg = np.meshgrid(np.linspace(-0.05, 2.05, 400),
                     np.linspace(-0.05, 2.05, 400))
points = np.array([xg.flatten(), yg.flatten()]).T
u_itp = LinearNDInterpolator(nodes, u_soln)(points)
Example #15
0
File: fd.i.py Project: dhadjia1/RBF
             # order polyharmonic splines (e.g., phs3) have always
             # performed well for me and they do not require the user
             # to tune a shape parameter. Use higher order
             # polyharmonic splines for higher order PDEs.

order = 2 # Order of the added polynomials. This should be at least as
          # large as the order of the PDE being solved (2 in this
          # case). Larger values may improve accuracy

# generate nodes
nodes, groups, _ = min_energy_nodes(N, vert, smp) 

# create the "left hand side" matrix. 
# create the component which evaluates the PDE
A_interior = weight_matrix(nodes[groups['interior']], nodes,
                           diffs=[[2, 0], [0, 2]], n=n, 
                           basis=basis, order=order)
# create the component for the fixed boundary conditions
A_boundary = weight_matrix(nodes[groups['boundary:all']], nodes, 
                           diffs=[0, 0]) 
# Add the components to the corresponding rows of `A`
A = csc_matrix((N, N))
A = add_rows(A,A_interior,groups['interior'])
A = add_rows(A,A_boundary,groups['boundary:all'])
                           
# create "right hand side" vector
d = np.zeros((N,))
d[groups['interior']] = -1.0
d[groups['boundary:all']] = 0.0

# find the solution at the nodes
Example #16
0
# define a circular domain
vert,smp = rbf.domain.circle()

nodes,smpid = menodes(N,vert,smp)
# smpid describes which boundary simplex, if any, the nodes are 
# attached to. If it is -1, then the node is in the interior
boundary, = (smpid>=0).nonzero()
interior, = (smpid==-1).nonzero()

# create the left-hand-side matrix which is the Laplacian of the basis 
# function for interior nodes and the undifferentiated basis functions 
# for the boundary nodes. The third argument to weight_matrix 
# describes the derivates order for each spatial dimension
A = scipy.sparse.lil_matrix((N,N))
A[interior,:]  = weight_matrix(nodes[interior],nodes,[[2,0],[0,2]])
A[boundary,:]  = weight_matrix(nodes[boundary],nodes,[0,0])
# convert A to a csr matrix for efficient solving
A = A.tocsr()

# create the right-hand-side vector, consisting of the forcing term 
# for the interior nodes and zeros for the boundary nodes
d = np.zeros(N)
d[interior] = forcing(nodes[interior,0],nodes[interior,1]) 
d[boundary] = true_soln(nodes[boundary,0],nodes[boundary,1])

# find the solution at the nodes
u = scipy.sparse.linalg.spsolve(A,d)
err = u - true_soln(nodes[:,0],nodes[:,1])

# plot the results
Example #17
0
# define the problem domain
vert = np.array([[0.762, 0.057], [0.492, 0.247], [0.225, 0.06], [0.206, 0.056],
                 [0.204, 0.075], [0.292, 0.398], [0.043, 0.609],
                 [0.036, 0.624], [0.052, 0.629], [0.373, 0.63], [0.479, 0.953],
                 [0.49, 0.966], [0.503, 0.952], [0.611, 0.629], [0.934, 0.628],
                 [0.95, 0.622], [0.941, 0.607], [0.692, 0.397], [0.781, 0.072],
                 [0.779, 0.055]])
smp = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8],
                [8, 9], [9, 10], [10, 11], [11, 12], [12, 13], [13, 14],
                [14, 15], [15, 16], [16, 17], [17, 18], [18, 19], [19, 0]])
dt = 0.000025  # time step size
N = 100000  # total number of nodes
nodes, smpid = menodes(N, vert, smp)  # generate nodes
boundary, = (smpid >= 0).nonzero()  # identify boundary nodes
interior, = (smpid == -1).nonzero()  # identify interior nodes
D = weight_matrix(nodes[interior], nodes, [[2, 0], [0, 2]], n=30)
r = np.linalg.norm(nodes - np.array([0.49, 0.46]), axis=1)
u_prev = 1.0 / (1 + (r / 0.01)**4)  # create initial conditions
u_curr = 1.0 / (1 + (r / 0.01)**4)
fig, axs = plt.subplots(2, 2, figsize=(7, 7))
axs = [axs[0][0], axs[0][1], axs[1][0], axs[1][1]]
for i in range(15001):
    u_next = dt**2 * D.dot(u_curr) + 2 * u_curr[interior] - u_prev[interior]
    u_prev[:] = u_curr
    u_curr[interior] = u_next
    if i in [0, 5000, 10000, 15000]:
        ax = axs[[0, 5000, 10000, 15000].index(i)]
        p = ax.scatter(nodes[:, 0],
                       nodes[:, 1],
                       s=3,
                       c=np.array(u_curr, copy=True),
Example #18
0
from rbf.fd import weight_matrix
from rbf.nodes import min_energy_nodes
from rbf.geometry import contains
import matplotlib.pyplot as plt
from scipy.integrate import ode
from scipy.interpolate import griddata

# define the problem domain
vert = np.array([[0.0, 0.0], [2.0, 0.0], [2.0, 1.0], [1.0, 1.0], [1.0, 2.0],
                 [0.0, 2.0]])
smp = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]])
times = np.linspace(0.0, 2.0, 5)  # output times
N = 20000  # total number of nodes
nodes, idx, _ = min_energy_nodes(N, vert, smp)  # generate nodes
# create differentiation matrices for the interior and boundary nodes
D = weight_matrix(nodes[idx['interior']], nodes, [(2, 0), (0, 2)], n=30)
# create initial and boundary conditions
r = np.sqrt((nodes[idx['interior'], 0] - 0.5)**2 +
            (nodes[idx['interior'], 1] - 0.5)**2)
u_init = 1.0 / (1 + (r / 0.05)**4)  # initial u in the interior
dudt_init = np.zeros(len(idx['interior']))  # initial velocity in the interior
u_bnd = np.zeros(len(idx['boundary:all']))  # boundary conditions
# Make state vector containing the initial displacements and velocities
v = np.hstack([u_init, dudt_init])


def f(t, v):
    ''' 
  Function used for time integration. This calculates the time 
  derivative of the current state vector. 
  '''
Example #19
0
## Enforce the PDE on interior nodes AND the free surface nodes 
# x component of force resulting from displacement in the x direction.
coeffs_xx = [lamb+2*mu, mu]
diffs_xx = [(2, 0), (0, 2)]
# x component of force resulting from displacement in the y direction.
coeffs_xy = [lamb, mu]
diffs_xy = [(1, 1), (1, 1)]
# y component of force resulting from displacement in the x direction.
coeffs_yx = [mu, lamb]
diffs_yx = [(1, 1), (1, 1)]
# y component of force resulting from displacement in the y direction.
coeffs_yy = [lamb+2*mu, mu]
diffs_yy =  [(0, 2), (2, 0)]
# make the differentiation matrices that enforce the PDE on the 
# interior nodes.
D_xx = weight_matrix(nodes[groups['interior']], nodes, diffs_xx, coeffs=coeffs_xx, n=n)
D_xy = weight_matrix(nodes[groups['interior']], nodes, diffs_xy, coeffs=coeffs_xy, n=n)
D_yx = weight_matrix(nodes[groups['interior']], nodes, diffs_yx, coeffs=coeffs_yx, n=n)
D_yy = weight_matrix(nodes[groups['interior']], nodes, diffs_yy, coeffs=coeffs_yy, n=n)
G_xx = add_rows(G_xx, D_xx, groups['interior'])
G_xy = add_rows(G_xy, D_xy, groups['interior'])
G_yx = add_rows(G_yx, D_yx, groups['interior'])
G_yy = add_rows(G_yy, D_yy, groups['interior'])

# use the ghost nodes to enforce the PDE on the boundary
D_xx = weight_matrix(nodes[groups['boundary:free']], nodes, diffs_xx, coeffs=coeffs_xx, n=n)
D_xy = weight_matrix(nodes[groups['boundary:free']], nodes, diffs_xy, coeffs=coeffs_xy, n=n)
D_yx = weight_matrix(nodes[groups['boundary:free']], nodes, diffs_yx, coeffs=coeffs_yx, n=n)
D_yy = weight_matrix(nodes[groups['boundary:free']], nodes, diffs_yy, coeffs=coeffs_yy, n=n)
G_xx = add_rows(G_xx, D_xx, groups['ghosts:free'])
G_xy = add_rows(G_xy, D_xy, groups['ghosts:free'])
Example #20
0
                 [0.0, 2.0]])
smp = np.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]])
times = np.linspace(0.0, 2.0, 5)  # output times
N = 50000  # total number of nodes
nodes, smpid = menodes(N, vert, smp)  # generate nodes
interior = np.nonzero(smpid == -1)[0].tolist()  # identify boundary nodes
boundary = np.nonzero(smpid >= 0)[0].tolist()  # identify boundary nodes
# calculate surface normal vector for each boundary node
normals = simplex_outward_normals(vert, smp)[smpid[boundary]]
# dx is the shortest distance between any two nodes
dx = np.min(neighbors(nodes, 2)[1][:, 1])
# add ghost nodes to greatly improve accuracy at the free surface
nodes = np.vstack((nodes, nodes[boundary] + 0.5 * dx * normals))
ghost = range(N, N + len(boundary))  # ghost node indices
# create differentiation matrices for the interior and boundary nodes
D = weight_matrix(nodes[interior + boundary], nodes, [(2, 0), (0, 2)], n=30)
dD = weight_matrix(nodes[boundary],
                   nodes, [(1, 0), (0, 1)],
                   coeffs=normals.T,
                   n=30)
# create initial and boundary conditions
r = np.sqrt((nodes[interior + boundary, 0] - 0.5)**2 +
            (nodes[interior + boundary, 1] - 0.5)**2)
u_init = 1.0 / (1 + (r / 0.05)**4)  # initial u in the interior
dudt_init = np.zeros(N)  # initial velocity in the interior
u_bnd = np.zeros(len(boundary))  # boundary conditions
# Make state vector containing the initial displacements and velocities
v = np.hstack([u_init, dudt_init])


def f(t, v):
Example #21
0
def elastic3d_surface_force(x, nrm, p, lamb=1.0, mu=1.0, **kwargs):
    ''' 
  Returns a collection of weight matrices that estimate surface
  traction forces at *x* resulting from displacements at *p*.

  Parameters
  ----------
  x : (N,3) array
    target points which reside on a surface.
  
  nrm : (N,3) array
    surface normal vectors at each point in *x*.

  p : (M,3) array
    observation points.  

  lamb : float
    first Lame parameter
  
  mu : float
    second Lame parameter
    
  **kwargs :
    additional arguments passed to *weight_matrix*

  Returns
  -------
  out : (3,3) list of sparse matrices
    A collection of matrices which return the surface traction force 
    at *x* exerted by the material, when dotted with the displacements 
    at *p*.

  '''
    coeffs_xx = [nrm[:, 0] * (lamb + 2 * mu), nrm[:, 1] * mu, nrm[:, 2] * mu]
    diffs_xx = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    coeffs_xy = [nrm[:, 0] * lamb, nrm[:, 1] * mu]
    diffs_xy = [(0, 1, 0), (1, 0, 0)]
    coeffs_xz = [nrm[:, 0] * lamb, nrm[:, 2] * mu]
    diffs_xz = [(0, 0, 1), (1, 0, 0)]
    coeffs_yx = [nrm[:, 0] * mu, nrm[:, 1] * lamb]
    diffs_yx = [(0, 1, 0), (1, 0, 0)]
    coeffs_yy = [nrm[:, 0] * mu, nrm[:, 1] * (lamb + 2 * mu), nrm[:, 2] * mu]
    diffs_yy = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    coeffs_yz = [nrm[:, 1] * lamb, nrm[:, 2] * mu]
    diffs_yz = [(0, 0, 1), (0, 1, 0)]
    coeffs_zx = [nrm[:, 0] * mu, nrm[:, 2] * lamb]
    diffs_zx = [(0, 0, 1), (1, 0, 0)]
    coeffs_zy = [nrm[:, 1] * mu, nrm[:, 2] * lamb]
    diffs_zy = [(0, 0, 1), (0, 1, 0)]
    coeffs_zz = [nrm[:, 0] * mu, nrm[:, 1] * mu, nrm[:, 2] * (lamb + 2 * mu)]
    diffs_zz = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]
    D_xx = weight_matrix(x, p, diffs_xx, coeffs=coeffs_xx, **kwargs)
    D_xy = weight_matrix(x, p, diffs_xy, coeffs=coeffs_xy, **kwargs)
    D_xz = weight_matrix(x, p, diffs_xz, coeffs=coeffs_xz, **kwargs)
    D_yx = weight_matrix(x, p, diffs_yx, coeffs=coeffs_yx, **kwargs)
    D_yy = weight_matrix(x, p, diffs_yy, coeffs=coeffs_yy, **kwargs)
    D_yz = weight_matrix(x, p, diffs_yz, coeffs=coeffs_yz, **kwargs)
    D_zx = weight_matrix(x, p, diffs_zx, coeffs=coeffs_zx, **kwargs)
    D_zy = weight_matrix(x, p, diffs_zy, coeffs=coeffs_zy, **kwargs)
    D_zz = weight_matrix(x, p, diffs_zz, coeffs=coeffs_zz, **kwargs)
    return [[D_xx, D_xy, D_xz], [D_yx, D_yy, D_yz], [D_zx, D_zy, D_zz]]
Example #22
0
# define a circular domain
vert, smp = rbf.domain.circle()

nodes, smpid = menodes(N, vert, smp)
# smpid describes which boundary simplex, if any, the nodes are
# attached to. If it is -1, then the node is in the interior
boundary, = (smpid >= 0).nonzero()
interior, = (smpid == -1).nonzero()

# create the left-hand-side matrix which is the Laplacian of the basis
# function for interior nodes and the undifferentiated basis functions
# for the boundary nodes. The third argument to weight_matrix
# describes the derivates order for each spatial dimension
A = scipy.sparse.lil_matrix((N, N))
A[interior, :] = weight_matrix(nodes[interior], nodes, [[2, 0], [0, 2]])
A[boundary, :] = weight_matrix(nodes[boundary], nodes, [0, 0])
# convert A to a csr matrix for efficient solving
A = A.tocsr()

# create the right-hand-side vector, consisting of the forcing term
# for the interior nodes and zeros for the boundary nodes
d = np.zeros(N)
d[interior] = forcing(nodes[interior, 0], nodes[interior, 1])
d[boundary] = true_soln(nodes[boundary, 0], nodes[boundary, 1])

# find the solution at the nodes
u = scipy.sparse.linalg.spsolve(A, d)
err = u - true_soln(nodes[:, 0], nodes[:, 1])

# plot the results
Example #23
0
coeffs_xx = [lamb + 2 * mu, mu]
diffs_xx = [(2, 0), (0, 2)]
# x component of force resulting from displacement in the y direction.
coeffs_xy = [lamb, mu]
diffs_xy = [(1, 1), (1, 1)]
# y component of force resulting from displacement in the x direction.
coeffs_yx = [mu, lamb]
diffs_yx = [(1, 1), (1, 1)]
# y component of force resulting from displacement in the y direction.
coeffs_yy = [lamb + 2 * mu, mu]
diffs_yy = [(0, 2), (2, 0)]
# make the differentiation matrices that enforce the PDE on the
# interior nodes.
D_xx = weight_matrix(nodes[int_idx + free_idx],
                     nodes,
                     diffs_xx,
                     coeffs=coeffs_xx,
                     n=n)
D_xy = weight_matrix(nodes[int_idx + free_idx],
                     nodes,
                     diffs_xy,
                     coeffs=coeffs_xy,
                     n=n)
D_yx = weight_matrix(nodes[int_idx + free_idx],
                     nodes,
                     diffs_yx,
                     coeffs=coeffs_yx,
                     n=n)
D_yy = weight_matrix(nodes[int_idx + free_idx],
                     nodes,
                     diffs_yy,