diff --git a/doc/notebooks/indentation/indentation_2D - Visco.ipynb b/doc/notebooks/indentation/indentation_2D - Visco.ipynb new file mode 100644 index 0000000..0da482c --- /dev/null +++ b/doc/notebooks/indentation/indentation_2D - Visco.ipynb @@ -0,0 +1,476 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2D indentation using Argiope & Hardness\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!type local_settings.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import matplotlib as mpl\n", + "import argiope as ag\n", + "import hardness as hd\n", + "import pandas as pd\n", + "import numpy as np\n", + "import os, subprocess, time, local_settings, time, sys\n", + "%matplotlib nbagg\n", + "\n", + "mpl.rcParams['grid.color'] = 'k'\n", + "mpl.rcParams['grid.linestyle'] = ':'\n", + "mpl.rcParams['grid.linewidth'] = 0.5\n", + "mpl.rcParams['contour.negative_linestyle'] = 'solid'\n", + "\n", + "# USEFUL FUNCTIONS\n", + "def create_dir(path):\n", + " try:\n", + " os.mkdir(path)\n", + " except:\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Settings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# SETTINGS\n", + "workdir = \"_workdir/\"\n", + "outputdir = \"outputs/\"\n", + "label = \"indentation_2D\"\n", + "\n", + "create_dir(workdir)\n", + "create_dir(workdir + outputdir) \n", + "print (local_settings.ABAQUS_PATH)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model definition" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#-------------------------------------------------------------------------------\n", + "# MESH DEFINITIONS\n", + "def element_map(mesh):\n", + " mesh.elements.loc[mesh.elements.type.argiope == \"tri3\", (\"type\", \"solver\", \"\")] = \"CAX3\" \n", + " mesh.elements.loc[mesh.elements.type.argiope == \"quad4\", (\"type\", \"solver\", \"\")] = \"CAX4R\" \n", + " return mesh\n", + " \n", + "def sample_material_map(mesh):\n", + " mesh.elements[\"materials\"] = \"SAMPLE_MAT\" \n", + " return mesh\n", + "\n", + "def indenter_material_map(mesh):\n", + " mesh.elements[\"materials\"] = \"INDENTER_MAT\" \n", + " return mesh\n", + " \n", + " \n", + "parts = {\n", + " \"sample\" : hd.models.Sample2D(lx = 1., ly = 1., \n", + " r1 = 2., r2 = 3., \n", + " Nx = 32, Ny = 16,\n", + " Nr = 2, Nt = 64, \n", + " gmsh_path = \"gmsh\",\n", + " file_name = \"dummy\", \n", + " workdir = workdir, \n", + " gmsh_space = 2, \n", + " gmsh_options = \"-algo delquad\",\n", + " element_map = element_map,\n", + " material_map = sample_material_map),\n", + " \n", + " \"indenter\" : hd.models.SpheroconicalIndenter2D(\n", + " R = 0.2,\n", + " psi= 70.3, \n", + " r1 = 1., \n", + " r2 = 3., \n", + " r3 = 4., \n", + " lc1 = .1, \n", + " lc2 = .5,\n", + " rigid = False,\n", + " gmsh_path = \"gmsh\",\n", + " file_name = \"dummy\", \n", + " workdir = workdir, \n", + " gmsh_space = 2, \n", + " gmsh_options = \"-algo delquad\",\n", + " element_map = element_map,\n", + " material_map = indenter_material_map)}\n", + " \n", + "materials = [ag.materials.ElasticPlasticRateDep(label = \"SAMPLE_MAT\", young_modulus = 100000.0, poisson_ratio = 0.3, \n", + " yield_stress = 10.0, multiplier = 1.0e-6, exponent = 1.4),\n", + " ag.materials.Elastic(label = \"INDENTER_MAT\", young_modulus = 1000000.0, poisson_ratio = 0.07)]\n", + "\n", + "\n", + "#-------------------------------------------------------------------------------\n", + "# AMPLITUDE (load vs time law)\n", + "\n", + "amplitude = ag.models.Amplitude(type = \"Exp\",\n", + " name = \"Exp100\",\n", + " duration = 100,\n", + " Nb_data_points = 100, \n", + " load0 = 10, \n", + " strain_rate0 = .01)\n", + "\n", + "#-------------------------------------------------------------------------------\n", + "# STEP DEFINTIONS\n", + "steps = [hd.models.Step2D(name = \"LOADING1\",\n", + " control_type = \"disp\", \n", + " duration = 1.,\n", + " kind = \"adaptative\", \n", + " nframes = 50,\n", + " controlled_value = -0.02,\n", + " field_output_frequency = 99999),\n", + "hd.models.Step2D(name = \"LOADING2\",\n", + " control_type = \"force\", \n", + " duration = 1.,\n", + " kind = \"adaptative\", \n", + " nframes = 50,\n", + " controlled_value = -800.0,\n", + " field_output_frequency = 99999),\n", + "hd.models.Step2D(name = \"LOADING3\",\n", + " control_type = \"amplitude\", \n", + " duration = amplitude.duration,\n", + " kind = \"adaptative\", \n", + " nframes = 50,\n", + " controlled_value = -80.0,\n", + " amplitude = amplitude,\n", + " field_output_frequency = 99999),\n", + "hd.models.Step2D(name = \"LOADING4\",\n", + " control_type = \"force\", \n", + " duration = 1.,\n", + " kind = \"adaptative\", \n", + " nframes = 50,\n", + " controlled_value = 0.0,\n", + " field_output_frequency = 99999),\n", + "] \n", + "\n", + "model0 = hd.models.Indentation2D(label = label, \n", + " parts = parts, \n", + " steps = steps,\n", + " materials = materials, \n", + " amplitude = amplitude, \n", + " solver = \"abaqus\", \n", + " solver_path = local_settings.ABAQUS_PATH,\n", + " workdir = workdir,\n", + " verbose = True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "print(\"1: Preprocessing ----------------------------------\")\n", + "%time model0.write_input()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(\"2: Processing -------------------------------------\")\n", + "%time model0.run_simulation()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "print(\"3: Postprocessing ---------------------------------\")\n", + "%time model0.postproc()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"4: Saving model -----------------------------------\")\n", + "%time model0.save(workdir + \"model.pcklz\")\n", + "model = ag.utils.load(workdir + \"model.pcklz\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model checking\n", + "\n", + "Mesh building and quality checking." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parts[\"indenter\"].mesh.elements.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parts[\"sample\"].mesh.elements.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "i = 1\n", + "fig = plt.figure()\n", + "parts_names = parts.keys()\n", + "for name, part in parts.items(): \n", + " mesh = part.mesh\n", + " patches = mesh.to_polycollection(edgecolor = \"black\", linewidth = .5, alpha = 1.)\n", + " stats = mesh.stats()\n", + " patches.set_array( stats.stats.max_abs_angular_deviation )\n", + " patches.set_cmap(mpl.cm.YlOrRd)\n", + " ax = fig.add_subplot(1, 2, i)\n", + " ax.set_aspect(\"equal\")\n", + " ax.set_xlim(mesh.nodes.coords.x.min(), mesh.nodes.coords.x.max())\n", + " ax.set_ylim(mesh.nodes.coords.y.min(), mesh.nodes.coords.y.max())\n", + " ax.add_collection(patches)\n", + " cbar = plt.colorbar(patches, orientation = \"horizontal\")\n", + " cbar.set_label(\"Max Abs. Angular Deviation [$^o$]\")\n", + " plt.xlabel(\"$x$\")\n", + " plt.ylabel(\"$y$\")\n", + " plt.grid()\n", + " plt.title(name.title())\n", + " i+= 1\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Simulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Post-Processing\n", + "\n", + "### Time data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hist = model.data[\"history\"]\n", + "hist.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "plt.figure(figsize=plt.figaspect(0.2))\n", + "ax1 = plt.subplot(1,3,1)\n", + "\n", + "for step, group in hist.groupby(\"step\"):\n", + " ax1.plot(-group.dtot, -group.F, label = \"Step {0}\".format(step))\n", + "ax1.grid()\n", + "ax1.legend(loc = \"best\")\n", + "ax1.set_ylabel(\"Total force $F$, [N]\")\n", + "ax1.set_xlabel(\"Displacement, $\\delta$ [mm]\")\n", + "\n", + "ax1=plt.subplot(1,3,2)\n", + "for step, group in hist.groupby(\"step\"):\n", + " ax1.plot(group.t, -group.F, label = \"Step {0}\".format(step))\n", + "ax1.grid()\n", + "ax1.legend(loc = \"best\")\n", + "ax1.set_ylabel(\"Total force $F$, [N]\")\n", + "ax1.set_xlabel(\"Time [s]\")\n", + "\n", + "\n", + "ax1=plt.subplot(1,3,3)\n", + "for step, group in hist.groupby(\"step\"):\n", + " ax1.plot(group.t, -group.dtot, label = \"Step {0}\".format(step))\n", + "ax1.grid()\n", + "ax1.legend(loc = \"best\")\n", + "ax1.set_ylabel(\"Displacement, $\\delta$ [mm]\")\n", + "ax1.set_xlabel(\"Time [s]\")\n", + "\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Fields" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.parts[\"sample\"].mesh.fields_metadata()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model.parts[\"sample\"].mesh.fields_metadata()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parts = {k:part.mesh.copy() for k, part in model.parts.items() }\n", + "\n", + "fig = plt.figure()\n", + "ax = fig.add_subplot(1,1,1)\n", + "ax.set_aspect(\"equal\")\n", + "ax.set_xlim(0., 4.)\n", + "ax.set_ylim(-2., 2.)\n", + "\n", + "field_num = 14 \n", + "disp_num = 15\n", + "levels = np.linspace(-1.e-2, 1.e-2, 11)\n", + "\n", + "for k, mesh in parts.items():\n", + " field = mesh.fields[field_num].data.v12\n", + " disp = mesh.fields[disp_num].data\n", + " mesh.nodes[(\"coords\", \"x\")] += disp.v1\n", + " mesh.nodes[(\"coords\", \"y\")] += disp.v2\n", + " tri = mesh.to_triangulation()\n", + " patches = mesh.to_polycollection(facecolor = \"none\",\n", + " edgecolor = \"black\",\n", + " linewidth = .5) \n", + " \n", + " grad = ax.tricontourf(tri, field, levels, cmap = mpl.cm.jet, alpha = 1.)\n", + " ax.tricontour(tri, field, levels, colors = \"white\", linewidths = 1.)\n", + " ax.add_collection(patches)\n", + "cbar = plt.colorbar(grad)\n", + "cbar.set_label(\"Cauchy Stress, $\\sigma_{12}$\")\n", + "ax.axis(\"off\")\n", + "plt.xlabel(\"$x$\")\n", + "plt.ylabel(\"$y$\")\n", + "#plt.grid()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "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.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/hardness/models.py b/hardness/models.py index af900aa..159f3d4 100644 --- a/hardness/models.py +++ b/hardness/models.py @@ -25,6 +25,7 @@ def write_input(self): hardness.models.indentation_2D_input(sample_mesh = self.parts["sample"], indenter_mesh = self.parts["indenter"], steps = self.steps, + amplitude = self.amplitude, materials = self.materials, solver = self.solver, path = "{0}/{1}.inp".format(self.workdir, @@ -319,8 +320,6 @@ def preprocess_mesh(self): open(self.workdir + self.file_name + ".geo", "w").write(geo) - - ################################################################################ @@ -338,6 +337,7 @@ def __init__(self, control_type = "disp", controlled_value = .1, min_frame_duration = 1.e-8, field_output_frequency = 99999, + amplitude = argiope.models.Amplitude(), solver = "abaqus"): self.control_type = control_type self.name = name @@ -347,8 +347,9 @@ def __init__(self, control_type = "disp", self.controlled_value = controlled_value self.min_frame_duration = min_frame_duration self.field_output_frequency = field_output_frequency + self.amplitude = amplitude self.solver = solver - + def get_input(self): control_type = self.control_type name = self.name @@ -359,28 +360,34 @@ def get_input(self): min_frame_duration = self.min_frame_duration solver = self.solver rootPath = "/templates/models/indentation_2D/steps/" + amplitude=self.amplitude + if solver == "abaqus": if kind == "fixed": if control_type == "disp": pattern = rootPath + "indentation_2D_step_disp_control_fixed.inp" - if control_type == "force": - pattern = rootPath + "indentation_2D_step_load_control_fixed.inp" + else : + pattern = rootPath + "indentation_2D_step_load_control_fixed.inp" + pattern = Template(open(MODPATH + pattern).read()) - + return pattern.substitute(NAME = name, CONTROLLED_VALUE = controlled_value, + AMPL_INSTRUCTION = amplitude.call_amplitude_inp(), DURATION = duration, FRAMEDURATION = float(duration) / nframes, FIELD_OUTPUT_FREQUENCY = self.field_output_frequency) if kind == "adaptative": if control_type == "disp": pattern = rootPath + "indentation_2D_step_disp_control_adaptative.inp" - if control_type == "force": - pattern = rootPath + "indentation_2D_step_load_control_adaptative.inp" + else : + pattern = rootPath + "indentation_2D_step_load_control_adaptative.inp" + pattern = Template(open(MODPATH + pattern).read()) - + return pattern.substitute(NAME = name, CONTROLLED_VALUE = controlled_value, + AMPL_INSTRUCTION = amplitude.call_amplitude_inp(), DURATION = duration, FRAMEDURATION = float(duration) / nframes, MINFRAMEDURATION = min_frame_duration, @@ -391,7 +398,8 @@ def get_input(self): ################################################################################ def indentation_2D_input(sample_mesh, indenter_mesh, - steps, + steps, + amplitude, materials, path = None, element_map = None, @@ -412,6 +420,7 @@ def indentation_2D_input(sample_mesh, pattern = pattern.substitute( SAMPLE_MESH = sample_mesh.mesh.write_inp(), INDENTER_MESH = indenter_mesh.mesh.write_inp(), + AMPLITUDE = amplitude.write_inp(), STEPS = "".join([step.get_input() for step in steps]), MATERIALS = "\n".join([m.write_inp() for m in materials]) ) if path == None: diff --git a/hardness/templates/models/indentation_2D/indentation_2D.inp b/hardness/templates/models/indentation_2D/indentation_2D.inp index 4d3aeb7..106b87b 100755 --- a/hardness/templates/models/indentation_2D/indentation_2D.inp +++ b/hardness/templates/models/indentation_2D/indentation_2D.inp @@ -26,6 +26,7 @@ $INDENTER_MESH *INSTANCE, NAME = I_INDENTER, PART= P_INDENTER *END INSTANCE *END ASSEMBLY +$AMPLITUDE **------------------------------------------------------------------------------ ** SURFACE INTERACTIONS **------------------------------------------------------------------------------ diff --git a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_adaptative.inp b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_adaptative.inp index 2b145f5..97e29e7 100644 --- a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_adaptative.inp +++ b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_adaptative.inp @@ -15,7 +15,7 @@ I_INDENTER.REF_NODE, 2, 2, $CONTROLLED_VALUE *NODE OUTPUT COORD, U, *NODE OUTPUT, NSET=I_INDENTER.REF_NODE -U +U$AMPL_INSTRUCTION *ELEMENT OUTPUT, ELSET=I_SAMPLE.ALL_ELEMENTS, DIRECTIONS = YES LE, EE, PE, PEEQ, S, *ELEMENT OUTPUT, ELSET=I_INDENTER.ALL_ELEMENTS, DIRECTIONS = YES diff --git a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_fixed.inp b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_fixed.inp index 9bddb6c..cb6b03a 100644 --- a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_fixed.inp +++ b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_disp_control_fixed.inp @@ -15,7 +15,7 @@ I_INDENTER.REF_NODE, 2, 2, $CONTROLLED_VALUE *NODE OUTPUT COORD, U, *NODE OUTPUT, NSET=I_INDENTER.REF_NODE -U +U$AMPL_INSTRUCTION *ELEMENT OUTPUT, ELSET=I_SAMPLE.ALL_ELEMENTS, DIRECTIONS = YES LE, EE, PE, PEEQ, S, *ELEMENT OUTPUT, ELSET=I_INDENTER.ALL_ELEMENTS, DIRECTIONS = YES diff --git a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_adaptative.inp b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_adaptative.inp index 480a128..f2871da 100644 --- a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_adaptative.inp +++ b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_adaptative.inp @@ -9,7 +9,7 @@ I_SAMPLE.AXIS, 1, 1 I_SAMPLE.BOTTOM, 1, 3 I_INDENTER.AXIS, 1, 1 I_INDENTER.REF_NODE, 4, 6 -*CLOAD +*CLOAD$AMPL_INSTRUCTION I_INDENTER.REF_NODE, 2, $CONTROLLED_VALUE *RESTART, WRITE, FREQUENCY = 0 *OUTPUT, FIELD, FREQUENCY = $FIELD_OUTPUT_FREQUENCY diff --git a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_fixed.inp b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_fixed.inp index e4f799b..8282067 100644 --- a/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_fixed.inp +++ b/hardness/templates/models/indentation_2D/steps/indentation_2D_step_load_control_fixed.inp @@ -9,7 +9,7 @@ I_SAMPLE.AXIS, 1, 1 I_SAMPLE.BOTTOM, 1, 3 I_INDENTER.AXIS, 1, 1 I_INDENTER.REF_NODE, 4, 6 -*CLOAD +*CLOAD$AMPL_INSTRUCTION I_INDENTER.REF_NODE, 2, $CONTROLLED_VALUE *RESTART, WRITE, FREQUENCY = 0 *OUTPUT, FIELD, FREQUENCY = $FIELD_OUTPUT_FREQUENCY