Exemple #1
0
# 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, 10.0, 20)  # output times
n_nominal = 1000  # total number of nodes
lamb = 1.0
mu = 1.0
rho = 1.0
stencil_size = 30
order = 2
basis = rbf.basis.phs5
nodes, idx, normals = min_energy_nodes(
    n_nominal,
    vert,
    smp,
    boundary_groups={'all': range(len(smp))},
    boundary_groups_with_ghosts=['all'],
    include_vertices=False)
n = nodes.shape[0]

# create initial and boundary conditions
r = np.sqrt((nodes[idx['interior'], 0] - 0.5)**2 +
            (nodes[idx['interior'], 1] - 0.5)**2)

u_init = np.zeros_like(nodes)
u_init[idx['interior'], 0] = 1.0 / (1 + (r / 0.2)**4)
u_init[idx['interior'], 1] = 1.0 / (1 + (r / 0.2)**4)

v_init = np.zeros_like(nodes)
Exemple #2
0
boundary_groups_with_ghosts = ['outside_corner']
# total number of nodes
N = 1000


# define a node density function. It takes an (N, D) array of positions
# and returns an (N,) array of normalized densities between 0 and 1
def rho(x):
    r = np.sqrt((x[:, 0] - 1.0)**2 + (x[:, 1] - 1.0)**2)
    return 0.2 + 0.8 / ((r / 0.3)**4 + 1.0)


nodes, groups, normals = min_energy_nodes(
    N,
    vert,
    smp,
    rho=rho,
    boundary_groups=boundary_groups,
    boundary_groups_with_ghosts=boundary_groups_with_ghosts,
    include_vertices=True)

# plot the results
fig, ax = plt.subplots(figsize=(6, 6))
# plot the domain
for s in smp:
    ax.plot(vert[s, 0], vert[s, 1], 'k-')

