PLATE

This function performs plate and shell analysis by building a finite element surface model from material properties, optional generated meshes, optional manually defined plate elements, supports, and pressure loads. It returns nodal displacement/reaction summaries and plate force result tables, depending on the selected output mode.

The solver applies linear elastic finite element equilibrium over plate degrees of freedom:

\mathbf{K}\mathbf{u} = \mathbf{F}

where \mathbf{K} is the assembled plate stiffness matrix, \mathbf{u} contains nodal displacement/rotation unknowns, and \mathbf{F} represents external nodal and equivalent surface load effects. Derived plate quantities (such as moment components) are then evaluated from the solved field.

Excel Usage

=PLATE(materials, meshes, plates, nodes, supports, pressures, pynite_plate_output)
  • materials (list[list], required): Materials [name, E, nu, rho].
  • meshes (list[list], optional, default: []): Rectangular meshes [name, width, height, div_x, div_y, material, thickness, origin_x, origin_y, origin_z].
  • plates (list[list], optional, default: []): Manual plates [name, n1, n2, n3, n4, material, thickness].
  • nodes (list[list], optional, default: []): Manual nodes [name, x, y, z].
  • supports (list[list], optional, default: []): Supports [node, fix_dx, fix_dy, fix_dz, fix_rx, fix_ry, fix_rz]. Bools.
  • pressures (list[list], optional, default: []): Uniform pressures [plate_or_mesh, pressure].
  • pynite_plate_output (str, optional, default: “Displacements”): Output type.

Returns (list[list]): Analysis results.

Example 1: Mesh nodal displacements under uniform surface pressure

Inputs:

materials meshes supports pressures pynite_plate_output
Concrete 3000000 0.2 0.15 Mesh1 10 10 2 2 Concrete 0.5 0 0 0 Mesh1_N_0_0 true true true true true true Mesh1 -10 Displacements

Excel formula:

=PLATE({"Concrete",3000000,0.2,0.15}, {"Mesh1",10,10,2,2,"Concrete",0.5,0,0,0}, {"Mesh1_N_0_0",TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}, {"Mesh1",-10}, "Displacements")

Expected output:

Node Dx Dy Dz
Mesh1_N_0_0 0 0 0
Mesh1_N_0_1 0 0 -0.552582
Mesh1_N_0_2 0 0 -1.45879
Mesh1_N_1_0 0 0 -0.552582
Mesh1_N_1_1 0 0 -1.47975
Mesh1_N_1_2 0 0 -2.43399
Mesh1_N_2_0 0 0 -1.45879
Mesh1_N_2_1 0 0 -2.43399
Mesh1_N_2_2 0 0 -3.39759
Example 2: Supported corner reaction summary for a single mesh panel

Inputs:

materials meshes supports pressures pynite_plate_output
Concrete 3000 0.2 0.15 M1 5 5 1 1 Concrete 0.5 0 0 0 M1_N_0_0 true true true true true true M1 -1 Reactions

Excel formula:

=PLATE({"Concrete",3000,0.2,0.15}, {"M1",5,5,1,1,"Concrete",0.5,0,0,0}, {"M1_N_0_0",TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}, {"M1",-1}, "Reactions")

Expected output:

Node Rx Ry Rz
M1_N_0_0 0 0 25
M1_N_0_1 0 0 0
M1_N_1_0 0 0 0
M1_N_1_1 0 0 0
Example 3: Plate center force and shear result sample

Inputs:

materials nodes plates supports pressures pynite_plate_output
Steel 29000 0.3 0.283 N1 0 0 0 P1 N1 N2 N3 N4 Steel 0.2 N1 true true true true true true P1 -5 PlateForces
N2 10 0 0 N2 true true true true true true
N3 10 10 0
N4 0 10 0

Excel formula:

=PLATE({"Steel",29000,0.3,0.283}, {"N1",0,0,0;"N2",10,0,0;"N3",10,10,0;"N4",0,10,0}, {"P1","N1","N2","N3","N4","Steel",0.2}, {"N1",TRUE,TRUE,TRUE,TRUE,TRUE,TRUE;"N2",TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}, {"P1",-5}, "PlateForces")

Expected output:

