Example #1
0
File: fem.py Project: basic-ph/feat
def vector_analysis(mesh, element_type, post_process=False, vtk_filename=None):
    # MESH
    # mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map
    logger.debug("mesh info: %d elements, %d nodes", num_elements, num_nodes)
    # DATA
    load_condition = "plane strain"  # "plane stress" or "plane strain"
    thickness = 1
    # MATERIAL
    matrix = base.Material("matrix", 4, 0.38, load_condition)  # BSL914C epoxy
    fiber = base.Material("fiber", 15, 0.07,
                          load_condition)  # T300 carbon fiber

    # BOUNDARY CONDITIONS INSTANCES
    left_side = bc.DirichletBC("left side", mesh, [0], 0.0)
    bl_corner = bc.DirichletBC("bottom left corner", mesh, [1], 0.0)
    right_side = bc.DirichletBC("right side", mesh, [0], 1.0)

    # ASSEMBLY
    E_array = vector.compute_E_array(num_elements, material_map,
                                     mesh.field_data, matrix, fiber)
    R = np.zeros(num_nodes * 2)
    K = vector.assembly(num_elements, num_nodes, elements, nodal_coord,
                        E_array, thickness)

    # save constrained dof rows of K
    # dirichlet dof are built only for boundaries with related reactions
    dirichlet_dof, dirichlet_values = bc.build_dirichlet_data(
        left_side, bl_corner)
    K = K.tocsr()
    K_rows = K[dirichlet_dof, :]
    K = K.tocsc()

    # BOUNDARY CONDITIONS APPLICATION
    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, bl_corner,
                                 right_side)
    # SOLVER
    D = linalg.spsolve(K, R)
    reactions = K_rows.dot(D)
    modulus = base.compute_modulus(nodal_coord, right_side, reactions,
                                   thickness)
    logger.debug("E2 = %f", modulus)

    if post_process:
        D_ready = np.column_stack((D[::2], D[1::2], np.zeros(num_nodes)))
        D_dict = {"displacement": D_ready}
        mesh.point_data = D_dict
        mesh.write(f"../data/vtk/sample/{vtk_filename}.vtk")
        logger.debug("VTK file created")

    return modulus
Example #2
0
File: fem.py Project: basic-ph/feat
def sp_base_analysis(mesh, element_type):
    # MESH
    # mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map
    logger.debug("mesh info: %d elements, %d nodes", num_elements, num_nodes)
    # DATA
    integration_points = 1  # hard-coded but could be removed
    load_condition = "plane strain"  # TODO also this could be removed 'cause we need only plane strain case
    thickness = 1  # TODO make this a passed argument?
    # MATERIAL
    matrix = base.Material("matrix", 10, 0.3, load_condition)
    fiber = base.Material("fiber", 100, 0.3, load_condition)

    # BOUNDARY CONDITIONS INSTANCES
    left_side = bc.DirichletBC("left side", mesh, [0], 0.0)
    bl_corner = bc.DirichletBC("bottom left corner", mesh, [1], 0.0)
    right_side = bc.DirichletBC("right side", mesh, [0], 1.0)

    # ASSEMBLY
    E_material = base.compute_E_material(num_elements, material_map,
                                         mesh.field_data, matrix, fiber)
    K = sparse.csc_matrix((2 * num_nodes, 2 * num_nodes))
    R = np.zeros(num_nodes * 2)
    K = base.sp_assembly(K, num_elements, num_nodes, elements, nodal_coord,
                         material_map, E_material, thickness, element_type)

    # save constrained dof rows of K
    # dirichlet dof are built only for boundaries with related reactions
    dirichlet_dof, dirichlet_values = bc.build_dirichlet_data(
        left_side, bl_corner)
    K = K.tocsr()
    K_rows = K[dirichlet_dof, :]
    K = K.tocsc()

    # BOUNDARY CONDITIONS APPLICATION
    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, bl_corner,
                                 right_side)
    # SOLVER
    D = linalg.spsolve(K, R)
    reactions = K_rows.dot(D)
    modulus = base.compute_modulus(nodal_coord, right_side, reactions,
                                   thickness)
    logger.debug("E2 = %f", modulus)

    return modulus