# plot the different node groups and their normal vectors
for i, (name, idx) in enumerate(groups.items()):
    ax.plot(nodes[idx, 0], nodes[idx, 1], 'C%s.' % i, label=name, ms=8)
    ax.quiver(nodes[idx, 0],
              nodes[idx, 1],
Exemple #3
0
N = 500 # total number of nodes.

n = 20 # stencil size. Increase this will generally improve accuracy

basis = phs3 # radial basis function used to compute the weights. Odd
             # 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
Exemple #4
0
'''
import numpy as np
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 
Exemple #5
0
# size of RBF-FD stencils
n = 20
# lame parameters
lamb = 1.0
mu = 1.0
# z component of body force
body_force = 1.0

## Build and solve for displacements and strain
#####################################################################
# generate nodes. The nodes are assigned groups based on which simplex
# they lay on
boundary_groups = {'fixed':[0],
                   'free':[1, 2, 3]}
nodes, groups, normals = min_energy_nodes(
  N, vert, smp,
  boundary_groups=boundary_groups,
  boundary_groups_with_ghosts=['free'])
# `nodes` : (N, 2) float array
# `groups` : dictionary containing index sets. It has the keys
#            "interior", "boundary:free", "boundary:fixed",
#            "ghosts:free".
# `normals : (N, 2) float array

# update `N` to include ghost nodes
N = nodes.shape[0]

## Create the sparse submatrices for the system matrix 
G_xx = sp.csr_matrix((N, N))
G_xy = sp.csr_matrix((N, N))
G_yx = sp.csr_matrix((N, N))
G_yy = sp.csr_matrix((N, N))
Exemple #6
0
vert = np.vstack((vert_bot, vert_top))
smp = np.array([np.arange(300), np.roll(np.arange(300), -1)]).T
# number of nodes excluding ghosts
N = 2000
# size of RBF-FD stencils
n = 20
# Lame parameters
lamb = 1.0
mu = 1.0
#####################################################################
# generate nodes. Note that this may take a while
groups = {'roller': [0, 1, 299], 'free': range(2, 299)}
nodes, idx, normals = min_energy_nodes(
    N,
    vert,
    smp,
    boundary_groups=groups,
    boundary_groups_with_ghosts=['roller', 'free'],
    rho=node_density)
# update `N` to include ghosts
N = nodes.shape[0]

# allocate the left-hand-side matrix components
G_xx = sp.csc_matrix((N, N))
G_xy = sp.csc_matrix((N, N))
G_yx = sp.csc_matrix((N, N))
G_yy = sp.csc_matrix((N, N))

# build the "left hand side" matrices for body force constraints
out = elastic2d_body_force(nodes[idx['interior']],
                           nodes,
Exemple #7
0
N = 500
# size of RBF-FD stencils
n = 30
# lame parameters
lamb = 1.0
mu = 1.0
# z component of body force
body_force = 1.0

## Build and solve for displacements and strain
#####################################################################
# generate nodes. Note that this may take a while
boundary_groups = {'fix': [0, 1], 'free': range(2, 12)}
nodes, idx, normals = min_energy_nodes(N,
                                       vert,
                                       smp,
                                       boundary_groups=boundary_groups,
                                       boundary_groups_with_ghosts=['free'],
                                       include_vertices=True)
N = nodes.shape[0]

# The "left hand side" matrices are built with the convenience
# functions from *rbf.fdbuild*. Read the documentation for these
# functions to better understand this step.
G_xx = sp.csr_matrix((N, N))
G_xy = sp.csr_matrix((N, N))
G_xz = sp.csr_matrix((N, N))

G_yx = sp.csr_matrix((N, N))
G_yy = sp.csr_matrix((N, N))
G_yz = sp.csr_matrix((N, N))
Exemple #8
0
# decomposition. If the value is too large then you may get a "Factor
# is exactly singular" error.
ilu_drop_tol = 0.005

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

## GENERATE THE DOMAIN AND NODES
# generate the domain according to `topo_func`
vert, smp = topography(topo_func, [-2.0, 2.0], [-2.0, 2.0], 1.0, n=30)

# generate the nodes
boundary_groups = {'free': range(10, smp.shape[0]), 'roller': range(0, 10)}
nodes, idx, normals = min_energy_nodes(
    N,
    vert,
    smp,
    boundary_groups=boundary_groups,
    boundary_groups_with_ghosts=['free', 'roller'],
    rho=density_func,
    itr=50)
# update `N` to now include the ghost nodes
N = nodes.shape[0]

## BUILD THE LEFT-HAND-SIDE MATRIX
# allocate the left-hand-side matrix components
G_xx = sp.csc_matrix((N, N))
G_xy = sp.csc_matrix((N, N))
G_xz = sp.csc_matrix((N, N))
G_yx = sp.csc_matrix((N, N))
G_yy = sp.csc_matrix((N, N))
G_yz = sp.csc_matrix((N, N))
G_zx = sp.csc_matrix((N, N))
Exemple #9
0
    '''
  compute the density of `nodes` and evaluate the density function at
  `x`. The output is normalize 1.0
  '''
    out = np.zeros(x.shape[0])
    for n in nodes:
        out += rbf.basis.se(x, n[None, :], eps=0.01)[:, 0]

    out /= np.max(out)
    return out


vert = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])
smp = np.array([[0, 1], [1, 2], [2, 3], [3, 0]])

nodes = min_energy_nodes(10000, vert, smp, rho=desired_rho)[0]

# plot the nodes
fig, ax = plt.subplots()
for s in smp:
    ax.plot(vert[s, 0], vert[s, 1], 'k-')

ax.plot(nodes[:, 0], nodes[:, 1], 'k.', ms=1)
ax.set_aspect('equal')
ax.set_title('node positions')
fig.tight_layout()
plt.savefig('../figures/nodes.b.1.png')

fig, axs = plt.subplots(1, 2, figsize=(10, 4))

# evaluate and plot the node density
Exemple #10
0
stencil_size = 50
poly_order = 2
basis = phs3

# create the domain boundary as a simplicial complex
vert, smp, boundary_groups = topography(
    topo_func,
    xbounds,
    ybounds,
    depth,
    n=30)
# create the nodes
nodes, groups, normals = min_energy_nodes(
    nominal_node_count, 
    vert, 
    smp, 
    pinned_nodes=pinned_nodes,
    boundary_groups=boundary_groups,
    boundary_groups_with_ghosts=['surface', 'sides', 'bottom'])
node_count = nodes.shape[0]

# allocate the left-hand-side matrix components
G_xx = sp.csc_matrix((node_count, node_count))
G_xy = sp.csc_matrix((node_count, node_count))
G_xz = sp.csc_matrix((node_count, node_count))

G_yx = sp.csc_matrix((node_count, node_count))
G_yy = sp.csc_matrix((node_count, node_count))
G_yz = sp.csc_matrix((node_count, node_count))

G_zx = sp.csc_matrix((node_count, node_count))
Exemple #11
0
pinned_node = [5.0, 0.0]
groups = {'bottom': [0], 'top': [2, 3, 4, 5], 'sides': [1, 6]}

nominal_node_count = 1000
stencil_size = 30
poly_order = 2
# lame parameters
lamb = 1.0
mu = 1.0

# create the nodes
nodes, idx, normals = min_energy_nodes(
    nominal_node_count,
    vert,
    smp,
    itr=1000,
    pinned_nodes=[pinned_node],
    include_vertices=False,
    boundary_groups=groups,
    boundary_groups_with_ghosts=['top', 'bottom', 'sides'])

node_count = nodes.shape[0]

for k, v in idx.items():
    plt.plot(nodes[v, 0], nodes[v, 1], 'o', label=k, ms=5)
    plt.quiver(nodes[v, 0], nodes[v, 1], normals[v, 0], normals[v, 1])

plt.legend()
plt.show()

# allocate the left-hand-side matrix components