symbolic fields

This commit is contained in:
Jukka Aho
2015-11-03 22:32:35 +02:00
parent 7a36a0ac3d
commit bb814b880d
6 changed files with 485 additions and 37 deletions
+222 -17
View File
@@ -25,7 +25,10 @@
"- Complete rewrite. The main ideas proposed in earlier version didn't work.\n",
"\n",
"### 2015-10-29\n",
"- Third iteration."
"- Third iteration.\n",
"\n",
"### 2015-11-03\n",
"- Starts to be ready. Introduced symbolic fields."
]
},
{
@@ -516,7 +519,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Creating continuous and discrete fields\n",
"### Creating continuous (and discrete) fields\n",
"\n",
"In previous section the concept of discrete fields was demonstrated. `DefaultDiscreteField` is subtype of `DiscreteField` which is subtype of `Field`:"
]
@@ -548,7 +551,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"There exists another type of fields too, namely `ContinuousField`s. Like the name already suggests it stores continuous time and spatial domain and it can be used to write custom fields. It needs to be callable. In this example `ContinuousField` is created which returns 1x4 dimensional array defined in $\\boldsymbol\\xi \\in [-1,1]^2, t\\in[0,1]$:"
"There exists another type of fields too: `ContinuousField`s. Like the name already suggests it stores continuous time and spatial domain and it can be used to write custom fields. It needs to be callable. In this example `ContinuousField` is created which returns 1x4 dimensional array defined in $\\boldsymbol\\xi \\in [-1,1]^2, t\\in[0,1]$:"
]
},
{
@@ -707,7 +710,7 @@
{
"data": {
"text/plain": [
"call (generic function with 1258 methods)"
"call (generic function with 1264 methods)"
]
},
"execution_count": 22,
@@ -731,7 +734,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we create two fields, one is discrete and another is continuous which takes discrete field as parameter:"
"Now we create two fields, one is discrete and another is continuous taking discrete field as input argument:"
]
},
{
@@ -796,7 +799,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we add another discrete field and see that continuous field which is \"connected\" to discrete fields updates accordingly:"
"Next we add another discrete field and see that continuous field \"connecting\" to discrete field updates accordingly:"
]
},
{
@@ -954,13 +957,13 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Basically summing the above values together we have (almost) just done numerical integration over element area. By using these two simple concepts we are able to construct rest of the results.\n",
"Basically summing the above values together we have (almost) done numerical integration over element area. By using these two simple concepts we are able to construct rest of the results.\n",
"\n",
"## Interpolation\n",
"\n",
"In earlier the concepts of `DiscreteField` and `ContinuousField` were introduced, so that now we can define discrete set of values and continuous functions. It has also been shown how fields can depend from each other such a way that we interpolate continuous field from discrete field and vice versa. \n",
"In earlier discussion the concepts of `DiscreteField` and `ContinuousField` were introduced, so that now we can define discrete set of values and continuous functions. It has also been shown how fields can depend from each other such a way that we can interpolate continuous field from discrete field and vice versa.\n",
"\n",
"This motivates us to create continuous fields which are interpolated from discrete fields using some polynomial basis. By thinking this way interpolation is nothing more than just an application of the earlier results already shown.\n",
"This motivates us to create continuous fields that are interpolated from discrete fields using some polynomial basis. By thinking this way interpolation is nothing more than just an application of the earlier results already shown.\n",
"\n",
"Some fields has special meaning in JuliaFEM. Typically one needs to define at least discrete field `geometry` and continuous field `basis` so that basic interpolation is working on element. \n",
"\n",
@@ -1132,7 +1135,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"It's also possible to take time derivatives. To do so, call `Field` with time and additional argument `Val{:derivative}`. Again, same example:"
"It's also possible to take time derivatives using finite difference approximation. To do so, call `Field` with time and additional argument `Val{:diff}`. Again, same example:"
]
},
{
@@ -1155,7 +1158,7 @@
}
],
"source": [
"pos(1.0, Val{:derivative})"
"velocity = pos(1.0, Val{:diff})"
]
},
{
@@ -1169,7 +1172,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"To interpolate in spatial domain, call `Basis` with `Increment` and coordinate $\\boldsymbol\\xi$. Increments to interpolate are the latest ones in each time step. Result depends from the content of the field. If it is scalar field, result will be scalar, if it's vector the result will be vector and so on.\n",
"To interpolate in spatial domain, call `Basis` with `Increment` and coordinate $\\boldsymbol\\xi$. Increments to interpolate are the latest ones in each time step by default. Result depends from the content of the field. If it is scalar field, result will be scalar, if it's vector the result will be vector and so on.\n",
"\n",
"Let's have a $\\Omega = \\left[0,1\\right]\\times\\left[0,1\\right] \\in \\mathbb{R}^2$ domain with a displacement field\n",
"\\begin{equation}\n",
@@ -1248,6 +1251,7 @@
}
],
"source": [
"# evaluate geometry + displacement at midpoint, basically x = X + u\n",
"N(X_increment, [0.0, 0.0]) + N(u_increment, [0.0, 0.0])"
]
},
@@ -1255,7 +1259,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Calculating gradient of vector field, i.e, $u_{i,j} = \\frac{\\partial u_i}{\\partial X_j}$:"
"Calculating gradients is also possible, for scalar or vector fields, if passing additional argument `Val{:grad}`. Here's an example of gradient of vector field, i.e, $u_{i,j} = \\frac{\\partial u_i}{\\partial X_j}$:"
]
},
{
@@ -1280,14 +1284,14 @@
],
"source": [
"N = Basis(basis, dbasis)\n",
"gradu = N(X_increment, u_increment, [0.0, 0.0], Val{:gradient})"
"gradu = N(X_increment, u_increment, [0.0, 0.0], Val{:grad})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Calculating time derivative of small strain tensor $\\epsilon$ is basically:"
"One can of course combine the above results. In this case field must be first interpolated in time domain and after that in spatial domain. So calculating time derivative of small strain tensor $\\epsilon$ is basically:"
]
},
{
@@ -1311,10 +1315,211 @@
}
],
"source": [
"du = u(1.0, Val{:derivative})\n",
"grad_du = N(X_increment, du, [0.0, 0.0], Val{:gradient})\n",
"du = u(1.0, Val{:diff})\n",
"grad_du = N(X_increment, du, [0.0, 0.0], Val{:grad})\n",
"strain_rate = 1/2*(grad_du + grad_du')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Symbolic fields\n",
"\n",
"There's still one kind of field not yet introduced, namely *symbolic fields*:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"JuliaFEM.SymbolicField(\"displacement\")"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u = Field(\"displacement\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The idea is to write equation in expression form using tiny symbolic interface and evaluate equations afterwards. Main benefits: \n",
"\n",
"- possibility to simplify equations symbolically\n",
"- prettier syntax\n",
"- \"lazy evaluation\" gives possibilities to optimize performance.\n",
"\n",
"Here's a preliminary example how this could work:"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# in future this will be something like this:\n",
"# u = Field(\"displacement\")\n",
"# eps = 1/2*(grad(u) + grad(u)')\n",
"# strain_rate = diff(eps)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(1 / 2) * (grad(diff(displacement)) + grad(diff(displacement))')"
]
}
],
"source": [
"# now this is\n",
"expr = JuliaFEM.Expression(\"1/2*(grad(diff(displacement)) + grad(diff(displacement))')\")\n",
"print(expr.expr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Evaluation of expression: call `Basis` with `FieldSet`, $\\boldsymbol\\xi$ and time as arguments:"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: expression = (1 / 2) * (grad(diff(displacement)) + grad(diff(displacement))')\n",
"INFO: expression = 1 / 2\n",
"INFO: new expression: 1 / 2\n",
"INFO: expression = grad(diff(displacement)) + grad(diff(displacement))'\n",
"INFO: expression = grad(diff(displacement))\n",
"INFO: inside gradient operator\n",
"INFO: gradient args: Any[:grad,:(diff(displacement))]\n",
"INFO: expression inside gradient\n",
"INFO: grad: evaluate field diff(displacement)\n",
"INFO: taking time derivative of displacement\n",
"INFO: expression = diff(displacement)\n",
"INFO: inside diff operator\n",
"INFO: data = Any[[0.0,0.0],[1.0,-1.0],[2.0,3.0],[0.0,0.0]]\n",
"INFO: evaluate geometry\n",
"INFO: evaluate gradient\n",
"INFO: expression = grad(diff(displacement))'\n",
"INFO: transpose\n",
"INFO: expression = transpose(grad(diff(displacement)))\n",
"INFO: expression = grad(diff(displacement))\n",
"INFO: inside gradient operator\n",
"INFO: gradient args: Any[:grad,:(diff(displacement))]\n",
"INFO: expression inside gradient\n",
"INFO: evaluate gradient\n",
"INFO: new expression: transpose([1.5 0.5\n",
" 1.0 2.0])\n",
"INFO: new expression: [1.5 0.5\n",
" 1.0 2.0] + transpose([1.5 0.5\n",
" 1.0 2.0])\n",
"INFO: new expression: (1 / 2) * ([1.5 0.5\n",
" 1.0 2.0] + transpose([1.5 0.5\n",
" 1.0 2.0]))\n"
]
}
],
"source": [
"X = Field(Vector[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])\n",
"u = Field(\n",
" (0.5, Vector[[0.0, 0.0], [0.5, -0.5], [1.0, 1.5], [0.0, 0.0]]),\n",
" (1.5, Vector[[0.0, 0.0], [1.5, -1.5], [3.0, 4.5], [0.0, 0.0]]))\n",
"fs = FieldSet()\n",
"fs[\"geometry\"] = X\n",
"fs[\"displacement\"] = u\n",
"xi = [0.0, 0.0]\n",
"time = 1.0\n",
"result = N(expr, fs, xi, time);"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
":((1 / 2) * (2x2 Array{Float64,2}:\n",
" 1.5 0.5\n",
" 1.0 2.0 + transpose(2x2 Array{Float64,2}:\n",
" 1.5 0.5\n",
" 1.0 2.0)))"
]
},
"execution_count": 46,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What happened is that fields were automatically interpolated and substituted to the equation. The result is `Expr` and can be evaluated like usual:"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2x2 Array{Float64,2}:\n",
" 1.5 0.75\n",
" 0.75 2.0 "
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"strain_rate = eval(result)"
]
}
],
"metadata": {