Plate Mx My Mxy Qx Qy
P1 4.34028 -83.3333 1.17832e-14 -9.32486e-15 -29.9603
Example 4: Combined plate displacement reaction and force output

Inputs:

materials meshes supports pressures pynite_plate_output
Concrete 3000 0.2 0.15 M1 5 5 1 1 Concrete 0.5 0 0 0 M1_N_0_0 true true true true true true M1 -1 Stacked

Excel formula:

=PLATE({"Concrete",3000,0.2,0.15}, {"M1",5,5,1,1,"Concrete",0.5,0,0,0}, {"M1_N_0_0",TRUE,TRUE,TRUE,TRUE,TRUE,TRUE}, {"M1",-1}, "Stacked")

Expected output:

Node Dx Dy Dz
M1_N_0_0 0 0 0
M1_N_0_1 0 0 -6.16228
M1_N_1_0 0 0 -6.16228
M1_N_1_1 0 0 -15.3246
Node Rx Ry Rz
M1_N_0_0 0 0 25
M1_N_0_1 0 0 0
M1_N_1_0 0 0 0
M1_N_1_1 0 0 0
Plate Mx My Mxy Qx Qy
M1_Q_0_0 -4.16667 -4.16667 0.171327 -4.77865 -4.77865

Python Code

Show Code
from Pynite import FEModel3D

