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
def test_stiffness_matrix(): 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 E_material = base.compute_E_material(num_elements, material_map, mesh.field_data, steel) k_0 = base.stiffness_matrix(0, elements, nodal_coord, material_map, E_material, thickness, element_type) k_1 = base.stiffness_matrix(1, elements, nodal_coord, material_map, E_material, thickness, element_type) k_0_true = np.array([ (5333333.33333333, 0.0, -5333333.33333333, 2000000., 0., -2000000.), (0., 2000000., 3000000., -2000000., -3000000., 0.), (-5333333.33333333, 3000000., 9833333.33333333, -5000000., -4500000., 2000000.), (2000000., -2000000., -5000000., 14000000., 3000000., -12000000.), (0., -3000000., -4500000., 3000000., 4500000., 0.), (-2000000., 0., 2000000., -12000000., 0., 12000000.), ]) k_1_true = np.array([ (4500000., 0., 0., -3000000., -4500000., 3000000.), (0., 12000000., -2000000., 0., 2000000., -12000000.), (0., -2000000., 5333333.33333333, 0., -5333333.33333333, 2000000.), (-3000000., 0., 0., 2000000., 3000000., -2000000.), (-4500000., 2000000., -5333333.33333333, 3000000., 9833333.33333333, -5000000.), (3000000., -12000000., 2000000., -2000000., -5000000., 14000000.), ]) np.testing.assert_allclose(k_0_true, k_0) np.testing.assert_allclose(k_1_true, k_1)
def test_compute_E_material(): element_type = "triangle" mesh_path = "tests/data/msh/test.msh" load_condition = "plane stress" # "plane stress" or "plane strain" steel = base.Material("steel", 3e7, 0.25, load_condition) mesh = meshio.read(mesh_path) num_elements = mesh.cells_dict[element_type].shape[0] material_map = mesh.cell_data_dict["gmsh:physical"][ element_type] - 1 # element-material map E_material = base.compute_E_material(num_elements, material_map, mesh.field_data, steel) E_steel = np.array([ (3.2e7, 8e6, 0.0), (8e6, 3.2e7, 0.0), (0.0, 0.0, 1.2e7), ]) # TODO add aluminum matrix testing np.testing.assert_allclose(E_steel, E_material[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)
def test_feap_1(): #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_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) #FIXME main_log.info("MATERIALS: TODO") # MESH mesh = meshio.read(mesh_path) elements = mesh.cells_dict[element_type] nodal_coord = mesh.points[:, :2] print(type(nodal_coord)) print(nodal_coord) 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_material = base.compute_E_material(num_elements, material_map, mesh.field_data, cheese) K = np.zeros((num_nodes * 2, num_nodes * 2)) R = np.zeros(num_nodes * 2) K = base.assembly(K, num_elements, elements, nodal_coord, material_map, E_material, thickness, element_type) main_log.debug("STIFFNESS MATRIX (K) BEFORE BC:\n %s\n", K) # contrained dof rows of K are saved now reaction_dof = bc.dirichlet_dof(left_side, bl_corner) K_rows = K[reaction_dof, :] # BOUNDARY CONDITIONS APPLICATION K, R = bc.apply_dirichlet(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 = np.linalg.solve(K, R) main_log.info("DISPLACEMENTS VECTOR (D):\n %s\n", D) reactions = np.dot(K_rows, 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 = [0, 1, 2, 4, 5, 6, 7] D_true = np.array([ 0.0, 0.0, 1.0, np.NaN, 1.0, -4.28571429e-01, 0.0, -4.28571429e-01, ]) reactions_true = np.array( [-3.84615385e+01, -3.84615385e+01, -7.10542736e-15]) np.testing.assert_allclose(reactions_true, reactions) np.testing.assert_allclose(D_true[comparable_dofs], D[comparable_dofs])
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) #FIXME 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_material = base.compute_E_material(num_elements, material_map, mesh.field_data, rubber) main_log.debug("E array:\n %s\n", E_material) K = np.zeros((num_nodes * 2, num_nodes * 2)) R = np.zeros(num_nodes * 2) K = base.assembly(K, num_elements, elements, nodal_coord, material_map, E_material, thickness, element_type) main_log.debug("STIFFNESS MATRIX (K) BEFORE BC:\n %s\n", K) # contrained dof rows of K are saved now reaction_dof = bc.dirichlet_dof(left_side, b_corner) K_rows = K[reaction_dof, :] # BOUNDARY CONDITIONS APPLICATION K, R = bc.apply_dirichlet(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) main_log.debug("LOAD VECTOR (R) BEFORE BC:\n %s\n", R) # SOLVER D = np.linalg.solve(K, R) main_log.info("DISPLACEMENTS VECTOR (D):\n %s\n", D) reactions = np.dot(K_rows, 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)