Example #3
0
def test_build_dirichlet_data():

    mesh_path = "tests/data/msh/base.msh"
    mesh = meshio.read(mesh_path)

    left_side = bc.DirichletBC("left side", mesh, [0], 0.0)
    bl_corner = bc.DirichletBC("bottom left corner", mesh, [1], 0.0)
    right_side = bc.DirichletBC("right side", mesh, [0], 1.0)

    dirichlet_dof, dirichlet_values = bc.build_dirichlet_data(
        left_side, bl_corner, right_side)
    dir_dof_true = np.array([0, 6, 1, 2, 4])
    dir_values_true = np.array([0., 0., 0., 1., 1.])

    np.testing.assert_allclose(dir_dof_true, dirichlet_dof)
    np.testing.assert_allclose(dir_values_true, dirichlet_values)
Example #4
0
def test_sparse_fem():
    mesh_path = "tests/data/msh/test.msh"

    element_type = "triangle"
    load_condition = "plane stress"  # "plane stress" or "plane strain"
    thickness = 0.5
    steel = base.Material("steel", 3e7, 0.25, load_condition)

    mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map

    left_side = bc.DirichletBC("left side", mesh, [0, 1], 0.0)
    br_corner = bc.DirichletBC("bottom right corner", mesh, [1], 0.0)
    tr_corner = bc.NeumannBC("top right corner", mesh, [1], -1000.0)

    E_material = base.compute_E_material(num_elements, material_map,
                                         mesh.field_data, steel)
    K = sparse.csc_matrix((2 * num_nodes, 2 * num_nodes))
    R = np.zeros(num_nodes * 2)
    # for e in range(num_elements):
    #     K = base.sparse_assembly(K, e, mesh, E_material, thickness, element_type, integration_points)
    K = base.sp_assembly(K, num_elements, num_nodes, elements, nodal_coord,
                         material_map, E_material, thickness, element_type)

    print(K)
    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, br_corner)
    R = bc.apply_neumann(R, tr_corner)

    D = linalg.spsolve(K, R)

    D_true = np.array([
        0.0, 0.0, 1.90773874e-05, 0.0, 8.73032981e-06, -7.41539125e-05, 0.0,
        0.0
    ])
    np.testing.assert_almost_equal(D_true, D)
Example #5
0
def test_fem():
    mesh_path = "tests/data/msh/test.msh"

    element_type = "triangle"
    integration_points = 1
    load_condition = "plane stress"  # "plane stress" or "plane strain"
    thickness = 0.5
    steel = base.Material("steel", 3e7, 0.25, load_condition)

    mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map

    left_side = bc.DirichletBC("left side", mesh, [0, 1], 0.0)
    br_corner = bc.DirichletBC("bottom right corner", mesh, [1], 0.0)
    tr_corner = bc.NeumannBC("top right corner", mesh, [1], -1000.0)

    E_array = vector.compute_E_array(num_elements, material_map,
                                     mesh.field_data, steel)
    R = np.zeros(num_nodes * 2)
    K = vector.assembly(num_elements, num_nodes, elements, nodal_coord,
                        E_array, thickness)

    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, br_corner)
    R = bc.apply_neumann(R, tr_corner)

    D = linalg.spsolve(K, R)

    D_true = np.array([
        0.0, 0.0, 1.90773874e-05, 0.0, 8.73032981e-06, -7.41539125e-05, 0.0,
        0.0
    ])
    # np.testing.assert_allclose(D_true, D)  # FIXME some zeros are 1.0e-20 why??
    np.testing.assert_almost_equal(D_true, D)
