{ "cells": [ { "cell_type": "markdown", "id": "29eb351e-1bf3-48c0-a3ff-5d58de4db493", "metadata": {}, "source": [ "# Using PlanarBiaxialExtension" ] }, { "cell_type": "code", "execution_count": 1, "id": "923a4b52-38d7-44fd-8ed5-9ba6c71d0dc3", "metadata": {}, "outputs": [], "source": [ "import pymecht as pmt\n", "from matplotlib import pyplot as plt\n", "import numpy as np" ] }, { "cell_type": "markdown", "id": "f203055c-f88a-42d6-a64d-83bfd27f3585", "metadata": {}, "source": [ "## Displacement controlled" ] }, { "cell_type": "markdown", "id": "6a53dace-9ad5-4141-9c18-d9ad3df7b0e7", "metadata": {}, "source": [ "We start by using the `PlanarBiaxialExtension` in a simple `disp_controlled` manner. We start by creating a material and using it to create a planar biaxial experimental sample. Then, we set it to have two fibers at $\\pm 10$ degrees. We also set the parameters, and print the sample and its parameter values. " ] }, { "cell_type": "code", "execution_count": 3, "id": "06fd9678-dbca-4eae-81dd-180209f36aeb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fiber directions set to 10 degrees ( 0.17453292519943295 radians)\n", "An object of type PlanarBiaxialExtensionwith stretch as input, cauchy as output, and the following material\n", "Material model with 2 components:\n", "Component1: GOH with fiber direction(s):[array([0.98480775, 0.17364818, 0. ]), array([ 0.98480775, -0.17364818, 0. ])]\n", "Component2: NH with fiber direction(s):[array([0.98480775, 0.17364818, 0. ]), array([ 0.98480775, -0.17364818, 0. ])]\n", " ------------------------------------------------------------------\n", "Keys Value Fixed? Lower bound Upper bound \n", "------------------------------------------------------------------\n", "L10 1.00 No 1.00e-04 1.00e+03 \n", "L20 1.00 No 1.00e-04 1.00e+03 \n", "thick 1.00 No 1.00e-04 1.00e+03 \n", "k1_0 20.00 No 0.10 30.00 \n", "k2_0 20.00 No 0.10 30.00 \n", "k3_0 0.10 No 0.00 0.33 \n", "mu_1 1.00 No 1.00e-04 1.00e+02 \n", "------------------------------------------------------------------\n", "\n" ] } ], "source": [ "mat = pmt.MatModel('goh','nh')\n", "\n", "sample = pmt.PlanarBiaxialExtension(mat)\n", "pmt.specify_two_fibers(sample,10)\n", "params = sample.parameters\n", "params.set('k1_0',20)\n", "params.set('k2_0',20)\n", "print(sample, params)" ] }, { "cell_type": "markdown", "id": "7e9420a9-7252-448c-b262-0238201a68bf", "metadata": {}, "source": [ "By default, the displacement measure (input) is stretch and the force measure (output) is Cauchy stress. Note that for planar biaxial setup, there are two inputs and two outputs (e.g., stretches and stresses along the two directions). Thus, when we create the displacement to be applied, we create a 2D array, where each row has two elements: stretch along the x-axis and stretch along the y-axis. We set them to increase linearly between unit stretch and a maximum stretch of 1.1 along the x-axis and 1.3 along the y-axis. \n", "\n", "Then, we perform then `disp_controlled` simulation at these stretches. It results in a stress array, which is also 2D, with each row having the stress along x-axis and that along the y-axis. Lastly, we plot the resulting stress-stretch curves along the two directions." ] }, { "cell_type": "code", "execution_count": 4, "id": "53a11b9c-1edf-4fc3-bd90-79e0b32860af", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(10, 2) (10, 2)\n", "[1.01111111 1.03333333] [1.08277678 0.20397835]\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "stretch = np.array([np.linspace(1,1.1,10),np.linspace(1,1.3,10)]).T\n", "stress = sample.disp_controlled(stretch,params)\n", "print(stretch.shape, stress.shape) #the shape of input and output arrays\n", "print(stretch[1], stress[1]) #example inputs and outputs\n", "\n", "fig,ax = plt.subplots(1,1,figsize=(4,3))\n", "ax.plot(stretch[:,0],stress[:,0]*100,'-o',label=r'$x$')\n", "ax.plot(stretch[:,1],stress[:,1]*100,'-o',label=r'$y$')\n", "ax.set_xlabel('Stretch [-]')\n", "ax.set_ylabel('Stress [kPa]')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "70484e13-0564-4214-b833-602ae4d5d05f", "metadata": {}, "source": [ "## Force controlled" ] }, { "cell_type": "markdown", "id": "6b664a6a-c9ca-47ac-bea1-e77ee77dfa87", "metadata": {}, "source": [ "The inverse of `disp_controlled` is `force_controlled` simulation, wherein we apply a force (or stress) and the result is a stretch (or strain/length etc., depending on the setting when creating a sample). Here, we use the stresses we calculated in the previous step to back calculate the stretch. We check the difference and see that a close-enough solution was found. Note that `force_controlled` uses iterative solver, evaluating the `disp_controlled` simulation multiple times to find the \"displacement\" that would result in the applied force (numerically close-enough). Thus, `force_controlled` is commonly slower than `disp_controlled`." ] }, { "cell_type": "code", "execution_count": 5, "id": "38d3680d-37cb-4abc-a073-1606e2acc371", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "8.503677451570787e-12\n" ] } ], "source": [ "stretch_back = sample.force_controlled(stress,params)\n", "print(np.linalg.norm(stretch_back-stretch))" ] }, { "cell_type": "markdown", "id": "848a698b-196c-4471-8357-d66870701c9a", "metadata": {}, "source": [ "## Different `force_measure`s" ] }, { "cell_type": "markdown", "id": "8899af4a-aaf0-48e8-8180-11d32e568bb2", "metadata": {}, "source": [ "There are different options for the `force_measure` argument, as we can see from the helper function." ] }, { "cell_type": "code", "execution_count": 6, "id": "ff6ffd24-d751-4afb-ac9d-fc678a00688e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;31mInit signature:\u001b[0m\n", "\u001b[0mpmt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mPlanarBiaxialExtension\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m\n", "\u001b[0m \u001b[0mmat_model\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\n", "\u001b[0m \u001b[0mdisp_measure\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'stretch'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\n", "\u001b[0m \u001b[0mforce_measure\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'cauchy'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\n", "\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mDocstring:\u001b[0m \n", "For simulating planar biaxial extension of a planar sample\n", "\n", "+-----------+---------------------------+\n", "| Parameter | Description (default) |\n", "+===========+===========================+\n", "| L10 | Ref length: 1st axis (1) |\n", "+-----------+---------------------------+\n", "| L20 | Ref length: 2nd axis (1) |\n", "+-----------+---------------------------+\n", "| thick | Sample thicknesse (1) |\n", "+-----------+---------------------------+\n", "\n", "\n", "Parameters\n", "----------\n", "mat_model: MatModel\n", " A material model object of type MatModel\n", "\n", "disp_measure: str\n", " The measure of displacement with the following options: \n", " \n", " * 'stretch' : The stretch ratio (default)\n", " * 'strain' : The Green-Lagrange strain\n", " * 'deltal' : The change in length\n", " * 'length' : The length\n", "\n", "force_measure: str\n", " The measure of force with the following options:\n", " \n", " * 'force' : The force per unit area\n", " * 'tension' : The force per unit thickness\n", " * 'cauchy' : The Cauchy stress (default)\n", " * '1pk' or '1stpk' or 'firstpk' : The first Piola-Kirchhoff stress\n", " * '2pk' or '2ndpk' or 'secondpk' : The second Piola-Kirchhoff stress\n", "\u001b[1;31mFile:\u001b[0m c:\\users\\2712332r\\appdata\\local\\anaconda3\\envs\\pymecht\\lib\\site-packages\\pymecht\\sampleexperiment.py\n", "\u001b[1;31mType:\u001b[0m type\n", "\u001b[1;31mSubclasses:\u001b[0m " ] } ], "source": [ "pmt.PlanarBiaxialExtension?" ] }, { "cell_type": "code", "execution_count": 7, "id": "0ae4a49c-6fa3-420b-aae5-043d453d2b86", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fiber directions set to 10 degrees ( 0.17453292519943295 radians)\n", "[[ 0. 0. ]\n", " [ 1.07087813 0.19739841]\n", " [ 2.29707897 0.42600305]\n", " [ 3.73982384 0.6939273 ]\n", " [ 5.49544981 1.01540952]\n", " [ 7.71157638 1.41391158]\n", " [10.61447776 1.92716025]\n", " [14.55572515 2.61571986]\n", " [20.09275611 3.57794081]\n", " [28.13077066 4.97660603]]\n", "[[ 0. 0. ]\n", " [ 4.28351252 0.78959362]\n", " [ 9.18831587 1.70401218]\n", " [ 14.95929535 2.7757092 ]\n", " [ 21.98179923 4.0616381 ]\n", " [ 30.84630553 5.65564632]\n", " [ 42.45791106 7.70864098]\n", " [ 58.22290059 10.46287943]\n", " [ 80.37102445 14.31176324]\n", " [112.52308264 19.90642412]]\n" ] } ], "source": [ "#output force\n", "sample = pmt.PlanarBiaxialExtension(mat,force_measure='force')\n", "pmt.specify_two_fibers(sample,10)\n", "print(sample.disp_controlled(stretch,params)) #prints force, which will depend on lengths and thickness\n", "params.set('L10',2)\n", "params.set('L20',2)\n", "params.set('thick',2)\n", "print(sample.disp_controlled(stretch,params)) #see the new force, which should be 4 times" ] }, { "cell_type": "code", "execution_count": 8, "id": "710dd95b-8c50-4462-bbde-bb91db26d85e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fiber directions set to 10 degrees ( 0.17453292519943295 radians)\n", "[[ 0. 0. ]\n", " [ 1.07087813 0.19739841]\n", " [ 2.29707897 0.42600305]\n", " [ 3.73982384 0.6939273 ]\n", " [ 5.49544981 1.01540952]\n", " [ 7.71157638 1.41391158]\n", " [10.61447776 1.92716025]\n", " [14.55572515 2.61571986]\n", " [20.09275611 3.57794081]\n", " [28.13077066 4.97660603]]\n", "[[ 0. 0. ]\n", " [ 1.07087813 0.19739841]\n", " [ 2.29707897 0.42600305]\n", " [ 3.73982384 0.6939273 ]\n", " [ 5.49544981 1.01540952]\n", " [ 7.71157638 1.41391158]\n", " [10.61447776 1.92716025]\n", " [14.55572515 2.61571986]\n", " [20.09275611 3.57794081]\n", " [28.13077066 4.97660603]]\n" ] } ], "source": [ "#output tension\n", "sample = pmt.PlanarBiaxialExtension(mat,force_measure='tension')\n", "pmt.specify_two_fibers(sample,10)\n", "params.set('L10',1)\n", "params.set('L20',1)\n", "params.set('thick',1)\n", "print(sample.disp_controlled(stretch,params)) #prints tension, which will depend on thickness, but not lengths\n", "params.set('L10',2)\n", "params.set('L20',2)\n", "print(sample.disp_controlled(stretch,params)) #see the new tension, which should be the same (independent of the lengths)" ] }, { "cell_type": "code", "execution_count": 9, "id": "d5f671c0-aea6-4205-bacc-e7f108525156", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fiber directions set to 10 degrees ( 0.17453292519943295 radians)\n", "[[ 0. 0. ]\n", " [ 1.07087813 0.19739841]\n", " [ 2.29707897 0.42600305]\n", " [ 3.73982384 0.6939273 ]\n", " [ 5.49544981 1.01540952]\n", " [ 7.71157638 1.41391158]\n", " [10.61447776 1.92716025]\n", " [14.55572515 2.61571986]\n", " [20.09275611 3.57794081]\n", " [28.13077066 4.97660603]]\n" ] } ], "source": [ "#output 1st PK stress\n", "sample = pmt.PlanarBiaxialExtension(mat,force_measure='1pk')\n", "pmt.specify_two_fibers(sample,10)\n", "params.set('L10',1)\n", "params.set('L20',1)\n", "params.set('thick',1)\n", "print(sample.disp_controlled(stretch,params)) #prints 1st PK stress" ] }, { "cell_type": "markdown", "id": "761f22a3-d711-4826-9983-a9bea0009970", "metadata": {}, "source": [ "## Different `disp_measure`s" ] }, { "cell_type": "markdown", "id": "5a48a4a5-fb0c-422a-be3f-99cc1fc59822", "metadata": {}, "source": [ "There are different options for the `disp_measure` argument, as we can see from the helper function. Thus, one can use different ones when creating the sample. This will result in different outputs from `force_controlled`. Similarly, the inputs to the `disp_controlled` will be treated as the chosen `disp_measure`." ] }, { "cell_type": "markdown", "id": "eb7087a5-8b2a-45af-878d-2eb01c87fcca", "metadata": {}, "source": [ "When using `force_controlled` simulation, an iterative solution is involved, for which an initial guess is required. There is a default value, which may not be reasonable for different `disp_measure`s leading to non-convergence of the iterative solver. Thus, we explicitly specify the initial guess using `x0` argument." ] }, { "cell_type": "code", "execution_count": 10, "id": "00580aff-e0df-4ebc-8825-7cd1d5b080a7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "strain [0.01 0.09]\n", "deltal [0.1 0.3]\n", "length [1.1 1.3]\n" ] } ], "source": [ "sample2 = pmt.PlanarBiaxialExtension(mat,disp_measure='strain')\n", "pmt.specify_two_fibers(sample2,10,verbose=False)\n", "result = sample2.force_controlled(stress,params, x0=[0.,0.])\n", "print('strain', result[-1])\n", "\n", "sample2 = pmt.PlanarBiaxialExtension(mat,disp_measure='deltal')\n", "pmt.specify_two_fibers(sample2,10,verbose=False)\n", "result = sample2.force_controlled(stress,params, x0=[0.,0.])\n", "print('deltal', result[-1])\n", "\n", "sample2 = pmt.PlanarBiaxialExtension(mat,disp_measure='length')\n", "pmt.specify_two_fibers(sample2,10,verbose=False)\n", "result = sample2.force_controlled(stress,params, x0=[params['L10'].value,params['L20'].value])\n", "print('length', result[-1])" ] }, { "cell_type": "markdown", "id": "c2005e83-e915-4f1c-a124-26b94307ed84", "metadata": {}, "source": [ "## Fiber direction warning" ] }, { "cell_type": "markdown", "id": "fc739633-5cf8-4507-88dd-879e23a9468a", "metadata": {}, "source": [ "One can manually specify fiber direction in the material models before using them to create a `PlanarBiaxialExtension` sample, as follows." ] }, { "cell_type": "code", "execution_count": 11, "id": "9ebbbd84-2f50-424e-9a29-f16fd42a437c", "metadata": {}, "outputs": [], "source": [ "mat = pmt.MatModel('goh','nh')\n", "mat_models = mat.models\n", "mat_models[0].fiber_dirs = np.array([1,0,0])\n", "sample = pmt.PlanarBiaxialExtension(mat)" ] }, { "cell_type": "markdown", "id": "081c6b51-1d6f-4284-b1c2-121b1ab3c71f", "metadata": {}, "source": [ "However, this makes it possible to create out of plane fiber directions, which can result in erroneous result. Thus, in such situations a warning will be generated." ] }, { "cell_type": "code", "execution_count": 12, "id": "a6287d41-2bf6-4463-a409-d28cf5bfcae7", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "c:\\Users\\2712332R\\AppData\\Local\\anaconda3\\envs\\pymecht\\Lib\\site-packages\\pymecht\\SampleExperiment.py:423: UserWarning: The PlanarBiaxialExtension assumes that fibers are in the plane. This is not satisfied and the results may be spurious.\n", " warnings.warn(\"The PlanarBiaxialExtension assumes that fibers are in the plane. This is not satisfied and the results may be spurious.\")\n" ] } ], "source": [ "mat = pmt.MatModel('goh','nh')\n", "mat_models = mat.models\n", "mat_models[0].fiber_dirs = np.array([0.5,0,0.5])\n", "sample = pmt.PlanarBiaxialExtension(mat)" ] }, { "cell_type": "markdown", "id": "bea24f73-2e25-4f28-bd5c-fe1c9b49f827", "metadata": {}, "source": [ "Thus, helper functions `specify_single_fiber` and `specify_two_fibers` are provided to avoid such errors." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }