changeset 831:760c11e81fd4 operator_storage_array_of_table

Introduce parse_tuple and parse_scalar and replace all external calls to parse_rational
author Jonatan Werpers <jonatan@werpers.com>
date Wed, 12 Jan 2022 15:32:58 +0100
parents 21ab60cc0a5c
children 00f6bbdcd73a
files src/SbpOperators/readoperator.jl test/SbpOperators/readoperator_test.jl test/SbpOperators/volumeops/inner_products/inner_product_test.jl test/SbpOperators/volumeops/inner_products/inverse_inner_product_test.jl
diffstat 4 files changed, 105 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/SbpOperators/readoperator.jl	Wed Jan 12 14:59:03 2022 +0100
+++ b/src/SbpOperators/readoperator.jl	Wed Jan 12 15:32:58 2022 +0100
@@ -4,7 +4,8 @@
 export get_stencil_set
 
 export parse_stencil
-export parse_rational
+export parse_scalar
+export parse_tuple
 
 export sbp_operators_path
 
@@ -32,6 +33,7 @@
     # Parsing as rationals is intentional, allows preserving exactness, which can be lowered using converts or promotions later.
 # TODO: readoperator.jl file name?
 # TODO: Remove references to toml for dict-input arguments
+# TODO: Documetning the format: Allows representing rationals as strings
 
 """
     read_stencil_set(fn; filters)
@@ -109,6 +111,22 @@
     end
 end
 
+
+function parse_scalar(toml)
+    try
+        return parse_rational(toml)
+    catch e
+        throw(ArgumentError("must be a number or a string representing a number."))
+    end
+end
+
+function parse_tuple(toml)
+    if !(toml isa Array)
+        throw(ArgumentError("argument must be an array"))
+    end
+    return Tuple(parse_scalar.(toml))
+end
+
 function parse_rational(toml)
     if toml isa String
         expr = Meta.parse(replace(toml, "/"=>"//"))
--- a/test/SbpOperators/readoperator_test.jl	Wed Jan 12 14:59:03 2022 +0100
+++ b/test/SbpOperators/readoperator_test.jl	Wed Jan 12 15:32:58 2022 +0100
@@ -5,25 +5,6 @@
 
 import Sbplib.SbpOperators.Stencil
 
-
-@testset "parse_rational" begin
-    @test SbpOperators.parse_rational("1") isa Rational
-    @test SbpOperators.parse_rational("1") == 1//1
-    @test SbpOperators.parse_rational("1/2") isa Rational
-    @test SbpOperators.parse_rational("1/2") == 1//2
-    @test SbpOperators.parse_rational("37/13") isa Rational
-    @test SbpOperators.parse_rational("37/13") == 37//13
-
-    @test SbpOperators.parse_rational(0.5) isa Rational
-    @test SbpOperators.parse_rational(0.5) == 1//2
-
-    @test SbpOperators.parse_rational("0.5") isa Rational
-    @test SbpOperators.parse_rational("0.5") == 1//2
-
-    @test SbpOperators.parse_rational(2) isa Rational
-    @test SbpOperators.parse_rational(2) == 2//1
-end
-
 @testset "readoperator" begin
     toml_str = """
         [meta]
@@ -126,4 +107,66 @@
         @test parse_stencil(Float64, TOML.parse(toml)["s2"]) == Stencil(2/1, -5/1, 4/1, -1/1, 0/1, 0/1; center=1)
         @test parse_stencil(Float64, TOML.parse(toml)["s3"]) == Stencil(1/1, -2/1, 1/1, 0/1, 0/1, 0/1; center=2)
     end