Example #6
0
def test_vect_assembly():
    mesh_path = "tests/data/msh/test.msh"
    element_type = "triangle"
    load_condition = "plane stress"  # "plane stress" or "plane strain"
    thickness = 0.5
    steel = base.Material("steel", 3e7, 0.25, load_condition)

    mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map

    left_side = bc.DirichletBC("left side", mesh, [0, 1], 0.0)
    br_corner = bc.DirichletBC("bottom right corner", mesh, [1], 0.0)
    tr_corner = bc.NeumannBC("top right corner", mesh, [1], -1000.0)

    E_array = vector.compute_E_array(num_elements, material_map,
                                     mesh.field_data, steel)
    R = np.zeros(num_nodes * 2)
    K = vector.assembly(num_elements, num_nodes, elements, nodal_coord,
                        E_array, thickness)
    K_true = np.array([
        [
            9833333.33333333, 0., -5333333.33333333, 2000000., 0., -5000000.,
            -4500000., 3000000.
        ],
        [
            0., 14000000., 3000000., -2000000., -5000000., 0., 2000000.,
            -12000000.
        ],
        [
            -5333333.33333333, 3000000., 9833333.33333333, -5000000.,
            -4500000., 2000000., 0., 0.
        ],
        [
            2000000., -2000000., -5000000., 14000000., 3000000., -12000000.,
            0., 0.
        ],
        [
            0., -5000000., -4500000., 3000000., 9833333.33333333, 0.,
            -5333333.33333333, 2000000.
        ],
        [
            -5000000., 0., 2000000., -12000000., 0., 14000000., 3000000.,
            -2000000.
        ],
        [
            -4500000., 2000000., 0., 0., -5333333.33333333, 3000000.,
            9833333.33333333, -5000000.
        ],
        [
            3000000., -12000000., 0., 0., 2000000., -2000000., -5000000.,
            14000000.
        ],
    ])
    np.testing.assert_allclose(K_true, K.toarray())

    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, br_corner)
    R = bc.apply_neumann(R, tr_corner)

    K_true_bc = np.array([
        [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        [
            -5.33333333e+06, 3.00000000e+06, 9.83333333e+06, -5.00000000e+06,
            -4.50000000e+06, 2.00000000e+06, 0.0, 0.0
        ],
        [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
        [
            0.0, -5.00000000e+06, -4.50000000e+06, 3.00000000e+06,
            9.83333333e+06, 0.0, -5.33333333e+06, 2.00000000e+06
        ],
        [
            -5.00000000e+06, 0.0, 2.00000000e+06, -1.20000000e+07, 0.0,
            1.40000000e+07, 3.00000000e+06, -2.00000000e+06
        ],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
    ])
    np.testing.assert_allclose(K_true_bc, K.toarray())
Example #7
0
def test_feap_1():
    # LOGGING
    main_log = logging.getLogger(__name__)
    main_log.setLevel(logging.INFO)
    main_handler = logging.StreamHandler()  # main_log handler
    main_handler.setLevel(logging.INFO)
    main_formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )  # main_log formatter
    main_handler.setFormatter(main_formatter)
    main_log.addHandler(main_handler)

    feat_log = logging.getLogger("feat")
    feat_log.setLevel(logging.DEBUG)
    feat_handler = logging.StreamHandler()
    feat_handler.setLevel(logging.DEBUG)
    feat_formatter = logging.Formatter(
        '%(name)s - %(levelname)s - %(message)s')
    feat_handler.setFormatter(feat_formatter)
    feat_log.addHandler(feat_handler)

    # SETTINGS
    mesh_path = "tests/data/msh/feap_1.msh"
    main_log.info("MESH FILE: %s", mesh_path)

    # DATA
    element_type = "triangle"
    load_condition = "plane strain"  # "plane stress" or "plane strain"
    thickness = 1
    main_log.info("LOAD CONDITION: %s", load_condition)
    main_log.info("THICKNESS: %s", thickness)

    # MATERIAL
    cheese = base.Material("cheese", 70, 0.3, load_condition)
    main_log.info("MATERIALS: TODO")

    # MESH
    mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map
    main_log.info("MESH INFO: %d elements, %d nodes", num_elements, num_nodes)

    # BOUNDARY CONDITIONS INSTANCES
    left_side = bc.DirichletBC("left side", mesh, [0], 0.0)
    bl_corner = bc.DirichletBC("bottom left corner", mesh, [1], 0.0)
    right_side = bc.DirichletBC("right side", mesh, [0], 1.0)
    main_log.info("BOUNDARY CONDITIONS: TODO")

    # ASSEMBLY
    E_array = vector.compute_E_array(num_elements, material_map,
                                     mesh.field_data, cheese)
    R = np.zeros(num_nodes * 2)
    K = vector.assembly(num_elements, num_nodes, elements, nodal_coord,
                        E_array, thickness)
    main_log.debug("STIFFNESS MATRIX (K) BEFORE BC:\n %s\n", K)

    # save constrained dof rows of K
    # dirichlet dof are built only for boundaries with related reactions
    dirichlet_dof, dirichlet_values = bc.build_dirichlet_data(
        left_side, bl_corner)
    K = K.tocsr()
    K_rows = K[dirichlet_dof, :]
    K = K.tocsc()

    # BOUNDARY CONDITIONS APPLICATION
    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, bl_corner,
                                 right_side)
    main_log.debug("STIFFNESS MATRIX (K) AFTER BC:\n %s\n", K)
    main_log.debug("LOAD VECTOR (R) BEFORE BC:\n %s\n", R)

    # SOLVER
    D = linalg.spsolve(K, R)
    main_log.info("DISPLACEMENTS VECTOR (D):\n %s\n", D)

    reactions = K_rows.dot(D)
    main_log.debug("REACTIONS (dirichlet dofs):\n %s\n", reactions)
    modulus = base.compute_modulus(nodal_coord, right_side, reactions,
                                   thickness)
    main_log.info("RESULTING ELASTIC MODULUS: %f", modulus)

    comparable_dofs = [2, 4, 5, 7]
    D_true = np.array([
        0.0,
        0.0,
        1.0,
        np.NaN,
        1.0,
        -4.28571429e-01,
        0.0,
        -4.28571429e-01,
    ])
    np.testing.assert_allclose(D_true[comparable_dofs], D[comparable_dofs])