def plate(materials, meshes=[], plates=[], nodes=[], supports=[], pressures=[], pynite_plate_output='Displacements'):
    """
    Analyze 2D plates and shells. Supports rectangular meshing or manual quad definition.

    See: https://pynite.readthedocs.io/en/latest/plate.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        materials (list[list]): Materials [name, E, nu, rho].
        meshes (list[list], optional): Rectangular meshes [name, width, height, div_x, div_y, material, thickness, origin_x, origin_y, origin_z]. Default is [].
        plates (list[list], optional): Manual plates [name, n1, n2, n3, n4, material, thickness]. Default is [].
        nodes (list[list], optional): Manual nodes [name, x, y, z]. Default is [].
        supports (list[list], optional): Supports [node, fix_dx, fix_dy, fix_dz, fix_rx, fix_ry, fix_rz]. Bools. Default is [].
        pressures (list[list], optional): Uniform pressures [plate_or_mesh, pressure]. Default is [].
        pynite_plate_output (str, optional): Output type. Valid options: Displacements, Reactions, Plate Forces/Moments, Stacked Results. Default is 'Displacements'.

    Returns:
        list[list]: Analysis results.
    """
    try:
        def to2d(x): return [[x]] if not isinstance(x, list) else x
        model = FEModel3D()

        # Materials
        for row in to2d(materials):
            if not row: continue
            name = str(row[0])
            E = float(row[1])
            nu = float(row[2])
            rho = float(row[3])
            G = E / (2 * (1 + nu)) # Calculate G
            model.add_material(name, E, G, nu, rho)

        # Nodes (Manual)
        for row in to2d(nodes):
            if not row: continue
            model.add_node(str(row[0]), float(row[1]), float(row[2]), float(row[3]))

        # Meshes
        for row in to2d(meshes):
            if not row: continue
            name, w, h, div_x, div_y, mat, thick = str(row[0]), float(row[1]), float(row[2]), int(row[3]), int(row[4]), str(row[5]), float(row[6])
            ox = float(row[7]) if len(row) > 7 else 0
            oy = float(row[8]) if len(row) > 8 else 0
            oz = float(row[9]) if len(row) > 9 else 0

            dx_inc, dy_inc = w / div_x, h / div_y

            # Generate mesh manually for robustness
            node_map = {}
            for i in range(div_x + 1):
                for j in range(div_y + 1):
                     nx, ny, nz = ox + i * dx_inc, oy + j * dy_inc, oz
                     n_name = f"{name}_N_{i}_{j}"
                     model.add_node(n_name, nx, ny, nz)
                     node_map[(i,j)] = n_name

            for i in range(div_x):
                for j in range(div_y):
                     p_name = f"{name}_Q_{i}_{j}"
                     n1, n2, n3, n4 = node_map[(i,j)], node_map[(i+1,j)], node_map[(i+1,j+1)], node_map[(i,j+1)]
                     model.add_plate(p_name, n1, n2, n3, n4, thick, mat)

        # Manual Plates
        for row in to2d(plates):
            if not row: continue
            model.add_plate(str(row[0]), str(row[1]), str(row[2]), str(row[3]), str(row[4]), float(row[6]), str(row[5]))

        # Supports
        for row in to2d(supports):
            if not row: continue
            n = str(row[0])
            flags = [bool(x) for x in row[1:7]]
            model.def_support(n, *flags)

        # Pressures
        for row in to2d(pressures):
            if not row: continue
            target = str(row[0])
            press = float(row[1])
            # Target could be a single plate or a mesh prefix?
            # Simple check:
            if target in model.plates:
                 model.add_plate_surface_pressure(target, press)
            else:
                 # Try prefix match
                 for p_name in model.plates:
                     if p_name.startswith(target):
                         model.add_plate_surface_pressure(p_name, press)

        # Add load combination and analyze
        model.add_load_combo('Combo 1', {'Case 1': 1.0})
        model.analyze(check_statics=False)

        # Safe result helper
        def get_val(obj, attr, *args):
            try:
                val = getattr(obj, attr)
                if callable(val): val = val(*args)
                if isinstance(val, dict): return float(val.get('Combo 1', 0.0))
                return float(val)
            except: return 0.0

        def flatten_result(value):
            if hasattr(value, 'flatten'):
                value = value.flatten().tolist()
            elif isinstance(value, tuple):
                value = list(value)
            return value

        res = []
        # max_cols = 6 for Stacked compatibility (PlateForces has 6)
        if pynite_plate_output == 'Displacements' or pynite_plate_output == 'Stacked':
            header = ['Node', 'Dx', 'Dy', 'Dz']
            if pynite_plate_output == 'Stacked': header += [''] * 2
            res.append(header)
            for n_nm in model.nodes:
                n = model.nodes[n_nm]
                row = [n_nm, get_val(n, 'DX'), get_val(n, 'DY'), get_val(n, 'DZ')]
                if pynite_plate_output == 'Stacked': row += [''] * 2
                res.append(row)

        if pynite_plate_output == 'Reactions' or pynite_plate_output == 'Stacked':
            header = ['Node', 'Rx', 'Ry', 'Rz']
            if pynite_plate_output == 'Stacked': header += [''] * 2
            res.append(header)
            for n_nm in model.nodes:
                n = model.nodes[n_nm]
                row = [n_nm, get_val(n, 'RxnFX'), get_val(n, 'RxnFY'), get_val(n, 'RxnFZ')]
                if pynite_plate_output == 'Stacked': row += [''] * 2
                res.append(row)

        if pynite_plate_output == 'PlateForces' or pynite_plate_output == 'Stacked':
            res.append(['Plate', 'Mx', 'My', 'Mxy', 'Qx', 'Qy'])
            for p_nm in model.plates:
                p = model.plates[p_nm]
                try:
                    center_x = ((p.j_node.X - p.i_node.X)**2 + (p.j_node.Y - p.i_node.Y)**2 + (p.j_node.Z - p.i_node.Z)**2)**0.5 / 2
                    center_y = ((p.n_node.X - p.i_node.X)**2 + (p.n_node.Y - p.i_node.Y)**2 + (p.n_node.Z - p.i_node.Z)**2)**0.5 / 2
                    moment = flatten_result(p.moment(center_x, center_y, combo_name='Combo 1'))
                    shear = flatten_result(p.shear(center_x, center_y, combo_name='Combo 1'))
                    res.append([
                        p_nm,
                        float(moment[0]),
                        float(moment[1]),
                        float(moment[2]),
                        float(shear[0]),
                        float(shear[1]),
                    ])
                except:
                    res.append([p_nm, 0, 0, 0, 0, 0])


        return res
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Materials [name, E, nu, rho].
Rectangular meshes [name, width, height, div_x, div_y, material, thickness, origin_x, origin_y, origin_z].
Manual plates [name, n1, n2, n3, n4, material, thickness].
Manual nodes [name, x, y, z].
Supports [node, fix_dx, fix_dy, fix_dz, fix_rx, fix_ry, fix_rz]. Bools.
Uniform pressures [plate_or_mesh, pressure].
Output type.