Beispiel #1
0
from egads4py import egads
from mpi4py import MPI
from tmr import TMR
import numpy as np
import argparse
import os
'''
Example to generate a 2D rectangular plate  with curved edges using egads4py
'''

# Create the plate geometry
l = 4.0  # length of the plate
h = 1.5  # height of the plate

# Create the egads context
ctx = egads.context()
ctx.setOutLevel(1)

x1 = [0.0, 0.0, 0.0]
x2 = [l, 0.0, 0.0]
x3 = [l, h, 0.0]
x4 = [0.0, h, 0.0]
d1 = np.array(x2) - np.array(x1)
d2 = np.array(x3) - np.array(x2)
d3 = np.array(x4) - np.array(x3)
d4 = np.array(x1) - np.array(x4)

# Make the nodes
n1 = ctx.makeTopology(egads.NODE, rdata=x1)
n2 = ctx.makeTopology(egads.NODE, rdata=x2)
n3 = ctx.makeTopology(egads.NODE, rdata=x3)
Beispiel #2
0
def create_3d_unstruct_mesh(n, AR, prob, ratio1, ratio2, hole_r,
                            forced_portion, force_magnitude, MBB_bc_portion,
                            loaded_thickness, ly):

    comm = MPI.COMM_WORLD

    # Create the egads context
    ctx = egads.context()

    # dimensions
    Lx = ly * AR
    Ly = ly
    h = ly

    parts = []

    if prob == 'lbracket':
        # Create base
        x0 = [0, 0, 0]
        x1 = [Lx * ratio1, Ly * ratio2, h]
        B0 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1])
        parts.append(ctx.makeTopology(egads.MODEL, children=[B0]))

        # Create arm 1
        x0 = [0, Ly * ratio2, 0]
        x1 = [Lx * ratio1, Ly * (1 - ratio2), h]
        B1 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1])
        parts.append(ctx.makeTopology(egads.MODEL, children=[B1]))

        # Create arm 2
        x0 = [Lx * ratio1, 0, 0]
        x1 = [Lx * (1 - ratio1), Ly * ratio2, h]
        B2 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1])

        # Create the cylinder cutout
        xc = Lx * (ratio1 + 1) * 0.5
        yc = Ly * ratio2 * 0.5
        x0 = [xc, yc, 0]
        x1 = [xc, yc, h]
        r = hole_r * Ly * ratio2
        C1 = ctx.makeSolidBody(egads.CYLINDER, rdata=[x0, x1, r])
        parts.append(B2.solidBoolean(C1, egads.SUBTRACTION))

    else:
        # Create the box
        x0 = [0, 0, 0]
        x1 = [Lx, Ly, h]
        B1 = ctx.makeSolidBody(egads.BOX, rdata=[x0, x1])

        # Create the cylinder cutout
        xc = Lx / 2
        yc = Ly / 2
        x0 = [xc, yc, 0]
        x1 = [xc, yc, h]
        r = hole_r * Ly
        C1 = ctx.makeSolidBody(egads.CYLINDER, rdata=[x0, x1, r])
        # parts.append(ctx.makeTopology(egads.MODEL, children=[B1]))
        parts.append(B1.solidBoolean(C1, egads.SUBTRACTION))

    # Create all of the models
    geos = []
    for p in parts:
        geos.append(TMR.ConvertEGADSModel(p))

    # Create the full list of vertices, edges, faces and volumes
    verts = []
    edges = []
    faces = []
    vols = []
    for geo in geos:
        verts.extend(geo.getVertices())
        edges.extend(geo.getEdges())
        faces.extend(geo.getFaces())
        vols.extend(geo.getVolumes())

    # Set all of the matching faces
    TMR.setMatchingFaces(geos)

    # Create the geometry
    geo = TMR.Model(verts, edges, faces, vols)

    # Create the new mesh
    mesh = TMR.Mesh(comm, geo)

    # Set the meshing options
    opts = TMR.MeshOptions()
    # opts.mesh_type_default = TMR.UNSTRUCTURED
    opts.write_mesh_quality_histogram = 1
    opts.triangularize_print_iter = 50000

    # Create the surface mesh
    htarget = ly / n
    mesh.mesh(htarget, opts)

    # Write the surface mesh to a file
    # mesh.writeToVTK('block.vtk', 'hex')

    # Create the model from the unstructured volume mesh
    model = mesh.createModelFromMesh()

    # Create the corresponding mesh topology from the mesh-model
    topo = TMR.Topology(comm, model)

    # Create the quad forest and set the topology of the forest
    forest = TMR.OctForest(comm)
    forest.setTopology(topo)
    forest.createTrees()
    forest.balance(1)

    # Create the nodes
    forest.createNodes()

    # Get the mesh connectivity
    conn = forest.getMeshConn()
    nnodes = np.max(conn) + 1
    nelems = len(conn)

    # Get the node locations
    X = forest.getPoints()

    # Set boundary conditions
    dof = -np.ones((nnodes, 3), dtype=int)
    geo_bc_tol = 1e-6

    if prob == 'cantilever' or prob == 'michell':
        bc_x_max = geo_bc_tol
        bc_x_min = -geo_bc_tol
        bc_y_max = Ly + geo_bc_tol
        bc_y_min = -geo_bc_tol
        bc_z_max = h + geo_bc_tol
        bc_z_min = -geo_bc_tol

        ndof = 0
        for i in range(nnodes):
            if (bc_x_min <= X[i, 0] <= bc_x_max
                    and bc_y_min <= X[i, 1] <= bc_y_max
                    and bc_z_min <= X[i, 2] <= bc_z_max):
                # This is the bc node
                pass
            else:
                dof[i, 0] = ndof
                ndof += 1
                dof[i, 1] = ndof
                ndof += 1
                dof[i, 2] = ndof
                ndof += 1

    elif prob == 'MBB':
        bc1_x_max = geo_bc_tol
        bc1_x_min = -geo_bc_tol
        bc1_y_max = Ly + geo_bc_tol
        bc1_y_min = -geo_bc_tol
        bc1_z_max = h + geo_bc_tol
        bc1_z_min = -geo_bc_tol

        bc2_x_max = Lx + geo_bc_tol
        bc2_x_min = Lx * (1 - MBB_bc_portion) - geo_bc_tol
        bc2_y_max = geo_bc_tol + geo_bc_tol
        bc2_y_min = -geo_bc_tol
        bc2_z_max = h + geo_bc_tol
        bc2_z_min = -geo_bc_tol

        ndof = 0
        for i in range(nnodes):
            if (bc1_x_min <= X[i, 0] <= bc1_x_max
                    and bc1_y_min <= X[i, 1] <= bc1_y_max
                    and bc1_z_min <= X[i, 2] <= bc1_z_max):
                # This is the bc node
                dof[i, 1] = ndof
                ndof += 1
            elif (bc2_x_min <= X[i, 0] <= bc2_x_max
                  and bc2_y_min <= X[i, 1] <= bc2_y_max
                  and bc2_z_min <= X[i, 2] <= bc2_z_max):
                # This is also bc node
                dof[i, 0] = ndof
                ndof += 1
            else:
                dof[i, 0] = ndof
                ndof += 1
                dof[i, 1] = ndof
                ndof += 1
                dof[i, 2] = ndof
                ndof += 1

    elif prob == 'lbracket':
        bc_x_max = Lx * ratio1 + geo_bc_tol
        bc_x_min = -geo_bc_tol
        bc_y_max = Ly + geo_bc_tol
        bc_y_min = Ly - geo_bc_tol
        bc_z_max = h + geo_bc_tol
        bc_z_min = -geo_bc_tol

        ndof = 0
        for i in range(nnodes):
            if (bc_x_min <= X[i, 0] <= bc_x_max
                    and bc_y_min <= X[i, 1] <= bc_y_max
                    and bc_z_min <= X[i, 2] <= bc_z_max):
                # This is the bc node
                pass
            else:
                dof[i, 0] = ndof
                ndof += 1
                dof[i, 1] = ndof
                ndof += 1
                dof[i, 2] = ndof
                ndof += 1

    # Set loading
    force = np.zeros(ndof)
    geo_tol = 1e-6

    if prob == 'cantilever':
        load_x_max = Lx + geo_tol
        load_x_min = Lx - geo_tol
        load_y_max = Ly * forced_portion + geo_tol
        load_y_min = -geo_tol
        load_z_max = 0.5 * h * (1 + loaded_thickness)
        load_z_min = 0.5 * h * (1 - loaded_thickness)

        force_dir = 1
        force_scal = -1.0

    elif prob == 'MBB':
        load_x_max = Lx * MBB_bc_portion + geo_tol
        load_x_min = -geo_tol
        load_y_max = Ly + geo_tol
        load_y_min = Ly - geo_tol
        load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol
        load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol

        force_dir = 1
        force_scal = -1.0

    elif prob == 'michell':
        load_x_max = Lx + geo_tol
        load_x_min = Lx - geo_tol
        load_y_max = 0.5 * Ly * (1 + forced_portion) + geo_tol
        load_y_min = 0.5 * Ly * (1 - forced_portion) - geo_tol
        load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol
        load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol

        force_dir = 1
        force_scal = -1.0

    elif prob == 'lbracket':
        load_x_max = Lx + geo_tol
        load_x_min = Lx - geo_tol
        load_y_max = Ly * ratio2 + geo_tol
        load_y_min = Ly * ratio2 * (1 - forced_portion) - geo_tol
        load_z_max = 0.5 * h * (1 + loaded_thickness) + geo_tol
        load_z_min = 0.5 * h * (1 - loaded_thickness) - geo_tol

        force_dir = 1
        force_scal = -1.0

    nforce = 0
    for i in range(nnodes):
        if (load_x_min <= X[i, 0] <= load_x_max
                and load_y_min <= X[i, 1] <= load_y_max
                and load_z_min <= X[i, 2] <= load_z_max):
            force[dof[i, force_dir]] = force_scal * force_magnitude
            nforce += 1

    force /= nforce

    # for n in range(X.shape[0]):
    #     print('node:{:4d} x:{:6f} y:{:6f} z:{:6f}'.format(n, X[n, 0], X[n, 1], X[n, 2]))

    # for ne in range(conn.shape[0]):
    #     print('elem:{:4d} conn = [{:3d} {:3d} {:3d} {:3d}]'.format(ne, conn[ne,0], conn[ne,1], conn[ne,2], conn[ne,3]))

    return nelems, nnodes, ndof, conn, X, dof, force