data structures, new testing concept

This commit is contained in:
Jukka Aho
2015-11-01 18:44:50 +02:00
parent 42d81bc86d
commit b985ebf50c
17 changed files with 875 additions and 847 deletions
+183 -142
View File
@@ -8,12 +8,13 @@
"\n",
"**Author(s)**: Jukka Aho\n",
"\n",
"**Abstract**: Description of basis data structures. In this notebook the concepts of `Increment`, `TimeStep`, `Field`, `FieldSet`, `SpatialBasis`, `TemporalBasis` are intoduced. With combining these atomic structures one is able to form finite elements and interpolate it's fields in time and spatial domain.\n",
"**Abstract**: Description of basis data structures. In this notebook the concepts of `Increment`, `TimeStep`, `DiscreteField`, `ContinuousField`, `FieldSet`, `SpatialBasis` and `TemporalBasis` are intoduced. By combining these atomic structures one is able to form finite elements and interpolate it's fields in time and spatial domain.\n",
"\n",
"- `Increment` is the most atomic structure. It's a vector-like object with 1 dimension. Each element in `Increment` can be scalar, vector or tensor (2 or 4 order). It's easy to extend `Increment` to have other data types too.\n",
"- `TimeStep` is container for increments in certain time $t$.\n",
"- `Field` is container for timesteps for a single field.\n",
"- `DefaultDiscreteField` is container for timesteps for a single field.\n",
"- `FieldSet` is container for all fields.\n",
"- `DefaultContinuousField` can have continuous field variables.\n",
"\n",
"## Revision history\n",
"\n",
@@ -86,8 +87,8 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 1 entry:\n",
" \"temperature\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.Inc…"
"Dict{ASCIIString,JuliaFEM.Field} with 1 entry:\n",
" \"temperature\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(1.0,JuliaFE…"
]
},
"execution_count": 1,
@@ -96,7 +97,7 @@
}
],
"source": [
"using JuliaFEM: Increment, TimeStep, Field, FieldSet\n",
"using JuliaFEM: Increment, TimeStep, Field, FieldSet, DefaultDiscreteField\n",
"\n",
"fs = FieldSet()\n",
"i1 = Increment([1, 2, 3])\n",
@@ -105,7 +106,7 @@
"i3 = Increment([2, 3, 4])\n",
"i4 = Increment([3, 4, 5])\n",
"t2 = TimeStep(2.0, Increment[i3, i4])\n",
"f1 = Field(TimeStep[t1, t2])\n",
"f1 = DefaultDiscreteField(TimeStep[t1, t2])\n",
"fs[\"temperature\"] = f1\n",
"fs"
]
@@ -127,7 +128,10 @@
{
"data": {
"text/plain": [
"([3,4,5],JuliaFEM.Increment{Int64})"
"3-element JuliaFEM.Increment{Int64}:\n",
" 3\n",
" 4\n",
" 5"
]
},
"execution_count": 2,
@@ -136,8 +140,7 @@
}
],
"source": [
"increment = fs[\"temperature\"][end][end]\n",
"increment, typeof(increment)"
"fs[\"temperature\"][2][2]"
]
},
{
@@ -188,12 +191,12 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 5 entries:\n",
" \"fourth order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"constant scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"vector field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"second order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…"
"Dict{ASCIIString,JuliaFEM.Field} with 5 entries:\n",
" \"fourth order tensor fi… => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(…\n",
" \"constant scalar field\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(…\n",
" \"vector field\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(…\n",
" \"scalar field\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(…\n",
" \"second order tensor fi… => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(…"
]
},
"execution_count": 4,
@@ -228,10 +231,10 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 3 entries:\n",
" \"density\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.Inc…\n",
" \"geometry\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.Inc…\n",
" \"temperature\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.Inc…"
"Dict{ASCIIString,JuliaFEM.Field} with 3 entries:\n",
" \"density\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaFE…\n",
" \"geometry\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaFE…\n",
" \"temperature\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaFE…"
]
},
"execution_count": 5,
@@ -287,26 +290,20 @@
},
"outputs": [
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 6 entries:\n",
" \"fourth order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"constant scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"vector field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"time series\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"second order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
"name": "stderr",
"output_type": "stream",
"text": [
"INFO: time on last timestep: 1.0\n"
]
}
],
"source": [
"fs2[\"time series\"] = (0.0, [1, 2, 3, 4]), (0.5, [2, 3, 4, 5]), (1.0, [1, 1, 1, 1])\n",
"fs2[\"time series\"][end].time\n",
"fs2"
"t0 = TimeStep(0.0, Increment([1, 2, 3, 4]))\n",
"t1 = TimeStep(0.5, Increment([2, 3, 4, 5]))\n",
"t2 = TimeStep(1.0, Increment([1, 1, 1, 1]))\n",
"fs2[\"time series\"] = [t0, t1, t2]\n",
"\n",
"info(\"time on last timestep: $(fs2[\"time series\"][end].time)\")"
]
},
{
@@ -324,21 +321,16 @@
},
"outputs": [
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 7 entries:\n",
" \"fourth order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"constant scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"vector field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"scalar field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"time series\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"time series 2\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…\n",
" \"second order tensor fi… => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[J…"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
"ename": "LoadError",
"evalue": "LoadError: MethodError: `convert` has no method matching convert(::Type{Float64}, ::Array{Int64,1})\nThis may have arisen from a call to the constructor Float64(...),\nsince type constructors fall back to convert methods.\nClosest candidates are:\n call{T}(::Type{T}, ::Any)\n convert(::Type{Float64}, !Matched::Int8)\n convert(::Type{Float64}, !Matched::Int16)\n ...\nwhile loading In[8], in expression starting on line 1",
"output_type": "error",
"traceback": [
"LoadError: MethodError: `convert` has no method matching convert(::Type{Float64}, ::Array{Int64,1})\nThis may have arisen from a call to the constructor Float64(...),\nsince type constructors fall back to convert methods.\nClosest candidates are:\n call{T}(::Type{T}, ::Any)\n convert(::Type{Float64}, !Matched::Int8)\n convert(::Type{Float64}, !Matched::Int16)\n ...\nwhile loading In[8], in expression starting on line 1",
"",
" in convert at /home/jukka/.julia/v0.4/JuliaFEM/src/fields.jl:205",
" in call at essentials.jl:56",
" in setindex! at dict.jl:641"
]
}
],
"source": [
@@ -363,9 +355,9 @@
{
"data": {
"text/plain": [
"2-element Array{JuliaFEM.TimeStep{T},1}:\n",
" JuliaFEM.Increment[[1,2,3,4]]\n",
" JuliaFEM.Increment[[2,3,4,5]]"
"2-element Array{JuliaFEM.TimeStep,1}:\n",
" JuliaFEM.TimeStep(0.0,JuliaFEM.Increment[[1,2,3,4]])\n",
" JuliaFEM.TimeStep(1.0,JuliaFEM.Increment[[2,3,4,5]])"
]
},
"execution_count": 9,
@@ -375,7 +367,7 @@
],
"source": [
"T0 = first(fs[\"temperature\"]) # pick first timestep (or to be spesific, last increment of first timestep)\n",
"T1 = T0 + 1 # create new increment from old one\n",
"T1 = Increment(T0 + 1) # create new increment from old one\n",
"timestep = TimeStep(1.0, T1) # create new timestep at t=1.0\n",
"push!(fs[\"temperature\"], timestep) # push to field"
]
@@ -533,7 +525,7 @@
"source": [
"### Creating continuous and discrete fields\n",
"\n",
"In the last section the concept of fields was demonstrated. The `Field` is actually just a typealias for a `DefaultDiscreteField` and `DefaultDiscreteField` is subtype of `DiscreteField` which is subtype of `AbstractField`:"
"In previous section the concept of discrete fields was demonstrated. `DefaultDiscreteField` is subtype of `DiscreteField` which is subtype of `Field`:"
]
},
{
@@ -555,8 +547,8 @@
}
],
"source": [
"using JuliaFEM: AbstractField, DiscreteField\n",
"Field <: DiscreteField <: AbstractField"
"using JuliaFEM: DefaultDiscreteField, DiscreteField, Field\n",
"DefaultDiscreteField <: DiscreteField <: Field"
]
},
{
@@ -574,7 +566,7 @@
},
"outputs": [],
"source": [
"using JuliaFEM: FieldSet, ContinuousField"
"using JuliaFEM: FieldSet, DefaultContinuousField, ContinuousField"
]
},
{
@@ -587,7 +579,7 @@
{
"data": {
"text/plain": [
"MyFunnyField()"
"MyContinuousField()"
]
},
"execution_count": 17,
@@ -596,12 +588,12 @@
}
],
"source": [
"type MyFunnyField <: ContinuousField\n",
"type MyContinuousField <: ContinuousField\n",
"end\n",
"function Base.call(f::MyFunnyField, xi::Vector, time::Number)\n",
"function Base.call(f::MyContinuousField, xi::Vector, time::Number)\n",
" time/4*[(1-xi[1])*(1-xi[2]) (1+xi[1])*(1-xi[2]) (1+xi[1])*(1+xi[2]) (1-xi[1])*(1+xi[2])]\n",
"end\n",
"f = MyFunnyField()"
"f = MyContinuousField()"
]
},
{
@@ -637,8 +629,8 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 1 entry:\n",
" \"basis\" => MyFunnyField()"
"Dict{ASCIIString,JuliaFEM.Field} with 1 entry:\n",
" \"basis\" => MyContinuousField()"
]
},
"execution_count": 19,
@@ -648,7 +640,7 @@
],
"source": [
"fs = FieldSet()\n",
"fs[\"basis\"] = MyFunnyField()\n",
"fs[\"basis\"] = MyContinuousField()\n",
"fs"
]
},
@@ -679,7 +671,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Naturally we can pass another fields or even fieldsets to continuous field to make fields depend from each other. Here's another example, where `ContinuousField` takes another field and operates it with some function."
"Again we have a shortcut to quickly define continuous fields:"
]
},
{
@@ -692,7 +684,7 @@
{
"data": {
"text/plain": [
"call (generic function with 1246 methods)"
"6.0"
]
},
"execution_count": 21,
@@ -701,11 +693,41 @@
}
],
"source": [
"type MyFunnyContinuousField <: ContinuousField\n",
"fs[\"continuous field\"] = (xi, t) -> xi[1]*xi[2]*t\n",
"fs[\"continuous field\"]([1.0, 2.0], 3.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Naturally we can pass another fields or even fieldsets to continuous field to make fields depend from each other. Here's another example, where `ContinuousField` takes another field and operates it with some function."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"call (generic function with 1259 methods)"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type MyContinuousField2 <: ContinuousField\n",
" basis :: Function\n",
" discrete_field :: DiscreteField\n",
"end\n",
"function Base.call(field::MyFunnyContinuousField, xi::Vector, time::Number=1.0)\n",
"function Base.call(field::MyContinuousField2, xi::Vector, time::Number=1.0)\n",
" data = last(field.discrete_field) # get the last timestep last increment\n",
" basis = field.basis(xi) # evaluate basis at point ξ.\n",
" sum([basis[i]*data[i] for i=1:length(data)]) # sum results\n",
@@ -721,7 +743,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 23,
"metadata": {
"collapsed": false
},
@@ -729,10 +751,10 @@
{
"data": {
"text/plain": [
"MyFunnyContinuousField(basis,JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.Increment[[1,2,3,4]]]))"
"MyContinuousField2(basis,JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaFEM.Increment[[1,2,3,4]])]))"
]
},
"execution_count": 22,
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
@@ -745,7 +767,7 @@
" (1+xi[1])*(1-xi[2]),\n",
" (1+xi[1])*(1+xi[2]),\n",
" (1-xi[1])*(1+xi[2])]\n",
"fs[\"continuous field\"] = MyFunnyContinuousField(basis, fs[\"discrete field\"])"
"fs[\"continuous field\"] = MyContinuousField2(basis, fs[\"discrete field\"])"
]
},
{
@@ -757,7 +779,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 24,
"metadata": {
"collapsed": false
},
@@ -768,7 +790,7 @@
"(2.5,[1,2,3,4])"
]
},
"execution_count": 23,
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
@@ -786,7 +808,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 25,
"metadata": {
"collapsed": false
},
@@ -794,19 +816,19 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 2 entries:\n",
" \"continuous field\" => MyFunnyContinuousField(basis,JuliaFEM.DefaultDiscreteFi…\n",
" \"discrete field\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFE…"
"Dict{ASCIIString,JuliaFEM.Field} with 2 entries:\n",
" \"continuous field\" => MyContinuousField2(basis,JuliaFEM.DefaultDiscreteField(…\n",
" \"discrete field\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,Ju…"
]
},
"execution_count": 24,
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"T0 = last(fs[\"discrete field\"])\n",
"push!(fs[\"discrete field\"], TimeStep(1.0, T0 + 1.0)) # push to field\n",
"push!(fs[\"discrete field\"], TimeStep(1.0, Increment(T0 + 1.0))) # push to field\n",
"fs"
]
},
@@ -819,7 +841,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 26,
"metadata": {
"collapsed": false
},
@@ -827,10 +849,10 @@
{
"data": {
"text/plain": [
"(3.5,[2,3,4,5])"
"(3.5,[2.0,3.0,4.0,5.0])"
]
},
"execution_count": 25,
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
@@ -848,7 +870,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 27,
"metadata": {
"collapsed": false
},
@@ -859,7 +881,7 @@
"(2.5,3.5)"
]
},
"execution_count": 26,
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
@@ -877,7 +899,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 28,
"metadata": {
"collapsed": false
},
@@ -888,28 +910,28 @@
"getindex (generic function with 126 methods)"
]
},
"execution_count": 27,
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"using JuliaFEM: DiscreteField\n",
"type MyFunnyDiscreteField <: DiscreteField\n",
"type MyDiscreteField <: DiscreteField\n",
" discrete_points :: Vector\n",
" continuous_field :: ContinuousField\n",
"end\n",
"Base.length(field::MyFunnyDiscreteField) = length(field.discrete_points)\n",
"Base.endof(field::MyFunnyDiscreteField) = endof(field.discrete_points)\n",
"Base.last(field::MyFunnyDiscreteField) = Float64[field[i] for i=1:length(field)]\n",
"function Base.getindex(field::MyFunnyDiscreteField, idx::Int64)\n",
"Base.length(field::MyDiscreteField) = length(field.discrete_points)\n",
"Base.endof(field::MyDiscreteField) = endof(field.discrete_points)\n",
"Base.last(field::MyDiscreteField) = Float64[field[i] for i=1:length(field)]\n",
"function Base.getindex(field::MyDiscreteField, idx::Int64)\n",
" field.continuous_field(field.discrete_points[idx])\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 29,
"metadata": {
"collapsed": false
},
@@ -924,14 +946,14 @@
" 4.24402"
]
},
"execution_count": 28,
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"discrete_points = 1.0/sqrt(3.0)*Vector[[-1, -1], [1, -1], [1, 1], [-1, 1]]\n",
"fs[\"discrete field 2\"] = MyFunnyDiscreteField(discrete_points, fs[\"continuous field\"])\n",
"fs[\"discrete field 2\"] = MyDiscreteField(discrete_points, fs[\"continuous field\"])\n",
"last(fs[\"discrete field 2\"])"
]
},
@@ -952,7 +974,7 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 30,
"metadata": {
"collapsed": false
},
@@ -963,7 +985,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 31,
"metadata": {
"collapsed": false
},
@@ -976,7 +998,7 @@
" 0.2"
]
},
"execution_count": 30,
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
@@ -996,7 +1018,7 @@
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": 32,
"metadata": {
"collapsed": false
},
@@ -1008,7 +1030,7 @@
" 0.25 0.25 0.25 0.25"
]
},
"execution_count": 31,
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
@@ -1028,7 +1050,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": 33,
"metadata": {
"collapsed": false
},
@@ -1039,7 +1061,7 @@
"([0.0,0.5,1.0,1.5,2.0],[0.0,0.125,0.5,1.125,2.0])"
]
},
"execution_count": 32,
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
@@ -1051,28 +1073,6 @@
"t, x"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"((0.0,0.0),(0.5,0.125),(1.0,0.5),(1.5,1.125),(2.0,2.0))"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x2 = tuple(collect(zip(t, x))...)"
]
},
{
"cell_type": "code",
"execution_count": 34,
@@ -1093,7 +1093,14 @@
}
],
"source": [
"fs[\"particle position\"] = x2\n",
"timesteps = TimeStep[]\n",
"for (ti, xi) in zip(t, x)\n",
" increment = Increment(xi)\n",
" push!(timesteps, TimeStep(ti, increment))\n",
"end\n",
"\n",
"#fs[\"particle position\"] = t, 1/2*t.^2\n",
"fs[\"particle position\"] = timesteps\n",
"temporalbasis = TemporalBasis((t) -> [1-t, t], (t) -> [-1, 1])\n",
"call(fs[\"particle position\"], temporalbasis, 1.0)"
]
@@ -1105,6 +1112,29 @@
"It's also possible to take time derivatives. To do so, call `Field` with `TemporalBasis`, time, and additional argument `Val{:derivative}`. Again, same example:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{Float64,1}:\n",
" 1.0"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"call(fs[\"particle position\"], temporalbasis, 1.0, Val{:derivative})"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -1123,7 +1153,7 @@
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 36,
"metadata": {
"collapsed": false
},
@@ -1131,12 +1161,12 @@
{
"data": {
"text/plain": [
"Dict{ASCIIString,JuliaFEM.AbstractField} with 2 entries:\n",
" \"geometry\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.In…\n",
" \"displacement\" => JuliaFEM.DefaultDiscreteField(JuliaFEM.TimeStep[JuliaFEM.In…"
"Dict{ASCIIString,JuliaFEM.Field} with 2 entries:\n",
" \"geometry\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaF…\n",
" \"displacement\" => JuliaFEM.DefaultDiscreteField([JuliaFEM.TimeStep(0.0,JuliaF…"
]
},
"execution_count": 35,
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
@@ -1144,13 +1174,15 @@
"source": [
"fs = FieldSet()\n",
"fs[\"geometry\"] = Vector{Float64}[[0.0,0.0], [1.0,0.0], [1.0,1.0], [0.0,1.0]]\n",
"fs[\"displacement\"] = (0.0, zeros(2, 4)), (1.0, Vector[[0.0, 0.0], [0.0, 0.0], [0.25, 0.0], [0.0, 0.0]])\n",
"u0 = TimeStep(0.0, Increment(zeros(2, 4)))\n",
"u1 = TimeStep(1.0, Increment(Vector[[0.0, 0.0], [0.0, 0.0], [0.25, 0.0], [0.0, 0.0]]))\n",
"fs[\"displacement\"] = [u0, u1]\n",
"fs"
]
},
{
"cell_type": "code",
"execution_count": 36,
"execution_count": 37,
"metadata": {
"collapsed": false
},
@@ -1163,7 +1195,7 @@
" 0.5 "
]
},
"execution_count": 36,
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
@@ -1185,7 +1217,7 @@
},
{
"cell_type": "code",
"execution_count": 37,
"execution_count": 38,
"metadata": {
"collapsed": false
},
@@ -1198,7 +1230,7 @@
" 0.0 0.0 "
]
},
"execution_count": 37,
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
@@ -1220,7 +1252,7 @@
},
{
"cell_type": "code",
"execution_count": 38,
"execution_count": 39,
"metadata": {
"collapsed": false
},
@@ -1231,7 +1263,7 @@
"FiniteElement"
]
},
"execution_count": 38,
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
@@ -1263,17 +1295,17 @@
},
{
"cell_type": "code",
"execution_count": 39,
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"ename": "LoadError",
"evalue": "LoadError: MethodError: `setindex!` has no method matching setindex!(::FiniteElement, ::Array{Array{Float64,1},1}, ::ASCIIString)\nwhile loading In[39], in expression starting on line 2",
"evalue": "LoadError: MethodError: `setindex!` has no method matching setindex!(::FiniteElement, ::Array{Array{Float64,1},1}, ::ASCIIString)\nwhile loading In[40], in expression starting on line 2",
"output_type": "error",
"traceback": [
"LoadError: MethodError: `setindex!` has no method matching setindex!(::FiniteElement, ::Array{Array{Float64,1},1}, ::ASCIIString)\nwhile loading In[39], in expression starting on line 2",
"LoadError: MethodError: `setindex!` has no method matching setindex!(::FiniteElement, ::Array{Array{Float64,1},1}, ::ASCIIString)\nwhile loading In[40], in expression starting on line 2",
""
]
}
@@ -1295,6 +1327,15 @@
"strain_rate = diff(strain)\n",
"strain_rate([0.0, 0.0], 1.0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
@@ -47,30 +47,6 @@
"- variational form, \"principle of minimum potential energy\": there exists some functional or \"potential function\" $\\Pi$ we are minimizing"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Logger(root,DEBUG,Base.PipeEndpoint(open, 0 bytes waiting),root)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"using Logging\n",
"using FactCheck\n",
"Logging.configure(level=DEBUG)"
]
},
{
"cell_type": "markdown",
"metadata": {},
@@ -89,13 +65,13 @@
},
{
"cell_type": "code",
"execution_count": 69,
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"using JuliaFEM: Element, Field, FieldSet, Basis"
"using JuliaFEM: Element, Basis, FieldSet"
]
},
{
@@ -107,7 +83,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 2,
"metadata": {
"collapsed": false
},
@@ -116,7 +92,7 @@
"type MyQuad4 <: Element\n",
" connectivity :: Array{Int, 1}\n",
" basis :: Basis\n",
" fields :: Dict{ASCIIString, FieldSet}\n",
" fields :: FieldSet\n",
"end"
]
},
@@ -129,7 +105,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 3,
"metadata": {
"collapsed": false
},
@@ -140,7 +116,7 @@
"MyQuad4"
]
},
"execution_count": 5,
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
@@ -165,7 +141,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 4,
"metadata": {
"collapsed": false
},
@@ -173,10 +149,10 @@
{
"data": {
"text/plain": [
"size (generic function with 74 methods)"
"size (generic function with 81 methods)"
]
},
"execution_count": 6,
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -192,6 +168,68 @@
"Here comes one important thing. We always define our \"things\" so that the first index is dimension, like $(x, y, z)$ or $(\\xi_1, \\xi_2, \\xi_3)$ and second index is basis function number / node id or something similar to that. To motivate this, consider the following example:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2x4 Array{Int64,2}:\n",
" 1 3 5 7\n",
" 2 4 6 8"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x = [1 2; 3 4; 5 6; 7 8]'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, if we consider $x$ as of some field e.g. geometry, our coordinates of first node is $(1, 2)$, second is $(3, 4)$ and so on. Typically on vector field problems the global assembly is something like $(u_1, v_1, u_2, v_2, \\ldots, )$. If fields are defined this way we can easily flatten matrix to vector and back:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"8-element Array{Int64,1}:\n",
" 1\n",
" 2\n",
" 3\n",
" 4\n",
" 5\n",
" 6\n",
" 7\n",
" 8"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dim = size(x)\n",
"x2 = vec(x)"
]
},
{
"cell_type": "code",
"execution_count": 7,
@@ -212,68 +250,6 @@
"output_type": "execute_result"
}
],
"source": [
"x = [1 2; 3 4; 5 6; 7 8]'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, if we consider $x$ as of some field e.g. geometry, our coordinates of first node is $(1, 2)$, second is $(3, 4)$ and so on. Typically on vector field problems the global assembly is something like $(u_1, v_1, u_2, v_2, \\ldots, )$. If fields are defined this way we can easily flatten matrix to vector and back:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"8-element Array{Int64,1}:\n",
" 1\n",
" 2\n",
" 3\n",
" 4\n",
" 5\n",
" 6\n",
" 7\n",
" 8"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dim = size(x)\n",
"x2 = vec(x)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2x4 Array{Int64,2}:\n",
" 1 3 5 7\n",
" 2 4 6 8"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"reshape(x2, dim)"
]
@@ -287,7 +263,7 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 8,
"metadata": {
"collapsed": false
},
@@ -317,7 +293,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 9,
"metadata": {
"collapsed": false
},
@@ -326,15 +302,22 @@
"name": "stderr",
"output_type": "stream",
"text": [
"28-Oct 04:26:43:INFO:root:Testing element MyQuad4\n",
"28-Oct 04:26:43:INFO:root:element dimension: 2 x 4\n",
"28-Oct 04:26:43:INFO:root:Initializing element\n",
"28-Oct 04:26:43:INFO:root:basis at [0.0,0.0]: [0.25 0.25 0.25 0.25]\n",
"28-Oct 04:26:43:INFO:root:field val at [0.0,0.0]: 2.5\n",
"28-Oct 04:26:43:INFO:root:derivative of basis at [0.0,0.0]: [-0.5 0.5 0.5 -0.5\n",
" -0.5 -0.5 0.5 0.5]\n",
"28-Oct 04:26:43:INFO:root:field val at [0.0,0.0]: [0.0 2.0]\n",
"28-Oct 04:26:43:INFO:root:Element MyQuad4 passed tests.\n"
"INFO: Testing element MyQuad4\n",
"INFO: element dimension: 2 x 4\n",
"INFO: Initializing element\n",
"INFO: basis at [0.0,0.0]: [0.25 0.25 0.25 0.25]\n",
"INFO: field val at [0.0,0.0]: 0.0\n"
]
},
{
"ename": "LoadError",
"evalue": "LoadError: MethodError: `inv` has no method matching inv(::Array{Float64,1})\nwhile loading In[9], in expression starting on line 2",
"output_type": "error",
"traceback": [
"LoadError: MethodError: `inv` has no method matching inv(::Array{Float64,1})\nwhile loading In[9], in expression starting on line 2",
"",
" in call at /home/jukka/.julia/v0.4/JuliaFEM/src/elements.jl:147",
" in test_element at /home/jukka/.julia/v0.4/JuliaFEM/src/elements.jl:57"
]
}
],
@@ -1291,6 +1274,7 @@
" u = basis(\"displacement\", ip, time, variation)\n",
" ∇u = dbasis(\"displacement\", ip, time, variation)\n",
" F = I + ∇u\n",
" # F = F_e*F_p\n",
" b = basis(\"displacement volume load\", ip, time)\n",
" E = 1/2*(F'*F - I)\n",
" S = λ*trace(E)*I + 2*μ*E\n",