From ff60b7ed3a4aa9be4e9621ef0e31176fe7048a22 Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Sun, 1 Nov 2015 18:47:33 +0200 Subject: [PATCH] forget couple new files --- src/fields.jl | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.jl | 145 ++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+) create mode 100644 src/fields.jl create mode 100644 src/test.jl diff --git a/src/fields.jl b/src/fields.jl new file mode 100644 index 0000000..d0218a4 --- /dev/null +++ b/src/fields.jl @@ -0,0 +1,261 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +# https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/notebooks/2015-06-14-data-structures.ipynb + +abstract Field +abstract DiscreteField <: Field +abstract ContinuousField <: Field + +### DEFAULT DISCRETE FIELD ### + +# 1. Increment + +type Increment{T} <: AbstractVector{T} + data :: Vector{T} +end + +function Base.size(increment::Increment) + size(increment.data) +end + +function Base.linearindexing(::Type{Increment}) + LinearFast() +end + +function Base.getindex(increment::Increment, i::Int) + increment.data[i] +end + +function Base.setindex!(increment::Increment, v, i::Int) + increment.data[i] = v +end + +function Base.dot(k::Number, increment::Increment) + k*increment +end + +function Base.convert(::Type{Increment}, data::Number) + Increment([data]) +end + +function Base.convert{T}(::Type{Increment}, data::Array{T, 2}) + Increment([data[:,i] for i=1:size(data, 2)]) +end + +function Base.convert{T}(::Type{Increment}, data::Array{T, 3}) + Increment([data[:,:,i] for i=1:size(data, 3)]) +end + +function Base.convert{T}(::Type{Increment}, data::Array{T, 4}) + Increment([data[:,:,:,i] for i=1:size(data, 4)]) +end + +function Base.convert{T}(::Type{Increment}, data::Array{T, 5}) + Increment([data[:,:,:,:,i] for i=1:size(data, 5)]) +end + +function Base.zeros(::Type{Increment}, dims...) + Increment(zeros(dims...)) +end + +function Base.vec(increment::Increment) + [increment...;] +end + +function Base.similar{T}(increment::Increment, data::Vector{T}) + Increment(reshape(data, round(Int, length(data)/length(increment)), length(increment))) +end + +function Base.convert{T}(::Type{Vector{T}}, increment::Increment) + return Increment[increment] +end + +# 2. TimeStep + +type TimeStep + time :: Float64 + increments :: Vector{Increment} +end + +function Base.size(timestep::TimeStep) + return size(timestep.increments) +end + +function Base.endof(timestep::TimeStep) + return endof(timestep.increments) +end + +function Base.length(timestep::TimeStep) + return length(timestep.increments) +end + +function Base.linearindexing(::Type{TimeStep}) + Base.LinearFast() +end + +function Base.getindex(timestep::TimeStep, i::Int) + return timestep.increments[i] +end + +#function TimeStep(data::Union{Number, Array}...) +# return TimeStep(0.0, Increment[Increment(d) for d in data]) +#end + +function TimeStep() + TimeStep(0.0, []) +end + +function TimeStep{T}(data::T...) + return TimeStep(0.0, Increment[Increment(d) for d in data]) +end + +function Base.convert(::Type{TimeStep}, value::Number) + return TimeStep(0.0, Increment[Increment(value)]) +end + +function Base.push!(timestep::TimeStep, increment::Increment) + push!(timestep.increments, increment) +end + +# 3. DefaultDiscreteField +type DefaultDiscreteField <: DiscreteField + timesteps :: Vector{TimeStep} +#= + function DefaultDiscreteField(data::Array) + if (typeof(data) == Vector{Int64}) || (typeof(data) == Vector{Float64}) + new(TimeStep[TimeStep(data)]) + else + new(data) + end + end +=# +end + +#= +type DefaultDiscreteField <: DiscreteField + timesteps :: Vector{TimeStep} + function DefaultDiscreteField(data...) + timesteps = TimeStep[] + for (i, d) in enumerate(data) + @debug("i = $i, d = $d") + if isa(d, Tuple) + # contains time vector + increments = Increment[Increment(d[2])] + push!(timesteps, TimeStep(d[1], increments)) + else + increments = Increment[Increment(d)] + push!(timesteps, TimeStep(i-1.0, increments)) + end + end + new(timesteps) + end +end +=# + + +function Base.size(field::DefaultDiscreteField) + return size(field.timesteps) +end + +function Base.linearindexing(::Type{DefaultDiscreteField}) + return LinearFast() +end + +function Base.getindex(field::DefaultDiscreteField, i::Int) + field.timesteps[i] +end + +function Base.length(field::DefaultDiscreteField) + length(field.timesteps) +end + +function Base.endof(field::DefaultDiscreteField) + endof(field.timesteps) +end + +function Base.first(field::DefaultDiscreteField) + return field[1][end] +end + +function Base.last(field::DefaultDiscreteField) + return field[end][end] +end + +function Base.push!(field::DefaultDiscreteField, timestep::TimeStep) + push!(field.timesteps, timestep) +end + +"""Quickly create fields. + +Examples +-------- +>>> Field([1, 2]) # creates field with one timestep and vector value [1, 2] +>>> Field(1, 2) # creates field with two timesteps, each having scalar value +>>> Field([1, 2], [3, 4]) # creates field with two timesteps, each having vector value +>>> Field( (0.0, [1, 2]), (0.5, [3, 4]) ) # like above, but give time also +""" +function Base.convert(::Type{DefaultDiscreteField}, data...) + timesteps = TimeStep[] + for (i, d) in enumerate(data) + if isa(d, Tuple) +# @debug("is tuple, has time, d = $d") + # contains time vector + increments = Increment[Increment(d[2])] + push!(timesteps, TimeStep(d[1], increments)) + else +# @debug("array without time, d = $d") +# @debug(typeof(d)) + increments = Increment[Increment(d)] + push!(timesteps, TimeStep(i-1.0, increments)) + end + end + field = DefaultDiscreteField(timesteps) + return field +end + +function Base.convert(::Type{DefaultDiscreteField}, data::Vector{TimeStep}) + field = DefaultDiscreteField(data) +# @debug(field) + return field +end + +### CONTINUOUS FIELDS ### + +type DefaultContinuousField <: ContinuousField + field :: Function +end + +function Base.call(field::DefaultContinuousField, xi::Vector, time::Number) + return field.field(xi, time) +end + +function Base.convert(::Type{DefaultContinuousField}, f::Function) + return DefaultContinuousField(f) +end + + +### FIELDSET ### + +typealias FieldSet Dict{ASCIIString, Field} + +# 1. given numbers, arrays or tuples -> discrete field + +function Base.convert(::Type{Field}, data::Union{Number, Array, Tuple}...) + return DiscreteField(data...) +end + +function Base.convert(::Type{DiscreteField}, data::Union{Number, Array, Tuple}...) + convert(DefaultDiscreteField, data...) +end + +# 2. given function -> continuous field + +function Base.convert(::Type{Field}, data::Function) + return ContinuousField(data) +end + +function Base.convert(::Type{ContinuousField}, data::Function) + convert(DefaultContinuousField, data) +end + diff --git a/src/test.jl b/src/test.jl new file mode 100644 index 0000000..206644a --- /dev/null +++ b/src/test.jl @@ -0,0 +1,145 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +""" JuliaFEM testing routines. """ +module Test + +using Base.Test + +abstract TestResult + +type NormalTestResult <: TestResult + test_function :: Function + result +end + +type CriticalTestResult <: TestResult + filename :: ASCIIString + message +end + +function TestResult(test_function::Function, result) + NormalTestResult(test_function, result) +end + +function TestResult(filename::ASCIIString, message) + CriticalTestResult(filename, message) +end + +global test_results = [] + + +function get_test_functions(func) + return Function[] +end + +""" Return all functions from module with name starting test """ +function get_test_functions(mod::Module) + test_function_names = filter((k) -> startswith(string(k), "test_"), names(mod, true)) + test_function_expressions = map((k) -> :($mod.$k), test_function_names) + test_functions = map(eval, test_function_expressions) + return test_functions +end + +""" Run tests from some file. """ +function run_test(filename::ASCIIString, test_function=nothing) + info("running tests from $filename") + test_module = nothing + try + test_module = include(filename) + catch error + warn("Unable to include file $filename for testing.") + err = Base.showerror(Base.STDOUT, error) + push!(test_results, TestResult(filename, "Unable to include file: $err")) + return + end + if isa(test_function, Void) + test_functions = get_test_functions(test_module) + else + test_functions = [eval( :($test_module.$test_function) )] + end + if length(test_functions) == 0 + warn("Unable to get test functions for file $filename. Define test functions inside module, look for test_heat.jl for concrete example how to do that.") + push!(test_results, TestResult(filename, "Unable to find test functions")) + return + end + for test_function in test_functions + run_test(test_function) + end +end + +""" Run single test set. """ +function run_test(test_function::Function) + + function test_handler(r::Base.Test.Success) + result = TestResult(test_function, r) + push!(test_results, result) + end + + function test_handler(r::Base.Test.Failure) + push!(test_results, TestResult(test_function, r)) + warn("test failed: $(r.expr)") + warn("partially evaluated expression: $(r.resultexpr)") + end + + function test_handler(r::Base.Test.Error) + push!(test_results, TestResult(test_function, r)) + warn("Error when testing: $(r.expr)") + end + + Base.Test.with_handler(test_handler) do + info("$test_function():") + # TODO: print docstring of test function if defined. + #@doc($test_function) + try + test_function() + catch error + warn("testing $test_function() stopped for critical error $error") + Base.showerror(Base.STDOUT, error) + print("\n") + warn("cannot continue to test function $test_function") + push!(test_results, TestResult("$test_function", error)) + end + info("$test_function(): done.") + end + +end + +function print_test_statistics() + info("################# TEST RESULTS #####################") + passed = 0 + failed = 0 + errors = 0 + critical = 0 + for result in test_results + if isa(result, NormalTestResult) + if isa(result.result, Base.Test.Success) + passed += 1 + continue + elseif isa(result.result, Base.Test.Failure) + failed += 1 + filename, linenum = Base.functionloc(result.test_function) + functionname = Base.function_name(result.test_function) + warn("test failed: $(result.result.expr), partially evaluated expression: $(result.result.expr)") + warn("in function $functionname, file $filename, line $linenum") + continue + elseif isa(result.result, Base.Test.Error) + errors += 1 + filename, linenum = Base.functionloc(result.test_function) + functionname = Base.function_name(result.test_function) + warn("error in function: $(result.result.expr)") + warn("in function $functionname, file $filename, line $linenum") + continue + end + elseif isa(result, CriticalTestResult) + critical += 1 + warn("Critical error on $(result.filename): $(result.message)") + end + end + info("$passed test passed, $failed test failed, $errors errors, $critical critical failures") + return passed, failed, errors, critical +end + +export @test, run_test, print_test_statistics + +end