+
+    @testset "parse_scalar" begin
+        toml = TOML.parse("""
+            a1 = 1
+            a2 = 1.5
+            a3 = 1.0
+            a4 = 10
+            a5 = "1/2"
+            a6 = "1.5"
+
+            e1 = [1,2,3]
+            e2 = "a string value"
+        """)
+
+        @test parse_scalar(toml["a1"]) == 1//1
+        @test parse_scalar(toml["a2"]) == 3//2
+        @test parse_scalar(toml["a3"]) == 1//1
+        @test parse_scalar(toml["a4"]) == 10//1
+        @test parse_scalar(toml["a5"]) == 1//2
+        @test parse_scalar(toml["a6"]) == 3//2
+
+        @test_throws ArgumentError parse_scalar(toml["e1"])
+        @test_throws ArgumentError parse_scalar(toml["e2"])
+    end
+
+    @testset "parse_tuple" begin
+        toml = TOML.parse("""
+            t1 = [1,3,4]
+            t2 = ["1/2","3/4","2/1"]
+
+            e1 = "not a tuple"
+            e2.a="1"
+            e3 = 1
+            e4 = ["1/2","3/4","not a number"]
+        """)
+
+        @test parse_tuple(toml["t1"]) == (1//1,3//1,4//1)
+        @test parse_tuple(toml["t2"]) == (1//2,3//4,2//1)
+
+        @test_throws ArgumentError parse_tuple(toml["e1"])
+        @test_throws ArgumentError parse_tuple(toml["e2"])
+        @test_throws ArgumentError parse_tuple(toml["e3"])
+        @test_throws ArgumentError parse_tuple(toml["e4"])
+    end
 end
+
+@testset "parse_rational" begin
+    @test SbpOperators.parse_rational("1") isa Rational
+    @test SbpOperators.parse_rational("1") == 1//1
+    @test SbpOperators.parse_rational("1/2") isa Rational
+    @test SbpOperators.parse_rational("1/2") == 1//2
+    @test SbpOperators.parse_rational("37/13") isa Rational
+    @test SbpOperators.parse_rational("37/13") == 37//13
+
+    @test SbpOperators.parse_rational(0.5) isa Rational
+    @test SbpOperators.parse_rational(0.5) == 1//2
+
+    @test SbpOperators.parse_rational("0.5") isa Rational
+    @test SbpOperators.parse_rational("0.5") == 1//2
+
+    @test SbpOperators.parse_rational(2) isa Rational
+    @test SbpOperators.parse_rational(2) == 2//1
+end
--- a/test/SbpOperators/volumeops/inner_products/inner_product_test.jl	Wed Jan 12 14:59:03 2022 +0100
+++ b/test/SbpOperators/volumeops/inner_products/inner_product_test.jl	Wed Jan 12 15:32:58 2022 +0100
@@ -15,8 +15,8 @@
     integral(H,v) = sum(H*v)
     @testset "inner_product" begin
         stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-        quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-        quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+        quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+        quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
         @testset "0D" begin
             H = inner_product(EquidistantGrid{Float64}(), quadrature_interior, quadrature_closure)
             @test H == IdentityMapping{Float64}()
@@ -38,8 +38,8 @@
 
     @testset "Sizes" begin
         stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-        quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-        quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+        quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+        quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
         @testset "1D" begin
             H = inner_product(g_1D, quadrature_interior, quadrature_closure)
             @test domain_size(H) == size(g_1D)
@@ -63,8 +63,8 @@
 
             @testset "2nd order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=2)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_1D, quadrature_interior, quadrature_closure)
                 for i = 1:2
                     @test integral(H,v[i]) ≈ v[i+1][end] - v[i+1][1] rtol = 1e-14
@@ -74,8 +74,8 @@
 
             @testset "4th order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_1D, quadrature_interior, quadrature_closure)
                 for i = 1:4
                     @test integral(H,v[i]) ≈ v[i+1][end] -  v[i+1][1] rtol = 1e-14
@@ -90,16 +90,16 @@
             u = evalOn(g_2D,(x,y)->sin(x)+cos(y))
             @testset "2nd order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=2)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_2D, quadrature_interior, quadrature_closure)
                 @test integral(H,v) ≈ b*Lx*Ly rtol = 1e-13
                 @test integral(H,u) ≈ π rtol = 1e-4
             end
             @testset "4th order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_2D, quadrature_interior, quadrature_closure)
                 @test integral(H,v) ≈ b*Lx*Ly rtol = 1e-13
                 @test integral(H,u) ≈ π rtol = 1e-8
--- a/test/SbpOperators/volumeops/inner_products/inverse_inner_product_test.jl	Wed Jan 12 14:59:03 2022 +0100
+++ b/test/SbpOperators/volumeops/inner_products/inverse_inner_product_test.jl	Wed Jan 12 15:32:58 2022 +0100
@@ -13,8 +13,8 @@
     g_2D = EquidistantGrid((77,66), (0.0, 0.0), (Lx,Ly))
     @testset "inverse_inner_product" begin
         stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-        quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-        quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+        quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+        quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
         @testset "0D" begin
             Hi = inverse_inner_product(EquidistantGrid{Float64}(), quadrature_interior, quadrature_closure)
             @test Hi == IdentityMapping{Float64}()
@@ -35,8 +35,8 @@
 
     @testset "Sizes" begin
         stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-        quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-        quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+        quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+        quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
         @testset "1D" begin
             Hi = inverse_inner_product(g_1D, quadrature_interior, quadrature_closure)
             @test domain_size(Hi) == size(g_1D)
@@ -55,8 +55,8 @@
             u = evalOn(g_1D,x->x^3-x^2+1)
             @testset "2nd order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=2)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_1D, quadrature_interior, quadrature_closure)
                 Hi = inverse_inner_product(g_1D, quadrature_interior, quadrature_closure)
                 @test Hi*H*v ≈ v rtol = 1e-15
@@ -64,8 +64,8 @@
             end
             @testset "4th order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_1D, quadrature_interior, quadrature_closure)
                 Hi = inverse_inner_product(g_1D, quadrature_interior, quadrature_closure)
                 @test Hi*H*v ≈ v rtol = 1e-15
@@ -77,8 +77,8 @@
             u = evalOn(g_2D,(x,y)->x*y + x^5 - sqrt(y))
             @testset "2nd order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=2)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_2D, quadrature_interior, quadrature_closure)
                 Hi = inverse_inner_product(g_2D, quadrature_interior, quadrature_closure)
                 @test Hi*H*v ≈ v rtol = 1e-15
@@ -86,8 +86,8 @@
             end
             @testset "4th order" begin
                 stencil_set = read_stencil_set(sbp_operators_path()*"standard_diagonal.toml"; order=4)
-                quadrature_interior = parse_rational(stencil_set["H"]["inner"])
-                quadrature_closure = parse_rational.(stencil_set["H"]["closure"])
+                quadrature_interior = parse_scalar(stencil_set["H"]["inner"])
+                quadrature_closure = parse_tuple(stencil_set["H"]["closure"])
                 H = inner_product(g_2D, quadrature_interior, quadrature_closure)
                 Hi = inverse_inner_product(g_2D, quadrature_interior, quadrature_closure)
                 @test Hi*H*v ≈ v rtol = 1e-15