{ "cells": [ { "cell_type": "markdown", "id": "a1ba93b5-c0c3-4ca1-9adf-fac77131a5d0", "metadata": {}, "source": [ "# What damage function would render a constant bond behavior?" ] }, { "cell_type": "code", "execution_count": null, "id": "54719971-159c-47ed-bff2-932261fee1be", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget" ] }, { "cell_type": "markdown", "id": "7436d011-2494-4db6-bc46-bda5ea94d8f1", "metadata": {}, "source": [ "Consider bond behavior" ] }, { "cell_type": "code", "execution_count": null, "id": "32eb7807-4b42-4f0d-af0b-e456c1ee8241", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pylab as plt\n", "import numpy as np\n", "import sympy as sp\n", "sp.init_printing()" ] }, { "cell_type": "code", "execution_count": null, "id": "1af3886e-964c-467b-aa49-1a6f5c7d90ae", "metadata": {}, "outputs": [], "source": [ "tau_bar, s, E, omega = sp.symbols(r'\\bar{\\tau}, s, E, \\omega', nonnegative=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "12ad00cd-d4a3-4b6c-b65b-99b71749b713", "metadata": {}, "outputs": [], "source": [ "tau_s = sp.Piecewise(\n", " (tau_bar, s>tau_bar / E),\n", " (E * s, True),\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "523c7a0f-ac25-4678-b5ac-8c9d4ba7d0ba", "metadata": {}, "outputs": [], "source": [ "constitutive_law = sp.Eq(tau_s, (1 - omega) * E * s)" ] }, { "cell_type": "code", "execution_count": null, "id": "b1437b9f-7a12-48c2-823b-b8dea0a5e428", "metadata": {}, "outputs": [], "source": [ "omega_s = sp.solve(constitutive_law, omega)[0]\n", "omega_s" ] }, { "cell_type": "code", "execution_count": null, "id": "e225eca6-3a92-497c-b60e-9cbc110a41e3", "metadata": {}, "outputs": [], "source": [ "get_omega_s = sp.lambdify((tau_bar, E, s), omega_s)" ] }, { "cell_type": "code", "execution_count": null, "id": "a5330769-b6a4-4b17-a581-7a0e25e76149", "metadata": {}, "outputs": [], "source": [ "s_range = np.linspace(1e-10, 0.01, 100)\n", "omega_s = get_omega_s(8, 28000, s_range)" ] }, { "cell_type": "code", "execution_count": null, "id": "3b6bc2dc-48d3-4258-b067-dffd07064cac", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "plt.plot(s_range, omega_s)" ] }, { "cell_type": "code", "execution_count": null, "id": "31dc8d77-ad7a-47a8-9e92-30addff2c582", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def compute_stress_tangent(strain, plastic_strain, E, sigma_yield, H_kinematic, H_isotropic):\n", " stress = E * (strain - plastic_strain)\n", " tangent = E + H_kinematic + H_isotropic\n", " return stress, tangent\n", "\n", "def calculate_plastic_strain(strain, plastic_strain, E, sigma_yield, H_kinematic, H_isotropic):\n", " stress, tangent = compute_stress_tangent(strain, plastic_strain, E, sigma_yield, H_kinematic, H_isotropic)\n", " if stress > sigma_yield:\n", " plastic_strain += (stress - sigma_yield) / tangent\n", " return plastic_strain\n", "\n", "# Material parameters\n", "E = 200.0 # Young's modulus\n", "sigma_yield = 100.0 # Yield stress\n", "H_kinematic = 10.0 # Kinematic hardening parameter\n", "H_isotropic = 5.0 # Isotropic hardening parameter\n", "\n", "# Strain increments\n", "n_steps = 10\n", "strain_increments = np.linspace(0.0, 1.5, num=n_steps)\n", "\n", "# Initialize arrays to store stress and plastic strain history\n", "stress_history = np.zeros_like(strain_increments)\n", "plastic_strain = 0.0\n", "\n", "# Loop over strain increments\n", "for i, strain_increment in enumerate(strain_increments):\n", " strain = strain_increment\n", " stress, _ = compute_stress_tangent(strain, plastic_strain, E, sigma_yield, H_kinematic, H_isotropic)\n", " stress_history[i] = stress\n", " plastic_strain = calculate_plastic_strain(strain, plastic_strain, E, sigma_yield, H_kinematic, H_isotropic)\n", "\n", "print(\"Strain increments:\", strain_increments)\n", "print(\"Stress history:\", stress_history)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "ecd9da8b-9dc1-4744-8ed9-7f186469a517", "metadata": {}, "outputs": [], "source": [ "# Material parameters\n", "E = 200.0 # Young's modulus\n", "sigma_yield = 100.0 # Yield stress\n", "H = 10.0 # Hardening parameter\n", "\n", "# Sample usage\n", "strain = 0.6 # Assuming a strain increment of 0.1\n", "plastic_strain = 0.0\n", "\n", "stress = calculate_stress(strain, plastic_strain, E, sigma_yield, H)\n", "plastic_strain = calculate_plastic_strain(strain, plastic_strain, E, sigma_yield, H)\n", "\n", "print(f\"Strain: {strain}\")\n", "print(f\"Stress: {stress}\")\n", "print(f\"Plastic Strain: {plastic_strain}\")\n" ] }, { "cell_type": "code", "execution_count": null, "id": "439faf64-45ef-401e-95a2-2fccc440829b", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "eps_range = np.linspace(0, 1, 20)\n", "for eps in eps_range:\n", " " ] }, { "cell_type": "code", "execution_count": null, "id": "828c3df2-aabe-4727-a5dd-583830ad4871", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "def compute_stress(strain, plastic_strain, E, sigma_yield, H):\n", " stress = E * (strain - plastic_strain)\n", " return stress\n", "\n", "def calculate_plastic_strain(strain, plastic_strain, E, sigma_yield, H):\n", " stress = compute_stress(strain, plastic_strain, E, sigma_yield, H)\n", " if stress > sigma_yield:\n", " plastic_strain += (stress - sigma_yield) / E\n", " return plastic_strain\n", "\n", "# Material parameters\n", "E = 200.0 # Young's modulus\n", "sigma_yield = 100.0 # Yield stress\n", "H = 10.0 # Isotropic hardening modulus\n", "\n", "# Strain increments\n", "n_steps = 10\n", "strain_increments = np.linspace(0.0, 1.5, num=n_steps)\n", "\n", "# Initialize arrays to store stress and plastic strain history\n", "stress_history = np.zeros_like(strain_increments)\n", "plastic_strain = 0.0\n", "\n", "# Loop over strain increments\n", "for i, strain_increment in enumerate(strain_increments):\n", " strain = strain_increment\n", " stress = compute_stress(strain, plastic_strain, E, sigma_yield, H)\n", " stress_history[i] = stress\n", " plastic_strain = calculate_plastic_strain(strain, plastic_strain, E, sigma_yield, H)\n", "\n", "print(\"Strain increments:\", strain_increments)\n", "print(\"Stress history:\", stress_history)\n" ] }, { "cell_type": "code", "execution_count": null, "id": "6bbbbf43-2267-4d8f-85ed-967abd1fce63", "metadata": {}, "outputs": [], "source": [ "# Sample usage\n", "strain = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]]) # Assuming a strain increment of 0.1 in each component\n", "plastic_strain = np.zeros((3, 3))\n", "damage = 0.0\n", "\n", "material_model = MaterialModel(E=1.0, nu=0.3, sigma_yield=1.0, H_kinematic=0.2, H_isotropic=0.1, damage_coeff=0.1)\n", "calculate_stress_tangent_damage(strain, plastic_strain, damage, material_model)" ] }, { "cell_type": "code", "execution_count": null, "id": "9c8cfbf2-99f6-452c-a0f9-45b888cc160c", "metadata": {}, "outputs": [], "source": [ "plastic_strain = np.zeros((3, 3))\n", "damage = 0.0\n", "# Sample usage\n", "strain = np.zeros((3,3), np.float_)\n", "eps_range = np.linspace(0, 1.1, 20)\n", "material_model = MaterialModel(E=1.0, nu=0.3, sigma_yield=1.0, H_kinematic=0., H_isotropic=0., damage_coeff=0.1)\n", "sig_list = []\n", "for eps in eps_range:\n", " strain[0, 0] = eps\n", " stress, tangent, plastic_strain, damage = material_model.compute_stress_tangent_and_damage_increment(strain, plastic_strain, damage)\n", " sig_list.append(stress[0,0])\n", "sig_range = np.array(sig_list)" ] }, { "cell_type": "code", "execution_count": null, "id": "e4b368fa-d6b9-4f7d-b2fd-157300acff5e", "metadata": {}, "outputs": [], "source": [ "plastic_strain" ] }, { "cell_type": "code", "execution_count": null, "id": "60b3d4f2-e1cf-4f7c-bdbc-e90e6880b22f", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "plt.plot(eps_range, sig_range)" ] }, { "cell_type": "markdown", "id": "9f39ac75-b548-426f-a5d7-d767f3249ded", "metadata": {}, "source": [ "I want to implement a user material for non-linear finite element simulation using the predictor corrector concept. Many finite element tools allow for an externally implemented method to compute the stress for a prescribed strain increment and the set of state variables. Can you generate such a method in Python assuming a onedimensional stress-strain relation and ideal plasticity? Then, please provide a sample code with a prescribed sequence of strain increments that starts from zero and monotonically increases and another one starting at zero and monotonically decreases. Plot the stress-strain history using matplotlib." ] }, { "cell_type": "code", "execution_count": null, "id": "cc2609b4-14c3-4e67-888f-678f4b535d56", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget" ] }, { "cell_type": "code", "execution_count": null, "id": "94b97583-0942-4fef-8c02-e934ccb422e6", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "def compute_stress(strain_increment, state_variables):\n", " # Material properties\n", " E = 100.0 # Young's modulus\n", " yield_stress = 10.0 # Yield stress\n", "\n", " # Unpack state variables\n", " stress_prev, plastic_strain_prev = state_variables\n", "\n", " # Compute trial stress\n", " stress_trial = stress_prev + E * strain_increment\n", "\n", " # Check for plastic deformation\n", " if stress_trial > yield_stress:\n", " plastic_strain = plastic_strain_prev + (stress_trial - yield_stress) / E\n", " stress = yield_stress\n", " else:\n", " plastic_strain = plastic_strain_prev\n", " stress = stress_trial\n", "\n", " return stress, plastic_strain\n", "\n", "# Prescribed sequence of strain increments\n", "strain_increments = [0.1, 0.2, 0.15, 0.25, -0.1, -0.2]\n", "\n", "# Initial state variables\n", "stress_initial = 0.0\n", "plastic_strain_initial = 0.0\n", "state_variables = (stress_initial, plastic_strain_initial)\n", "\n", "# Lists to store stress and strain values\n", "stress_history = [stress_initial]\n", "strain_history = [0.0]\n", "\n", "# Perform the simulation\n", "for strain_increment in strain_increments:\n", " # Compute stress and update state variables\n", " stress, plastic_strain = compute_stress(strain_increment, state_variables)\n", " state_variables = (stress, plastic_strain)\n", "\n", " # Update stress and strain history\n", " stress_history.append(stress)\n", " strain_history.append(strain_history[-1] + strain_increment)\n", "\n", "# Plot stress-strain history\n", "plt.plot(strain_history, stress_history)\n", "plt.xlabel('Strain')\n", "plt.ylabel('Stress')\n", "plt.title('Stress-Strain History')\n", "plt.grid(True)" ] }, { "cell_type": "code", "execution_count": null, "id": "cc4039db-aedb-47cb-98fd-faa8be6cd63f", "metadata": {}, "outputs": [], "source": [ "increments_rev" ] }, { "cell_type": "code", "execution_count": null, "id": "33260f76-9733-4efc-a6d0-76d00785cfe4", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "bmcs_env2", "language": "python", "name": "bmcs_env2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3" } }, "nbformat": 4, "nbformat_minor": 5 }