Example #8
0
def test_feap_2(poisson, D_true, reactions_true):
    # LOGGING
    main_log = logging.getLogger(__name__)
    main_log.setLevel(logging.DEBUG)
    main_handler = logging.StreamHandler()  # main_log handler
    main_handler.setLevel(logging.DEBUG)
    main_formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )  # main_log formatter
    main_handler.setFormatter(main_formatter)
    main_log.addHandler(main_handler)

    feat_log = logging.getLogger("feat")
    feat_log.setLevel(logging.DEBUG)
    feat_handler = logging.StreamHandler()
    feat_handler.setLevel(logging.DEBUG)
    feat_formatter = logging.Formatter(
        '%(name)s - %(levelname)s - %(message)s')
    feat_handler.setFormatter(feat_formatter)
    feat_log.addHandler(feat_handler)

    # SETTINGS
    mesh_path = "tests/data/msh/feap_2.msh"
    main_log.info("MESH FILE: %s", mesh_path)

    # DATA
    element_type = "triangle"
    load_condition = "plane strain"  # "plane stress" or "plane strain"
    thickness = 1
    main_log.info("LOAD CONDITION: %s", load_condition)
    main_log.info("THICKNESS: %s", thickness)

    # MATERIAL
    rubber = base.Material("rubber", 10, poisson, load_condition)
    main_log.info("MATERIALS: TODO")

    # MESH
    mesh = meshio.read(mesh_path)
    elements = mesh.cells_dict[element_type]
    nodal_coord = mesh.points[:, :2]
    num_elements = elements.shape[0]
    num_nodes = nodal_coord.shape[0]
    material_map = mesh.cell_data_dict["gmsh:physical"][
        element_type] - 1  # element-material map
    main_log.info("MESH INFO: %d elements, %d nodes", num_elements, num_nodes)

    # BOUNDARY CONDITIONS INSTANCES
    left_side = bc.DirichletBC("left side", mesh, [0], 0.0)
    b_corner = bc.DirichletBC("bottom corner", mesh, [1], 0.0)
    r_corner_x = bc.NeumannBC("right corner", mesh, [0], 0.4)
    r_corner_y = bc.NeumannBC("right corner", mesh, [1], 0.4)
    main_log.info("BOUNDARY CONDITIONS: TODO")

    # ASSEMBLY
    E_array = vector.compute_E_array(num_elements, material_map,
                                     mesh.field_data, rubber)
    main_log.debug("E array:\n %s\n", E_array)
    R = np.zeros(num_nodes * 2)
    K = vector.assembly(num_elements, num_nodes, elements, nodal_coord,
                        E_array, thickness)
    main_log.debug("STIFFNESS MATRIX (K) BEFORE BC:\n %s\n", K.todense())

    # save constrained dof rows of K
    # dirichlet dof are built only for boundaries with related reactions
    dirichlet_dof, dirichlet_values = bc.build_dirichlet_data(
        left_side, b_corner)
    K = K.tocsr()
    K_rows = K[dirichlet_dof, :]
    K = K.tocsc()

    # BOUNDARY CONDITIONS APPLICATION
    K, R = bc.sp_apply_dirichlet(num_nodes, K, R, left_side, b_corner)
    R = bc.apply_neumann(R, r_corner_x, r_corner_y)
    main_log.debug("STIFFNESS MATRIX (K) AFTER BC:\n %s\n", K.todense())
    main_log.debug("LOAD VECTOR (R) BEFORE BC:\n %s\n", R)

    # SOLVER
    D = linalg.spsolve(K, R)
    main_log.info("DISPLACEMENTS VECTOR (D):\n %s\n", D)

    reactions = K_rows.dot(D)
    main_log.debug("REACTIONS (dirichlet dofs):\n %s\n", reactions)

    np.testing.assert_allclose(D_true, D)
    np.testing.assert_allclose(reactions_true, reactions)