From cc3f2a32df4178df4959c6d2aa687b7e92353ae2 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 10 Jul 2024 15:51:03 +0200 Subject: [PATCH 01/24] Update .gitignore and remove .DS_Store --- .github/.DS_Store | Bin 6148 -> 0 bytes .gitignore | 34 ++++++++++++++++++++++++++++++++-- docs/.DS_Store | Bin 10244 -> 0 bytes docs/src/.DS_Store | Bin 6148 -> 0 bytes notes/.DS_Store | Bin 6148 -> 0 bytes src/.DS_Store | Bin 6148 -> 0 bytes src/examples/.DS_Store | Bin 6148 -> 0 bytes test/.DS_Store | Bin 6148 -> 0 bytes 8 files changed, 32 insertions(+), 2 deletions(-) delete mode 100644 .github/.DS_Store delete mode 100644 docs/.DS_Store delete mode 100644 docs/src/.DS_Store delete mode 100644 notes/.DS_Store delete mode 100644 src/.DS_Store delete mode 100644 src/examples/.DS_Store delete mode 100644 test/.DS_Store diff --git a/.github/.DS_Store b/.github/.DS_Store deleted file mode 100644 index 3d5eba318b7e9c54de12a8fdb7da06710e304667..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}yIJ5FUrL@d{PSp_Pin!4lU}2N)@tffEAl{lug(}6lw4D z4f+yX`vANG=RQCmqBFKrfwD;Df>1jnjX&@F_~&zEX8=HSrqLEa9RMUMVa3CyM95FN zBo$|=Aqq3bDI}mFhb+vOqS^2q8KATC@WeEX;R5cQUp5L89isO~I7;Gd(rn&}%1ZUc z%bKjoRrxhI*Lg7MPo`O?KmI~r`&uXAqTde>;z8c4zuwd7q#vh)u}O%d0frnM#%ZMU zj-IAbW^x1Tke>8<^|jfo)okrFRJ*-1Z>ZV(R|4P-J9KqBBQ^I z9G%~t`Ir_^vcAh;oF+OwL+@ha6v@I2FaylMV;FGvhg^M362~$F%)o!a0NoD?mC$!s zSTt7$Hl_qXtfJWn_NkVj9Ock=SXe|4im<7OHdVM1L)dh*D;MWGEG*h|5U%(TZf4;s z6k%q^@s$Y&;alXE8DIwPGq7Sm>-7GAdbs|-pTu9x05kAUF(9hlpxePMxwmy`bM)3K t)MHc!(opTwW&qa?;?q7g$MOo;lTsRUj$!NeDRFh+ec!E^7OrMoT0m?%OrliWFT z?mcJDz2AK2-o1ATA<$dU+X>MKAtDwkmBo0w#YNj`nRf|(%@UM={)Fi1lAB9gPI{hg zP!S*yAP^uBAP^uBAaG|OfNM6r#5yj6dw@WIK!Cta1nB&rVWBeW%PB6|)PXm)1wdJg z)$GD&+y^ip&6iPMPI1Xx@tu740KO~uTMXdt*sf7?lu=(!amn2YaCZWJWbk(=z@np{ z#>@#sxeV?B0s#W^5ukhb1td)h#3WYL{{5qL&N5vu61f6GP3?k(i^N4@op>ZZ>6GGL z$}70Nsr(_TB^<{}m!DJVVbdrjm8L$&_EM&8%7{Yp1q#M8evZ&0VKYOJZ~D{o4;Fk6BsUIm1T*{!BpX=ZxxX z^^mNI_ISq0=9raSJ5=48bz(99z(RCN*_Y2nKkJ!mq5q9VZn82$lm@DRv>4CZmSay~ zE$wj)aY>$JDh^8SYM}k$RDn!doY{d|Zn2L8ToWoY>S~!$l3b^bjE>1kWoZ#5MT;rgD4rbAap_|);U97x7y0Ex;)ta?!k*QdDs5PjqVqUi@>X@E$g!1_eY|qJ{E#||>5;`Dx;TO` zua2s{>SHwWBPrJ#$Qd^6)iiJGS9hu7?qn)&43sdxMddQD-;4F^n_&xe>(@=s$(FoTh{GG6p zY{Fj!yUAf76G=Kt)5Q25E z9yUN5Y=J2BKrifr12712NWc+DLk0{u3Jw&Y2q)kqJPpsm8F(IEfLGxScoW`+ci;kC zgiqlTOvC5!4P1e%a1E}*ukaiE4mSizkcB#-NoW>U2rWXJ5EeRxZlRBNUMNplhboze zzoKHOmov#N`X{Ku@mu9fXy>locSgQkTg)9VHg)vfC{c64oz-eeM|UYTu`9A?C= zqB|ol`^s||H^Wj%zGqcAcV@GRXV(xi-Z&vr+A52D>wDLT$arOeudZE(>ON&5S3_-K z5wlAXm@0=N?GomYQsb*_ou~p=7h_x4Bs@Zi2t0Z?~#wm zC32a}AW?rHKa!ux4G@u@A<$qgBWN3Jgf4ghwn8^N2>q}VcEKK`Y66B}7)D_niK-)2 zC%}X}xZojOpM)uR3Z8*yk*qJmOYjPugY)n@()KN%w(r9yb7;7?nuc(3mWGwH1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0PhghN56s>KZh4j{^n2D%%-jfL8Qzp^L~?g?@iwPlDz2-*-nz5Vpd^}`;)A3XXy#R~BT;V3R4Nr(>};0LW&kxTF9`4n?`yV4Tk+Wd1notMz~O`*D;F8;!4YX}MB8wqmVVtJVW|hmGB# zHymXhZ*Y%a-C`{EXMNAV6NTe${nQPX4!tN12O=N}Lb%+&8>Imoci1QmG7;-agH^L? z-TK+dq}ggU*6ilS)#;i&xzoaa}{>!~|PW0v+{=bp z@$-G%TFmvr`%fRXnR-zV;)_|%_t5kEh#M@Ls8_^VU9^Rn^%w>W1Aol`uMajF$F{;; zq9`3u;s^k&U|0zH{4Bv^Y=v!wxkOkXRE7d&C{;%cD#I~uE5EkFT%rsoR2@F3x-(TL z6e{kH`EB7&Xj`Juh5^HX&cL#~tn>YU`}gO6J;+=c1`GoW#Q?21uG7Ji)ZSWJ9N%kg tw1;S1xL+<&gg~k7SakSSdH1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T01jedD?^X7_ z*zfG;i)zOJ+@zVG0b>9|7NL{VV`}d0I!eJp7se>DLCtcCMbAKo*reP?sL4WY5@h$EcFyZRjuPJ@Z!)xA?$2@da}- z6(QCdPiYj*F3ve;Qps@17)9SQO0%hVmtpp2);B5ZU)FVqufcLM1xx``z!cb{0z9*2 z!%;-5O#xHD6!=m=`-5i@<_X(~Ve4QOt^mXVn}gBUT|yk6Fi+SGA-)F^5XbfSF- M1VOAa1@@r8Cq|<@qW}N^ From 75ac013104c6ea3d7197a748f5be7657a23a64ca Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Mon, 15 Jul 2024 11:29:20 +0200 Subject: [PATCH 02/24] Add partial implementation of laplacian tests --- test/laplacian_test.jl | 206 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 test/laplacian_test.jl diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl new file mode 100644 index 0000000..4a89044 --- /dev/null +++ b/test/laplacian_test.jl @@ -0,0 +1,206 @@ +using Test +using GridTools + +include("mesh_definitions.jl") + +const global IDim_ = Dimension{:IDim_, LOCAL} +const global JDim_ = Dimension{:JDim_, LOCAL} +const global IDim = IDim_() +const global JDim = JDim_() + +Ioff = FieldOffset("Ioff", source=IDim, target=(IDim, Dimension{:I_, LOCAL}())) +Joff = FieldOffset("Joff", source=JDim, target=(JDim, Dimension{:J_, LOCAL}())) + +# ---------------------------------------------------------------------------------------- + +@field_operator function lap(in_field::Field{Tuple{IDim, JDim}, Float64}) + return -4.0 * in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) +end + +field_data = collect(reshape(1.:16., 4, 4)) +in_field = Field((IDim, JDim), field_data) +out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + +lap(in_field, backend="embedded", out=out_field) +@show out_field.data + +# ---------------------------------------------------------------------------------------- + +@field_operator function laplap(in_field::Field{Tuple{IDim, JDim}, Float64}) + return lap(lap(in_field)) +end + +field_data = collect(reshape(1.:16., 4, 4)) +in_field = Field((IDim, JDim), field_data) +out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + +lap(in_field, backend="embedded", out=out_field) +@show out_field.data + +# ---------------------------------------------------------------------------------------- + +# @field_operator function lap(in_field::Field{Tuple{Dimension{:IDim, HORIZONTAL}, Dimension{:JDim, HORIZONTAL}}, Float64})::Field{Tuple{Dimension{:IDim, HORIZONTAL}, Dimension{:JDim, HORIZONTAL}}, Float64} +# nrows, ncols = size(in_field.data) +# out_data = zeros(Float64, nrows, ncols) +# out_data .= in_field.data # Copy inplace: to keep the initial values in the border + +# for i in 2:(nrows - 1) +# for j in 2:(ncols - 1) +# # Perform the stencil operation +# out_data[i, j] = -4 * in_field.data[i, j] + +# in_field.data[i+1, j] + +# in_field.data[i-1, j] + +# in_field.data[i, j+1] + +# in_field.data[i, j-1] +# end +# end + +# return Field(in_field.dims, out_data) +# end + +# @field_operator function lap(in_field::Matrix{Float64})::Matrix{Float64} +# nrows, ncols = size(in_field) +# out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros +# out_field .= in_field # Copy inplace: to keep the initial values in the border +# for i in 2:(nrows - 1) +# for j in 2:(ncols - 1) +# # Perform the stencil operation +# out_field[i, j] = -4 * in_field[i, j] + +# in_field[i+1, j] + +# in_field[i-1, j] + +# in_field[i, j+1] + +# in_field[i, j-1] +# end +# end + +# return out_field +# end + +# function lap_vectorized(in_field::Matrix{Float64})::Matrix{Float64} +# nrows, ncols = size(in_field) +# out_field = zeros(Float64, nrows, ncols) +# out_field .= in_field # Copy inplace: to keep the initial values in the border +# # Vectorized operations (with slicing) +# out_field[2:end-1, 2:end-1] = -4 * in_field[2:end-1, 2:end-1] + +# in_field[3:end, 2:end-1] + # i+1 +# in_field[1:end-2, 2:end-1] + # i-1 +# in_field[2:end-1, 3:end] + # j+1 +# in_field[2:end-1, 1:end-2] # j-1 + +# return out_field +# end + +# function lap_vectorized_optimized(in_field::Matrix{Float64})::Matrix{Float64} +# nrows, ncols = size(in_field) +# out_field = zeros(Float64, nrows, ncols) +# out_field .= in_field + +# # Prepare shifted arrays by slicing without creating new arrays +# north = @view in_field[1:end-2, 2:end-1] # Shift up (1 row) +# south = @view in_field[3:end, 2:end-1] # Shift down (1 row) +# west = @view in_field[2:end-1, 1:end-2] # Shift left (1 col) +# east = @view in_field[2:end-1, 3:end] # Shift right (1 col) + +# # Calculate using views to avoid extra allocations +# @. out_field[2:end-1, 2:end-1] = -4 * in_field[2:end-1, 2:end-1] + north + south + west + east + +# return out_field +# end + +# function lap_vectorized_optimized_simd(in_field::Matrix{Float64})::Matrix{Float64} +# nrows, ncols = size(in_field) +# out_field = zeros(Float64, nrows, ncols) +# out_field .= in_field + +# # Threading and SIMD applied to manual loop for potentially greater control and optimization +# @threads for j = 2:ncols-1 +# @simd for i = 2:nrows-1 +# out_field[i, j] = -4 * in_field[i, j] + +# in_field[i-1, j] + # North +# in_field[i+1, j] + # South +# in_field[i, j-1] + # West +# in_field[i, j+1] # East +# end +# end + +# return out_field +# end + +# function laplap(in_field::Matrix{Float64})::Matrix{Float64} +# return lap(lap(in_field)) +# end + +# function lap_program(in_field::Matrix{Float64}, out_field::Matrix{Float64})::Nothing +# nrows, ncols = size(in_field) +# for i in 2:(nrows - 1) +# for j in 2:(ncols - 1) +# # Perform the stencil operation +# out_field[i, j] = -4 * in_field[i, j] + +# in_field[i+1, j] + +# in_field[i-1, j] + +# in_field[i, j+1] + +# in_field[i, j-1] +# end +# end +# #The out_field have been changed, but the values in the border remain the same +# return nothing +# end + +# function laplap_program(in_field::Matrix{Float64}, out_field::Matrix{Float64})::Nothing +# temp_field = laplap(in_field) # Perform the laplap operation on the entire field +# out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] +# return nothing +# end + +# function pretty_print_matrix(mat::Matrix)::Nothing +# max_width = maximum(length(string(e)) for e in mat) + +# for row in eachrow(mat) +# formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") +# println(formatted_row) +# end +# return nothing +# end + +# function allocate_cartesian_case()::Matrix{Float64} +# return [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10] +# end + +# # Test Cases (on a manually defined 10x10 matrix (0..99)) +# function test_laplacian_operations() +# # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension +# in_field = allocate_cartesian_case() + +# # Print the original matrix +# println("Original in_field Matrix:") +# pretty_print_matrix(in_field) + +# # Apply the laplacian operation using the non-in-place version +# out_field = lap_vectorized_optimized(in_field) +# println("\nOutput Matrix after applying lap function:") +# pretty_print_matrix(out_field) + +# # Apply the laplacian operation using the in-place version +# out_field_program = allocate_cartesian_case() +# lap_program(in_field, out_field_program) +# println("\nOutput Matrix after applying lap_program function:") +# pretty_print_matrix(out_field_program) + +# # Apply the laplacian operation twice using the non-in-place version +# out_field_double = laplap(in_field) +# println("\nOutput Matrix after applying laplap function:") +# pretty_print_matrix(out_field_double) + +# # Apply the laplacian operation twice using the in-place version +# out_field_program = allocate_cartesian_case() +# laplap_program(in_field, out_field_program) +# println("\nOutput Matrix after applying laplap_program function:") +# pretty_print_matrix(out_field_program) +# end + +# Call the test function +#test_laplacian_operations() \ No newline at end of file From a2504c63ff81d79e297d29a4182779dacd4db10e Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 09:32:39 +0200 Subject: [PATCH 03/24] Fix offset_provider in the laplacian tests --- test/laplacian_test.jl | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl index 4a89044..e84c5b6 100644 --- a/test/laplacian_test.jl +++ b/test/laplacian_test.jl @@ -3,18 +3,23 @@ using GridTools include("mesh_definitions.jl") -const global IDim_ = Dimension{:IDim_, LOCAL} -const global JDim_ = Dimension{:JDim_, LOCAL} +const global IDim_ = Dimension{:IDim_, HORIZONTAL} +const global JDim_ = Dimension{:JDim_, HORIZONTAL} const global IDim = IDim_() const global JDim = JDim_() -Ioff = FieldOffset("Ioff", source=IDim, target=(IDim, Dimension{:I_, LOCAL}())) -Joff = FieldOffset("Joff", source=JDim, target=(JDim, Dimension{:J_, LOCAL}())) +const Ioff = FieldOffset("Ioff", source=IDim, target=IDim) +const Joff = FieldOffset("Joff", source=JDim, target=JDim) + +offset_provider = Dict{String, Dimension}( + "Ioff" => IDim, + "Joff" => JDim + ) # ---------------------------------------------------------------------------------------- -@field_operator function lap(in_field::Field{Tuple{IDim, JDim}, Float64}) - return -4.0 * in_field + +@field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return in_field + in_field(Ioff[1]) + in_field(Ioff[-1]) + in_field(Joff[1]) + @@ -25,21 +30,21 @@ field_data = collect(reshape(1.:16., 4, 4)) in_field = Field((IDim, JDim), field_data) out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) -lap(in_field, backend="embedded", out=out_field) +lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) @show out_field.data # ---------------------------------------------------------------------------------------- -@field_operator function laplap(in_field::Field{Tuple{IDim, JDim}, Float64}) - return lap(lap(in_field)) -end +# @field_operator function laplap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) +# return lap(lap(in_field)) +# end -field_data = collect(reshape(1.:16., 4, 4)) -in_field = Field((IDim, JDim), field_data) -out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) +# field_data = collect(reshape(1.:16., 4, 4)) +# in_field = Field((IDim, JDim), field_data) +# out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) -lap(in_field, backend="embedded", out=out_field) -@show out_field.data +# lap(in_field, backend="embedded", out=out_field) +# @show out_field.data # ---------------------------------------------------------------------------------------- From 22baf590257550a52fdb2106cc38aa940afe4314 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 14:03:47 +0200 Subject: [PATCH 04/24] Add partial implementation of the laplacian test. Incorrect outputs dimension --- test/laplacian_test.jl | 253 +++++++++++------------------------------ 1 file changed, 67 insertions(+), 186 deletions(-) diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl index e84c5b6..744c9f9 100644 --- a/test/laplacian_test.jl +++ b/test/laplacian_test.jl @@ -1,4 +1,5 @@ using Test +using Printf using GridTools include("mesh_definitions.jl") @@ -16,196 +17,76 @@ offset_provider = Dict{String, Dimension}( "Joff" => JDim ) -# ---------------------------------------------------------------------------------------- - -@field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - return in_field + - in_field(Ioff[1]) + - in_field(Ioff[-1]) + - in_field(Joff[1]) + - in_field(Joff[-1]) +function test_lap(field::Field) + field_data = field.data + in_field = Field((IDim, JDim), field_data) + out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + + @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return -4.0*in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) + end + + lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) + + println("\nOutput Matrix after applying lap() operator:") + pretty_print_matrix(out_field.data) end -field_data = collect(reshape(1.:16., 4, 4)) -in_field = Field((IDim, JDim), field_data) -out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) - -lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) -@show out_field.data - -# ---------------------------------------------------------------------------------------- - -# @field_operator function laplap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) -# return lap(lap(in_field)) -# end - -# field_data = collect(reshape(1.:16., 4, 4)) -# in_field = Field((IDim, JDim), field_data) -# out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) - -# lap(in_field, backend="embedded", out=out_field) -# @show out_field.data - -# ---------------------------------------------------------------------------------------- - -# @field_operator function lap(in_field::Field{Tuple{Dimension{:IDim, HORIZONTAL}, Dimension{:JDim, HORIZONTAL}}, Float64})::Field{Tuple{Dimension{:IDim, HORIZONTAL}, Dimension{:JDim, HORIZONTAL}}, Float64} -# nrows, ncols = size(in_field.data) -# out_data = zeros(Float64, nrows, ncols) -# out_data .= in_field.data # Copy inplace: to keep the initial values in the border - -# for i in 2:(nrows - 1) -# for j in 2:(ncols - 1) -# # Perform the stencil operation -# out_data[i, j] = -4 * in_field.data[i, j] + -# in_field.data[i+1, j] + -# in_field.data[i-1, j] + -# in_field.data[i, j+1] + -# in_field.data[i, j-1] -# end -# end - -# return Field(in_field.dims, out_data) -# end - -# @field_operator function lap(in_field::Matrix{Float64})::Matrix{Float64} -# nrows, ncols = size(in_field) -# out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros -# out_field .= in_field # Copy inplace: to keep the initial values in the border -# for i in 2:(nrows - 1) -# for j in 2:(ncols - 1) -# # Perform the stencil operation -# out_field[i, j] = -4 * in_field[i, j] + -# in_field[i+1, j] + -# in_field[i-1, j] + -# in_field[i, j+1] + -# in_field[i, j-1] -# end -# end - -# return out_field -# end - -# function lap_vectorized(in_field::Matrix{Float64})::Matrix{Float64} -# nrows, ncols = size(in_field) -# out_field = zeros(Float64, nrows, ncols) -# out_field .= in_field # Copy inplace: to keep the initial values in the border -# # Vectorized operations (with slicing) -# out_field[2:end-1, 2:end-1] = -4 * in_field[2:end-1, 2:end-1] + -# in_field[3:end, 2:end-1] + # i+1 -# in_field[1:end-2, 2:end-1] + # i-1 -# in_field[2:end-1, 3:end] + # j+1 -# in_field[2:end-1, 1:end-2] # j-1 - -# return out_field -# end - -# function lap_vectorized_optimized(in_field::Matrix{Float64})::Matrix{Float64} -# nrows, ncols = size(in_field) -# out_field = zeros(Float64, nrows, ncols) -# out_field .= in_field - -# # Prepare shifted arrays by slicing without creating new arrays -# north = @view in_field[1:end-2, 2:end-1] # Shift up (1 row) -# south = @view in_field[3:end, 2:end-1] # Shift down (1 row) -# west = @view in_field[2:end-1, 1:end-2] # Shift left (1 col) -# east = @view in_field[2:end-1, 3:end] # Shift right (1 col) - -# # Calculate using views to avoid extra allocations -# @. out_field[2:end-1, 2:end-1] = -4 * in_field[2:end-1, 2:end-1] + north + south + west + east - -# return out_field -# end - -# function lap_vectorized_optimized_simd(in_field::Matrix{Float64})::Matrix{Float64} -# nrows, ncols = size(in_field) -# out_field = zeros(Float64, nrows, ncols) -# out_field .= in_field - -# # Threading and SIMD applied to manual loop for potentially greater control and optimization -# @threads for j = 2:ncols-1 -# @simd for i = 2:nrows-1 -# out_field[i, j] = -4 * in_field[i, j] + -# in_field[i-1, j] + # North -# in_field[i+1, j] + # South -# in_field[i, j-1] + # West -# in_field[i, j+1] # East -# end -# end - -# return out_field -# end - -# function laplap(in_field::Matrix{Float64})::Matrix{Float64} -# return lap(lap(in_field)) -# end - -# function lap_program(in_field::Matrix{Float64}, out_field::Matrix{Float64})::Nothing -# nrows, ncols = size(in_field) -# for i in 2:(nrows - 1) -# for j in 2:(ncols - 1) -# # Perform the stencil operation -# out_field[i, j] = -4 * in_field[i, j] + -# in_field[i+1, j] + -# in_field[i-1, j] + -# in_field[i, j+1] + -# in_field[i, j-1] -# end -# end -# #The out_field have been changed, but the values in the border remain the same -# return nothing -# end - -# function laplap_program(in_field::Matrix{Float64}, out_field::Matrix{Float64})::Nothing -# temp_field = laplap(in_field) # Perform the laplap operation on the entire field -# out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] -# return nothing -# end - -# function pretty_print_matrix(mat::Matrix)::Nothing -# max_width = maximum(length(string(e)) for e in mat) - -# for row in eachrow(mat) -# formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") -# println(formatted_row) -# end -# return nothing -# end - -# function allocate_cartesian_case()::Matrix{Float64} -# return [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10] -# end - -# # Test Cases (on a manually defined 10x10 matrix (0..99)) -# function test_laplacian_operations() -# # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension -# in_field = allocate_cartesian_case() - -# # Print the original matrix -# println("Original in_field Matrix:") -# pretty_print_matrix(in_field) +function test_lap_lap(field::Field) + field_data = field.data + in_field = Field((IDim, JDim), field_data) + out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + + @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return -4.0*in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) + end -# # Apply the laplacian operation using the non-in-place version -# out_field = lap_vectorized_optimized(in_field) -# println("\nOutput Matrix after applying lap function:") -# pretty_print_matrix(out_field) + @field_operator function lap_lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + tmp = lap(in_field) + return lap(tmp) + end + + lap_lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) + + println("\nOutput Matrix after applying lap(lap()) operator:") + pretty_print_matrix(out_field.data) +end + +function pretty_print_matrix(mat::Matrix)::Nothing + max_width = maximum(length(string(e)) for e in mat) + + for row in eachrow(mat) + formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") + println(formatted_row) + end + return +end + +function allocate_cartesian_case()::Field + return Field((IDim, JDim), [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10]) +end + +# Test Cases (on a manually defined 10x10 matrix (0..99)) +function execute_laplacian_operations() + # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension + in_field = allocate_cartesian_case() -# # Apply the laplacian operation using the in-place version -# out_field_program = allocate_cartesian_case() -# lap_program(in_field, out_field_program) -# println("\nOutput Matrix after applying lap_program function:") -# pretty_print_matrix(out_field_program) - -# # Apply the laplacian operation twice using the non-in-place version -# out_field_double = laplap(in_field) -# println("\nOutput Matrix after applying laplap function:") -# pretty_print_matrix(out_field_double) + # Print the original matrix + println("Original in_field Matrix:") + pretty_print_matrix(in_field.data) -# # Apply the laplacian operation twice using the in-place version -# out_field_program = allocate_cartesian_case() -# laplap_program(in_field, out_field_program) -# println("\nOutput Matrix after applying laplap_program function:") -# pretty_print_matrix(out_field_program) -# end + test_lap(in_field) + + test_lap_lap(in_field) +end # Call the test function -#test_laplacian_operations() \ No newline at end of file +execute_laplacian_operations() From 48372099e2f238bb3b417c1d0b25346782713b60 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 14:44:49 +0200 Subject: [PATCH 05/24] Change the input data of laplacian tests to an easier cartesian domain --- test/laplacian_test.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl index 744c9f9..bb5c75a 100644 --- a/test/laplacian_test.jl +++ b/test/laplacian_test.jl @@ -20,7 +20,7 @@ offset_provider = Dict{String, Dimension}( function test_lap(field::Field) field_data = field.data in_field = Field((IDim, JDim), field_data) - out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) return -4.0*in_field + @@ -39,7 +39,7 @@ end function test_lap_lap(field::Field) field_data = field.data in_field = Field((IDim, JDim), field_data) - out_field = Field((IDim, JDim), zeros(Float64, 4, 4)) + out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) return -4.0*in_field + @@ -71,7 +71,8 @@ function pretty_print_matrix(mat::Matrix)::Nothing end function allocate_cartesian_case()::Field - return Field((IDim, JDim), [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10]) + return Field((IDim, JDim), ones(Float64, 8, 8)) + #return Field((IDim, JDim), [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10]) end # Test Cases (on a manually defined 10x10 matrix (0..99)) From 492fea680dd9f5637cdbe268b6fbd15728eb9273 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 14:59:17 +0200 Subject: [PATCH 06/24] Clean the inputs of laplacian tests --- test/laplacian_test.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl index bb5c75a..5c44c1f 100644 --- a/test/laplacian_test.jl +++ b/test/laplacian_test.jl @@ -17,9 +17,7 @@ offset_provider = Dict{String, Dimension}( "Joff" => JDim ) -function test_lap(field::Field) - field_data = field.data - in_field = Field((IDim, JDim), field_data) +function test_lap(in_field::Field) out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) @@ -36,9 +34,7 @@ function test_lap(field::Field) pretty_print_matrix(out_field.data) end -function test_lap_lap(field::Field) - field_data = field.data - in_field = Field((IDim, JDim), field_data) +function test_lap_lap(in_field::Field) out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) From ae3ec8f66b523f82498088de96b1d3df77bb89b9 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 15:05:50 +0200 Subject: [PATCH 07/24] Clean comments --- test/laplacian_test.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl index 5c44c1f..4d61f20 100644 --- a/test/laplacian_test.jl +++ b/test/laplacian_test.jl @@ -67,13 +67,14 @@ function pretty_print_matrix(mat::Matrix)::Nothing end function allocate_cartesian_case()::Field + # Create a matrix filled with a constant value (1 in this case) return Field((IDim, JDim), ones(Float64, 8, 8)) + + # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension #return Field((IDim, JDim), [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10]) end -# Test Cases (on a manually defined 10x10 matrix (0..99)) function execute_laplacian_operations() - # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension in_field = allocate_cartesian_case() # Print the original matrix From 5b843146fa0069ccd04e18ef770bc5abc2f6de17 Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Wed, 17 Jul 2024 16:26:55 +0200 Subject: [PATCH 08/24] Introduce canonicalization of arithmetic operations (fixes wrong results with GT4Py backend) --- src/gt2py/gt2py.jl | 3 ++- src/gt2py/jast_to_foast.jl | 1 + src/gt2py/preprocessing.jl | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/gt2py/gt2py.jl b/src/gt2py/gt2py.jl index 9ed12fd..9fc68c2 100644 --- a/src/gt2py/gt2py.jl +++ b/src/gt2py/gt2py.jl @@ -218,7 +218,8 @@ end function preprocess_definiton(expr::Expr, closure_vars::Dict) sat = single_assign_target_pass(expr) ucc = unchain_compairs_pass(sat) - ssa = single_static_assign_pass(ucc) + nop = canonicalize_arithmetic_ops(ucc) + ssa = single_static_assign_pass(nop) py_closure_vars = translate_closure_vars(closure_vars) annotations = get_annotation(ssa, py_closure_vars) return (ssa, py_closure_vars, annotations) diff --git a/src/gt2py/jast_to_foast.jl b/src/gt2py/jast_to_foast.jl index ec75203..c843059 100644 --- a/src/gt2py/jast_to_foast.jl +++ b/src/gt2py/jast_to_foast.jl @@ -266,6 +266,7 @@ end function visit_(sym::Val{:call}, args::Array, outer_loc) if args[1] in bin_op + @assert length(args)==3 "Expected a binary operation. AST must be canonicalized using `canonicalize_arithmetic_ops` first." return foast.BinOp( op = visit(args[1]), left = visit(args[2], outer_loc), diff --git a/src/gt2py/preprocessing.jl b/src/gt2py/preprocessing.jl index 97ca6cc..49298af 100644 --- a/src/gt2py/preprocessing.jl +++ b/src/gt2py/preprocessing.jl @@ -28,6 +28,21 @@ function unchain_compairs_pass(expr::Expr)::Expr end end +""" +Transform all arithmetic operations with more than two arguments into binary operations. +""" +function canonicalize_arithmetic_ops(expr) + if expr isa Expr + expr = Expr(expr.head, map(canonicalize_nary_ops, expr.args)...) # visit all children + + if expr.head == :call && expr.args[1] in bin_op && length(expr.args) > 3 + op, a, b, tail... = expr.args + return canonicalize_nary_ops(Expr(:call, op, Expr(:call, op, a, b), tail...)) + end + end + return expr +end + function recursive_unchain(args::Array)::Expr if length(args) == 3 return Expr(:call, args[2], args[1], args[3]) From 9e33a2ac3f93ae183c3e9ce6071b1b6b86815d4b Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Wed, 17 Jul 2024 16:28:28 +0200 Subject: [PATCH 09/24] Fix typo --- src/gt2py/preprocessing.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gt2py/preprocessing.jl b/src/gt2py/preprocessing.jl index 49298af..d87f640 100644 --- a/src/gt2py/preprocessing.jl +++ b/src/gt2py/preprocessing.jl @@ -33,11 +33,11 @@ Transform all arithmetic operations with more than two arguments into binary ope """ function canonicalize_arithmetic_ops(expr) if expr isa Expr - expr = Expr(expr.head, map(canonicalize_nary_ops, expr.args)...) # visit all children + expr = Expr(expr.head, map(canonicalize_arithmetic_ops, expr.args)...) # visit all children if expr.head == :call && expr.args[1] in bin_op && length(expr.args) > 3 op, a, b, tail... = expr.args - return canonicalize_nary_ops(Expr(:call, op, Expr(:call, op, a, b), tail...)) + return canonicalize_arithmetic_ops(Expr(:call, op, Expr(:call, op, a, b), tail...)) end end return expr From 6d34e15499f48dd5a9f8555ee330459c01f3d107 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 18:22:38 +0200 Subject: [PATCH 10/24] Add laplacian tests --- test/gt2py_fo_exec.jl | 127 +++++++++++++++++++++++++++++++++++++++ test/mesh_definitions.jl | 15 ++++- 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index 16352de..c78d0fe 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -1,4 +1,5 @@ using Test +using Printf using GridTools using MacroTools @@ -78,6 +79,43 @@ function testwrapper(setupfunc::Union{Function,Nothing}, testfunc::Function, arg end end +function pretty_print_matrix(mat::Matrix)::Nothing + max_width = maximum(length(string(e)) for e in mat) + + for row in eachrow(mat) + formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") + println(formatted_row) + end + return +end + +function lap_ground_truth(in_field::Matrix{Float64})::Matrix{Float64} + nrows, ncols = size(in_field) + out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros + out_field .= in_field # Copy inplace: to keep the initial values in the border + for i in 2:(nrows - 1) + for j in 2:(ncols - 1) + # Perform the stencil operation + out_field[i, j] = -4 * in_field[i, j] + + in_field[i+1, j] + + in_field[i-1, j] + + in_field[i, j+1] + + in_field[i, j-1] + end + end + + return out_field +end + +function lap_lap_ground_truth(in_field::Matrix{Float64}) + x_length, y_length = size(in_field) + out_field = zeros(Float64, x_length, y_length) + out_field .= in_field + temp_field = lap_ground_truth(lap_ground_truth(in_field)) # Perform the laplap operation on the entire field + out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] # Restrict the copy to avoid the copy in the unchanged border + return out_field +end + # Setup ------------------------------------------------------------------------------------------------------ function setup_simple_connectivity()::Dict{String,Connectivity} @@ -117,6 +155,22 @@ function setup_simple_connectivity()::Dict{String,Connectivity} return offset_provider end +function setup_constant_cartesian_domain() + offset_provider = Dict{String, Dimension}( + "Ioff" => IDim, + "Joff" => JDim + ) + return offset_provider +end + +function constant_cartesian_domain()::Field + return Field((IDim, JDim), ones(Float64, 8, 8)) +end + +function simple_cartesian_domain()::Field + return Field((IDim, JDim), [Float64((i-1) * 5 + j-1) for i in 1:5, j in 1:5]) +end + # Test Definitions ------------------------------------------------------------------------------------------- function test_fo_addition(backend::String) @@ -427,6 +481,65 @@ function test_nested_fo(backend::String) @test out.data == expected_output end +function test_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) + in_field = domain_generator() + x_length, y_length = size(in_field.data) + out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) + expected_out = lap_ground_truth(in_field.data) + + @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return -4.0*in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) + end + + lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) + + if debug + println("\nOutput Matrix after applying lap() operator in the field operator:") + pretty_print_matrix(out_field.data) + + println("\nExpected ground truth of laplacian computation without field operator:") + pretty_print_matrix(expected_out) + end + + @test out_field.data[2:end-1, 2:end-1] == expected_out[2:end-1, 2:end-1] +end + +function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) + in_field = domain_generator() + x_length, y_length = size(in_field.data) + out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) + expected_out = lap_lap_ground_truth(in_field.data) + + @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return -4.0*in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) + end + + @field_operator function lap_lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + tmp = lap(in_field) + return lap(tmp) + end + + lap_lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) + + if debug + println("\nOutput Matrix after applying lap(lap()) operator:") + pretty_print_matrix(out_field.data) + + println("\nExpected ground truth of lap(lap()) computation without field operator:") + pretty_print_matrix(expected_out) + end + + @test out_field.data[3:end-2, 3:end-2] == expected_out[3:end-2, 3:end-2] +end + # Test Executions -------------------------------------------------------------------------------------------- function test_gt4py_fo_exec() @@ -491,6 +604,20 @@ function test_gt4py_fo_exec() testwrapper(nothing, test_nested_fo, "embedded") testwrapper(nothing, test_nested_fo, "py") + + # TODO: add support for the embedded backend when the dims is changing due to cartesian offsets + # (Note: check the debug flag for pretty printing the outputs) + # testwrapper(setup_constant_cartesian_domain, test_lap, "embedded", constant_cartesian_domain) + testwrapper(setup_constant_cartesian_domain, test_lap, "py", constant_cartesian_domain) + + # testwrapper(setup_constant_cartesian_domain, test_lap, "embedded", simple_cartesian_domain) + testwrapper(setup_constant_cartesian_domain, test_lap, "py", simple_cartesian_domain) + + # testwrapper(setup_constant_cartesian_domain, test_lap_lap, "embedded", constant_cartesian_domain) + testwrapper(setup_constant_cartesian_domain, test_lap_lap, "py", constant_cartesian_domain) + + # testwrapper(setup_constant_cartesian_domain, test_lap_lap, "embedded", simple_cartesian_domain) + testwrapper(setup_constant_cartesian_domain, test_lap_lap, "py", simple_cartesian_domain) end @testset "Testset GT2Py fo exec" test_gt4py_fo_exec() diff --git a/test/mesh_definitions.jl b/test/mesh_definitions.jl index 51fdaa4..9385368 100644 --- a/test/mesh_definitions.jl +++ b/test/mesh_definitions.jl @@ -1,3 +1,6 @@ + +# Unstructured ----------------------------------------------------------------------------------------------- + const global Cell_ = Dimension{:Cell_, HORIZONTAL} const global K_ = Dimension{:K_, HORIZONTAL} const global Edge_ = Dimension{:Edge_, HORIZONTAL} @@ -22,4 +25,14 @@ const global E2V = FieldOffset("E2V", source=Vertex, target=(Edge, E2VDim)) const global V2E = FieldOffset("V2E", source=Edge, target=(Vertex, V2EDim)) const global E2C = FieldOffset("E2C", source=Cell, target=(Edge, E2CDim)) const global C2E = FieldOffset("C2E", source=Edge, target=(Cell, C2EDim)) -const global Koff = FieldOffset("Koff", source=K, target=K) \ No newline at end of file +const global Koff = FieldOffset("Koff", source=K, target=K) + +# Cartesian -------------------------------------------------------------------------------------------------- + +const global IDim_ = Dimension{:IDim_, HORIZONTAL} +const global JDim_ = Dimension{:JDim_, HORIZONTAL} +const global IDim = IDim_() +const global JDim = JDim_() + +const global Ioff = FieldOffset("Ioff", source=IDim, target=IDim) +const global Joff = FieldOffset("Joff", source=JDim, target=JDim) \ No newline at end of file From 056df924709927fdef1a5eddcc9a4305c51b98dc Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 18:23:07 +0200 Subject: [PATCH 11/24] Remove previous laplacian tests in separate file --- test/laplacian_test.jl | 90 ------------------------------------------ 1 file changed, 90 deletions(-) delete mode 100644 test/laplacian_test.jl diff --git a/test/laplacian_test.jl b/test/laplacian_test.jl deleted file mode 100644 index 4d61f20..0000000 --- a/test/laplacian_test.jl +++ /dev/null @@ -1,90 +0,0 @@ -using Test -using Printf -using GridTools - -include("mesh_definitions.jl") - -const global IDim_ = Dimension{:IDim_, HORIZONTAL} -const global JDim_ = Dimension{:JDim_, HORIZONTAL} -const global IDim = IDim_() -const global JDim = JDim_() - -const Ioff = FieldOffset("Ioff", source=IDim, target=IDim) -const Joff = FieldOffset("Joff", source=JDim, target=JDim) - -offset_provider = Dict{String, Dimension}( - "Ioff" => IDim, - "Joff" => JDim - ) - -function test_lap(in_field::Field) - out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) - - @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - return -4.0*in_field + - in_field(Ioff[1]) + - in_field(Ioff[-1]) + - in_field(Joff[1]) + - in_field(Joff[-1]) - end - - lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) - - println("\nOutput Matrix after applying lap() operator:") - pretty_print_matrix(out_field.data) -end - -function test_lap_lap(in_field::Field) - out_field = Field((IDim, JDim), zeros(Float64, 8, 8)) - - @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - return -4.0*in_field + - in_field(Ioff[1]) + - in_field(Ioff[-1]) + - in_field(Joff[1]) + - in_field(Joff[-1]) - end - - @field_operator function lap_lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - tmp = lap(in_field) - return lap(tmp) - end - - lap_lap(in_field, offset_provider=offset_provider, backend="py", out=out_field) - - println("\nOutput Matrix after applying lap(lap()) operator:") - pretty_print_matrix(out_field.data) -end - -function pretty_print_matrix(mat::Matrix)::Nothing - max_width = maximum(length(string(e)) for e in mat) - - for row in eachrow(mat) - formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") - println(formatted_row) - end - return -end - -function allocate_cartesian_case()::Field - # Create a matrix filled with a constant value (1 in this case) - return Field((IDim, JDim), ones(Float64, 8, 8)) - - # Create a 10x10 matrix populated with values from 0 to 99 using an array comprehension - #return Field((IDim, JDim), [Float64((i-1) * 10 + j-1) for i in 1:10, j in 1:10]) -end - -function execute_laplacian_operations() - in_field = allocate_cartesian_case() - - # Print the original matrix - println("Original in_field Matrix:") - pretty_print_matrix(in_field.data) - - test_lap(in_field) - - test_lap_lap(in_field) -end - -# Call the test function -execute_laplacian_operations() From 66f323b3771f1f2f23b6eec63445e3a76d95727b Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 18:35:54 +0200 Subject: [PATCH 12/24] Clean the output generation in the max and min cases to homogenize it with the laplacian case --- test/gt2py_fo_exec.jl | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index c78d0fe..ddb48ce 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -163,6 +163,14 @@ function setup_constant_cartesian_domain() return offset_provider end +function field_increasing_values() + return Field(Cell, collect(1.0:15.0)) +end + +function field_decreasing_values() + return Field(Cell, reverse(collect(1.0:15.0))) +end + function constant_cartesian_domain()::Field return Field((IDim, JDim), ones(Float64, 8, 8)) end @@ -311,8 +319,8 @@ function compute_expected_output_comparing_values(offset_provider::Dict{String, return expected_output end -function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::String, a::Field) - a = Field(Cell, collect(1.0:15.0)) +function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::String, generate_field::Function) + a::Field = generate_field() out = Field(Edge, zeros(Float64, 12)) # Compute the ground truth manually computing the maximum of the value of each neighbor @@ -326,8 +334,8 @@ function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::S @test out == expected_output end -function test_fo_min_over(offset_provider::Dict{String,Connectivity}, backend::String, a::Field) - a = Field(Cell, collect(1.0:15.0)) +function test_fo_min_over(offset_provider::Dict{String,Connectivity}, backend::String, generate_field::Function) + a::Field = generate_field() out = Field(Edge, zeros(Float64, 12)) # Compute the ground truth manually computing the minimum of the value of each neighbor @@ -564,21 +572,17 @@ function test_gt4py_fo_exec() testwrapper(setup_simple_connectivity, test_fo_neighbor_sum, "embedded") testwrapper(setup_simple_connectivity, test_fo_neighbor_sum, "py") - # Test the comparison of values in the Fields - field_values_increasing = Field(Cell, collect(1.0:15.0)) - field_values_decreasing = Field(Cell, reverse(collect(1.0:15.0))) - - testwrapper(setup_simple_connectivity, test_fo_max_over, "embedded", field_values_increasing) - testwrapper(setup_simple_connectivity, test_fo_max_over, "py", field_values_increasing) + testwrapper(setup_simple_connectivity, test_fo_max_over, "embedded", field_increasing_values) + testwrapper(setup_simple_connectivity, test_fo_max_over, "py", field_increasing_values) - testwrapper(setup_simple_connectivity, test_fo_max_over, "embedded", field_values_decreasing) - testwrapper(setup_simple_connectivity, test_fo_max_over, "py", field_values_decreasing) + testwrapper(setup_simple_connectivity, test_fo_max_over, "embedded", field_decreasing_values) + testwrapper(setup_simple_connectivity, test_fo_max_over, "py", field_decreasing_values) - testwrapper(setup_simple_connectivity, test_fo_min_over, "embedded", field_values_increasing) - testwrapper(setup_simple_connectivity, test_fo_min_over, "py", field_values_increasing) + testwrapper(setup_simple_connectivity, test_fo_min_over, "embedded", field_increasing_values) + testwrapper(setup_simple_connectivity, test_fo_min_over, "py", field_increasing_values) - testwrapper(setup_simple_connectivity, test_fo_min_over, "embedded", field_values_decreasing) - testwrapper(setup_simple_connectivity, test_fo_min_over, "py", field_values_decreasing) + testwrapper(setup_simple_connectivity, test_fo_min_over, "embedded", field_decreasing_values) + testwrapper(setup_simple_connectivity, test_fo_min_over, "py", field_decreasing_values) testwrapper(nothing, test_fo_simple_broadcast, "embedded") testwrapper(nothing, test_fo_simple_broadcast, "py") From 1cfdb9cea85655c98bceeb60444a13b6128be3f7 Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Wed, 17 Jul 2024 18:38:29 +0200 Subject: [PATCH 13/24] Add a todo for the test of the border values when the out_offset will be introduced --- test/gt2py_fo_exec.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index ddb48ce..e0c950c 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -514,6 +514,7 @@ function test_lap(offset_provider::Dict{String, Dimension}, backend::String, dom end @test out_field.data[2:end-1, 2:end-1] == expected_out[2:end-1, 2:end-1] + # TODO: add in the future the test for the border values end function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) @@ -546,6 +547,7 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, end @test out_field.data[3:end-2, 3:end-2] == expected_out[3:end-2, 3:end-2] + # TODO: add in the future the test for the border values end # Test Executions -------------------------------------------------------------------------------------------- From b9018ac6d2652dd6324ac726e3b3a0b0d1dafe9e Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Thu, 18 Jul 2024 09:47:08 +0200 Subject: [PATCH 14/24] Remove the Printf dependency and improve the print debug of the laplacian --- test/gt2py_fo_exec.jl | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index e0c950c..70f1d5d 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -1,5 +1,4 @@ using Test -using Printf using GridTools using MacroTools @@ -81,14 +80,21 @@ end function pretty_print_matrix(mat::Matrix)::Nothing max_width = maximum(length(string(e)) for e in mat) + reqpadding(str::String, len::Int)::String = str * " " ^ (len - length(str)) for row in eachrow(mat) - formatted_row = join([@sprintf("%*s", max_width, string(x)) for x in row], " ") + formatted_row = join([reqpadding(string(x), max_width) for x in row], " ") println(formatted_row) end return end +function print_debug_info(title::String, mat::Matrix)::Nothing + println("----------------------------------------------------------------------------") + println(title) + pretty_print_matrix(mat) +end + function lap_ground_truth(in_field::Matrix{Float64})::Matrix{Float64} nrows, ncols = size(in_field) out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros @@ -506,11 +512,10 @@ function test_lap(offset_provider::Dict{String, Dimension}, backend::String, dom lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) if debug - println("\nOutput Matrix after applying lap() operator in the field operator:") - pretty_print_matrix(out_field.data) - - println("\nExpected ground truth of laplacian computation without field operator:") - pretty_print_matrix(expected_out) + print_debug_info("Input Matrix before applying the laplacian:", in_field.data) + print_debug_info("Output Matrix after applying lap() operator in the field operator:", out_field.data) + print_debug_info("Expected ground truth of laplacian computation without field operator:", expected_out) + print("\n\n") end @test out_field.data[2:end-1, 2:end-1] == expected_out[2:end-1, 2:end-1] @@ -539,11 +544,10 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, lap_lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) if debug - println("\nOutput Matrix after applying lap(lap()) operator:") - pretty_print_matrix(out_field.data) - - println("\nExpected ground truth of lap(lap()) computation without field operator:") - pretty_print_matrix(expected_out) + print_debug_info("Input Matrix before applying the laplacian of laplacian (lap_lap):", in_field.data) + print_debug_info("Output Matrix after applying lap(lap()) operator in the field operator:", out_field.data) + print_debug_info("Expected ground truth of lap(lap()) computation without field operator:", expected_out) + print("\n\n") end @test out_field.data[3:end-2, 3:end-2] == expected_out[3:end-2, 3:end-2] From ffb8b2cfe345f03fa94b1a57a48bc6b68e57fa6c Mon Sep 17 00:00:00 2001 From: LorenzoVarese Date: Thu, 18 Jul 2024 09:50:17 +0200 Subject: [PATCH 15/24] Fix naming cartesian offset provider --- test/gt2py_fo_exec.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index 70f1d5d..49a8c5b 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -161,7 +161,7 @@ function setup_simple_connectivity()::Dict{String,Connectivity} return offset_provider end -function setup_constant_cartesian_domain() +function setup_cartesian_offset_provider() offset_provider = Dict{String, Dimension}( "Ioff" => IDim, "Joff" => JDim @@ -617,17 +617,17 @@ function test_gt4py_fo_exec() # TODO: add support for the embedded backend when the dims is changing due to cartesian offsets # (Note: check the debug flag for pretty printing the outputs) - # testwrapper(setup_constant_cartesian_domain, test_lap, "embedded", constant_cartesian_domain) - testwrapper(setup_constant_cartesian_domain, test_lap, "py", constant_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", constant_cartesian_domain) + testwrapper(setup_cartesian_offset_provider, test_lap, "py", constant_cartesian_domain) - # testwrapper(setup_constant_cartesian_domain, test_lap, "embedded", simple_cartesian_domain) - testwrapper(setup_constant_cartesian_domain, test_lap, "py", simple_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", simple_cartesian_domain) + testwrapper(setup_cartesian_offset_provider, test_lap, "py", simple_cartesian_domain) - # testwrapper(setup_constant_cartesian_domain, test_lap_lap, "embedded", constant_cartesian_domain) - testwrapper(setup_constant_cartesian_domain, test_lap_lap, "py", constant_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", constant_cartesian_domain) + testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", constant_cartesian_domain) - # testwrapper(setup_constant_cartesian_domain, test_lap_lap, "embedded", simple_cartesian_domain) - testwrapper(setup_constant_cartesian_domain, test_lap_lap, "py", simple_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", simple_cartesian_domain) + testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", simple_cartesian_domain) end @testset "Testset GT2Py fo exec" test_gt4py_fo_exec() From 814e14eb6b41bc1abb56d02d7ebfd7764f5df624 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:14:48 +0200 Subject: [PATCH 16/24] Ignore Manifest.toml (autogenerated) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c29d09f..92d93be 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ deps/src/ # Build artifacts for creating documentation generated by the Documenter package docs/build/ .DS_Store + +Manifest.toml From 20f95e05d9a938b190a3cd4ad35c5c08472ddbe7 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:17:00 +0200 Subject: [PATCH 17/24] Add simple suggestions to laplacian tests (field operator) --- test/gt2py_fo_exec.jl | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index 49a8c5b..5514fc4 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -78,24 +78,13 @@ function testwrapper(setupfunc::Union{Function,Nothing}, testfunc::Function, arg end end -function pretty_print_matrix(mat::Matrix)::Nothing - max_width = maximum(length(string(e)) for e in mat) - reqpadding(str::String, len::Int)::String = str * " " ^ (len - length(str)) - - for row in eachrow(mat) - formatted_row = join([reqpadding(string(x), max_width) for x in row], " ") - println(formatted_row) - end - return -end - function print_debug_info(title::String, mat::Matrix)::Nothing println("----------------------------------------------------------------------------") println(title) - pretty_print_matrix(mat) + display(mat) end -function lap_ground_truth(in_field::Matrix{Float64})::Matrix{Float64} +function lap_reference(in_field::Matrix{Float64})::Matrix{Float64} nrows, ncols = size(in_field) out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros out_field .= in_field # Copy inplace: to keep the initial values in the border @@ -113,12 +102,12 @@ function lap_ground_truth(in_field::Matrix{Float64})::Matrix{Float64} return out_field end -function lap_lap_ground_truth(in_field::Matrix{Float64}) +function lap_lap_reference(in_field::Matrix{Float64}) x_length, y_length = size(in_field) out_field = zeros(Float64, x_length, y_length) out_field .= in_field - temp_field = lap_ground_truth(lap_ground_truth(in_field)) # Perform the laplap operation on the entire field - out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] # Restrict the copy to avoid the copy in the unchanged border + temp_field = lap_reference(lap_reference(in_field)) # Perform the laplap operation on the entire field + #out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] # Restrict the copy to avoid the copy in the unchanged border return out_field end @@ -174,18 +163,18 @@ function field_increasing_values() end function field_decreasing_values() - return Field(Cell, reverse(collect(1.0:15.0))) + return Field(Cell, collect(15.0:-1:1.0)) end -function constant_cartesian_domain()::Field +function constant_cartesian_field()::Field return Field((IDim, JDim), ones(Float64, 8, 8)) end -function simple_cartesian_domain()::Field +function simple_cartesian_field()::Field return Field((IDim, JDim), [Float64((i-1) * 5 + j-1) for i in 1:5, j in 1:5]) end -# Test Definitions ------------------------------------------------------------------------------------------- + return Field(Cell, 15.0:-1:1.0) function test_fo_addition(backend::String) a = Field(Cell, collect(1.0:15.0)) @@ -499,7 +488,7 @@ function test_lap(offset_provider::Dict{String, Dimension}, backend::String, dom in_field = domain_generator() x_length, y_length = size(in_field.data) out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) - expected_out = lap_ground_truth(in_field.data) + expected_out = lap_reference(in_field.data) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) return -4.0*in_field + @@ -526,7 +515,7 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, in_field = domain_generator() x_length, y_length = size(in_field.data) out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) - expected_out = lap_lap_ground_truth(in_field.data) + expected_out = lap_lap_reference(in_field.data) @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) return -4.0*in_field + @@ -537,8 +526,7 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, end @field_operator function lap_lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - tmp = lap(in_field) - return lap(tmp) + return lap(lap(in_field)) end lap_lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) From 2a892e3c99da2b7b4dc7c6928b49f6e1a8681a25 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:33:14 +0200 Subject: [PATCH 18/24] Fix tests and change the copy of border values in the laplacian --- test/gt2py_fo_exec.jl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index 5514fc4..c81d5fe 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -87,7 +87,7 @@ end function lap_reference(in_field::Matrix{Float64})::Matrix{Float64} nrows, ncols = size(in_field) out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros - out_field .= in_field # Copy inplace: to keep the initial values in the border + out_field[2:end-1, 2:end-1] .= in_field[2:end-1, 2:end-1] # Border values are not computed with the stencil operation for i in 2:(nrows - 1) for j in 2:(ncols - 1) # Perform the stencil operation @@ -105,9 +105,8 @@ end function lap_lap_reference(in_field::Matrix{Float64}) x_length, y_length = size(in_field) out_field = zeros(Float64, x_length, y_length) - out_field .= in_field - temp_field = lap_reference(lap_reference(in_field)) # Perform the laplap operation on the entire field - #out_field[3:end-2, 3:end-2] .= temp_field[3:end-2, 3:end-2] # Restrict the copy to avoid the copy in the unchanged border + out_field[3:end-2, 3:end-2] .= in_field[3:end-2, 3:end-2] # Border values are not computed with the stencil operation + out_field = lap_reference(lap_reference(in_field)) # Perform the laplap operation on the entire field return out_field end @@ -605,17 +604,17 @@ function test_gt4py_fo_exec() # TODO: add support for the embedded backend when the dims is changing due to cartesian offsets # (Note: check the debug flag for pretty printing the outputs) - # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", constant_cartesian_domain) - testwrapper(setup_cartesian_offset_provider, test_lap, "py", constant_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", constant_cartesian_field) + testwrapper(setup_cartesian_offset_provider, test_lap, "py", constant_cartesian_field) - # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", simple_cartesian_domain) - testwrapper(setup_cartesian_offset_provider, test_lap, "py", simple_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap, "embedded", simple_cartesian_field) + testwrapper(setup_cartesian_offset_provider, test_lap, "py", simple_cartesian_field) - # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", constant_cartesian_domain) - testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", constant_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", constant_cartesian_field) + testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", constant_cartesian_field) - # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", simple_cartesian_domain) - testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", simple_cartesian_domain) + # testwrapper(setup_cartesian_offset_provider, test_lap_lap, "embedded", simple_cartesian_field) + testwrapper(setup_cartesian_offset_provider, test_lap_lap, "py", simple_cartesian_field) end @testset "Testset GT2Py fo exec" test_gt4py_fo_exec() From 74f0ffec450bed60a0ee81a6147d6a0a5d373e62 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Mon, 22 Jul 2024 14:30:37 +0200 Subject: [PATCH 19/24] Improve copy of the border values in the reference computation of laplacian --- test/gt2py_fo_exec.jl | 73 ++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index c81d5fe..d7dc21e 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -84,10 +84,30 @@ function print_debug_info(title::String, mat::Matrix)::Nothing display(mat) end +function copy_borders!(dest_matrix::Matrix{Float64}, src_matrix::Matrix{Float64}, border_width::Int) + nrows, ncols = size(src_matrix) + + # Ensure both matrices have the same size and the border width is feasible + @assert size(dest_matrix) == size(src_matrix) "Both matrices must be of the same size" + @assert border_width > 0 && border_width <= nrows ÷ 2 && border_width <= ncols ÷ 2 "Border width must be positive and less than half the smallest dimension" + + # Top and bottom border rows + dest_matrix[1:border_width, :] .= src_matrix[1:border_width, :] + dest_matrix[(nrows-border_width+1):end, :] .= src_matrix[(nrows-border_width+1):end, :] + + # Left and right border columns + dest_matrix[:, 1:border_width] .= src_matrix[:, 1:border_width] + dest_matrix[:, (ncols-border_width+1):end] .= src_matrix[:, (ncols-border_width+1):end] + + return dest_matrix +end + function lap_reference(in_field::Matrix{Float64})::Matrix{Float64} nrows, ncols = size(in_field) + @assert nrows >= 3 && ncols >= 3 "Input matrix must be at least 3x3 to compute stencil operations." + out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros - out_field[2:end-1, 2:end-1] .= in_field[2:end-1, 2:end-1] # Border values are not computed with the stencil operation + for i in 2:(nrows - 1) for j in 2:(ncols - 1) # Perform the stencil operation @@ -99,14 +119,19 @@ function lap_reference(in_field::Matrix{Float64})::Matrix{Float64} end end + copy_borders!(out_field, in_field, 1) # Border values are not computed with the stencil operation return out_field end function lap_lap_reference(in_field::Matrix{Float64}) x_length, y_length = size(in_field) + @assert x_length >= 5 && y_length >= 5 "Input matrix must be at least 5x5 to compute double laplacian." + out_field = zeros(Float64, x_length, y_length) - out_field[3:end-2, 3:end-2] .= in_field[3:end-2, 3:end-2] # Border values are not computed with the stencil operation - out_field = lap_reference(lap_reference(in_field)) # Perform the laplap operation on the entire field + + out_field = lap_reference(lap_reference(in_field)) + + copy_borders!(out_field, in_field, 2) # Border values are not computed with the stencil operation return out_field end @@ -280,7 +305,7 @@ function test_fo_neighbor_sum(offset_provider::Dict{String,Connectivity}, backen return sum(idx -> idx != -1 ? field_data[idx] : 0, v) end - # Compute the ground truth manually computing the sum on that dimension + # Compute the reference manually computing the sum on that dimension edge_to_cell_data = offset_provider["E2C"].data expected_output = Float64[] for i in axes(edge_to_cell_data, 1) @@ -317,7 +342,7 @@ function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::S a::Field = generate_field() out = Field(Edge, zeros(Float64, 12)) - # Compute the ground truth manually computing the maximum of the value of each neighbor + # Compute the reference manually computing the maximum of the value of each neighbor expected_output = expected_output = compute_expected_output_comparing_values(offset_provider, a, maximum) @field_operator function fo_max_over(a::Field{Tuple{Cell_},Float64})::Field{Tuple{Edge_},Float64} @@ -332,7 +357,7 @@ function test_fo_min_over(offset_provider::Dict{String,Connectivity}, backend::S a::Field = generate_field() out = Field(Edge, zeros(Float64, 12)) - # Compute the ground truth manually computing the minimum of the value of each neighbor + # Compute the reference manually computing the minimum of the value of each neighbor expected_output = compute_expected_output_comparing_values(offset_provider, a, minimum) @field_operator function fo_min_over(a::Field{Tuple{Cell_},Float64})::Field{Tuple{Edge_},Float64} @@ -464,7 +489,7 @@ function test_nested_fo(backend::String) b = Field(Cell, ones(15)) out = Field(Cell, zeros(15)) - # Compute the Ground Truth + # Compute the Reference intermediate_result = a.data .+ b.data expected_output = intermediate_result .+ a.data @@ -479,35 +504,39 @@ function test_nested_fo(backend::String) nested_fo(a, b, backend=backend, out=out) - # Test against the Ground Truth + # Test against the reference @test out.data == expected_output end +# Define the Laplacian field operation in the global scope for accessibility across multiple tests. +@field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) + return -4.0*in_field + + in_field(Ioff[1]) + + in_field(Ioff[-1]) + + in_field(Joff[1]) + + in_field(Joff[-1]) +end + function test_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) in_field = domain_generator() x_length, y_length = size(in_field.data) out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) expected_out = lap_reference(in_field.data) - - @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - return -4.0*in_field + - in_field(Ioff[1]) + - in_field(Ioff[-1]) + - in_field(Joff[1]) + - in_field(Joff[-1]) - end lap(in_field, offset_provider=offset_provider, backend=backend, out=out_field) if debug print_debug_info("Input Matrix before applying the laplacian:", in_field.data) print_debug_info("Output Matrix after applying lap() operator in the field operator:", out_field.data) - print_debug_info("Expected ground truth of laplacian computation without field operator:", expected_out) + print_debug_info("Expected reference of laplacian computation without field operator:", expected_out) print("\n\n") end @test out_field.data[2:end-1, 2:end-1] == expected_out[2:end-1, 2:end-1] + # TODO: add in the future the test for the border values + # @test out_field.data[1, :] == expected_out[1, :] && out_field.data[end, :] == expected_out[end, :] \ + # out_field.data[:, 1] == expected_out[:, 1] && out_field.data[:, end] == expected_out[:, end] end function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) @@ -516,14 +545,6 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) expected_out = lap_lap_reference(in_field.data) - @field_operator function lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) - return -4.0*in_field + - in_field(Ioff[1]) + - in_field(Ioff[-1]) + - in_field(Joff[1]) + - in_field(Joff[-1]) - end - @field_operator function lap_lap(in_field::Field{Tuple{IDim_, JDim_}, Float64}) return lap(lap(in_field)) end @@ -533,7 +554,7 @@ function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, if debug print_debug_info("Input Matrix before applying the laplacian of laplacian (lap_lap):", in_field.data) print_debug_info("Output Matrix after applying lap(lap()) operator in the field operator:", out_field.data) - print_debug_info("Expected ground truth of lap(lap()) computation without field operator:", expected_out) + print_debug_info("Expected reference of lap(lap()) computation without field operator:", expected_out) print("\n\n") end From 761e4342f844ce755e5be4a937b835fd4347589d Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:39:31 +0200 Subject: [PATCH 20/24] Add `similar` to Fields --- src/GridTools.jl | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/GridTools.jl b/src/GridTools.jl index 9127f7e..d602c38 100644 --- a/src/GridTools.jl +++ b/src/GridTools.jl @@ -207,6 +207,47 @@ function Field( return Field(Tuple(dim), data, Tuple(broadcast_dims), origin = origin) end +""" + similar(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} + +Create a new `Field` object similar to `f` but with a different element type `T` or different dimensions `dims`. + +# Arguments +- `f::Field`: The original `Field` object to be replicated. +- `T`: The element type of the new `Field` object (default: element type of `f.data`). +- `dims::Dims`: The dimensions of the new `Field` object (default: size of `f.data`). + +# Returns +- `Field`: A new `Field` object with the specified element type and dimensions. + +# Examples +```julia-repl +julia> A1Dim_ = Dimension(:A1_, LOCAL); + +julia> A1Dim = A1Dim_(); + +julia> in_field = Field((A1Dim, A1Dim), 3*ones(Float64, 4, 4)) +4×4 Float64 Field with dimensions ("A1", "A1") with indices 1:4×1:4: + 3.0 3.0 3.0 3.0 + 3.0 3.0 3.0 3.0 + 3.0 3.0 3.0 3.0 + 3.0 3.0 3.0 3.0 + +julia> out_field = similar(in_field, Int); + +julia> size(out_field) +(4, 4) + +julia> eltype(out_field) +Int64 + +``` +""" +function Base.similar(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} + new_data = similar(f.data, T, dims) + return Field(f.dims, new_data, f.broadcast_dims, f.origin) +end + # TODO(tehrengruber): There is no need to have FieldOffset and FieldOffsetTS, remove FieldOffset struct FieldOffsetTS{ Name, From d1af0f535704edde9c4062cdaf2971392fa9674e Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:01:37 +0200 Subject: [PATCH 21/24] Add notes on future naming for mesh definitions --- test/mesh_definitions.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/mesh_definitions.jl b/test/mesh_definitions.jl index 9385368..9369af2 100644 --- a/test/mesh_definitions.jl +++ b/test/mesh_definitions.jl @@ -1,5 +1,5 @@ -# Unstructured ----------------------------------------------------------------------------------------------- +# ExampleMeshes.Unstructured ----------------------------------------------------------------------------------------------- const global Cell_ = Dimension{:Cell_, HORIZONTAL} const global K_ = Dimension{:K_, HORIZONTAL} @@ -27,7 +27,7 @@ const global E2C = FieldOffset("E2C", source=Cell, target=(Edge, E2CDim)) const global C2E = FieldOffset("C2E", source=Edge, target=(Cell, C2EDim)) const global Koff = FieldOffset("Koff", source=K, target=K) -# Cartesian -------------------------------------------------------------------------------------------------- +# ExampleMeshes.Cartesian -------------------------------------------------------------------------------------------------- const global IDim_ = Dimension{:IDim_, HORIZONTAL} const global JDim_ = Dimension{:JDim_, HORIZONTAL} From ea9b2b13601a1de247e856605bd873771b38b969 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:03:41 +0200 Subject: [PATCH 22/24] Update similar override, use similar_field. Improve naming --- src/GridTools.jl | 5 +- test/gt2py_fo_exec.jl | 153 +++++++++++++++++++++--------------------- 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/src/GridTools.jl b/src/GridTools.jl index d602c38..62354d6 100644 --- a/src/GridTools.jl +++ b/src/GridTools.jl @@ -19,6 +19,7 @@ export Dimension, VERTICAL, LOCAL, Field, + similar_field, Connectivity, FieldOffset, neighbor_sum, @@ -208,7 +209,7 @@ function Field( end """ - similar(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} + similar_field(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} Create a new `Field` object similar to `f` but with a different element type `T` or different dimensions `dims`. @@ -243,7 +244,7 @@ Int64 ``` """ -function Base.similar(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} +function similar_field(f::Field, ::Type{T}=eltype(f.data), dims::Dims=size(f.data)) where {T} new_data = similar(f.data, T, dims) return Field(f.dims, new_data, f.broadcast_dims, f.origin) end diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index d7dc21e..a7d9a9c 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -102,37 +102,37 @@ function copy_borders!(dest_matrix::Matrix{Float64}, src_matrix::Matrix{Float64} return dest_matrix end -function lap_reference(in_field::Matrix{Float64})::Matrix{Float64} - nrows, ncols = size(in_field) +function lap_reference(in_field_data::Matrix{Float64})::Matrix{Float64} + nrows, ncols = size(in_field_data) @assert nrows >= 3 && ncols >= 3 "Input matrix must be at least 3x3 to compute stencil operations." - out_field = zeros(Float64, nrows, ncols) # Initialize out_field as a matrix of zeros + out_field_data = similar(in_field_data) for i in 2:(nrows - 1) for j in 2:(ncols - 1) # Perform the stencil operation - out_field[i, j] = -4 * in_field[i, j] + - in_field[i+1, j] + - in_field[i-1, j] + - in_field[i, j+1] + - in_field[i, j-1] + out_field_data[i, j] = -4 * in_field_data[i, j] + + in_field_data[i+1, j] + + in_field_data[i-1, j] + + in_field_data[i, j+1] + + in_field_data[i, j-1] end end - copy_borders!(out_field, in_field, 1) # Border values are not computed with the stencil operation - return out_field + copy_borders!(out_field_data, in_field_data, 1) # Border values are not computed with the stencil operation + return out_field_data end -function lap_lap_reference(in_field::Matrix{Float64}) - x_length, y_length = size(in_field) +function lap_lap_reference(in_field_data::Matrix{Float64}) + x_length, y_length = size(in_field_data) @assert x_length >= 5 && y_length >= 5 "Input matrix must be at least 5x5 to compute double laplacian." - out_field = zeros(Float64, x_length, y_length) + out_field_data = similar(in_field_data) - out_field = lap_reference(lap_reference(in_field)) + out_field_data = lap_reference(lap_reference(in_field_data)) - copy_borders!(out_field, in_field, 2) # Border values are not computed with the stencil operation - return out_field + copy_borders!(out_field_data, in_field_data, 2) # Border values are not computed with the stencil operation + return out_field_data end # Setup ------------------------------------------------------------------------------------------------------ @@ -198,61 +198,61 @@ function simple_cartesian_field()::Field return Field((IDim, JDim), [Float64((i-1) * 5 + j-1) for i in 1:5, j in 1:5]) end - return Field(Cell, 15.0:-1:1.0) + # return Field(Cell, 15.0:-1:1.0) TODO: adjust this computation function test_fo_addition(backend::String) a = Field(Cell, collect(1.0:15.0)) b = Field(Cell, collect(-1.0:-1:-15.0)) - out = Field(Cell, zeros(Float64, 15)) + out_field = Field(Cell, zeros(Float64, 15)) @field_operator function fo_addition(a::Field{Tuple{Cell_},Float64}, b::Field{Tuple{Cell_},Float64})::Field{Tuple{Cell_},Float64} return a .+ b end - fo_addition(a, b, backend=backend, out=out) - @test all(out.data .== 0) + fo_addition(a, b, backend=backend, out=out_field) + @test all(out_field.data .== 0) end function test_fo_cartesian_offset(backend::String) - inp = Field(K, collect(1.0:15.0)) - out = Field(K, zeros(Float64, 14)) # field is one smaller since we shift by one + a = Field(K, collect(1.0:15.0)) + out_field = Field(K, zeros(Float64, 14)) # field is one smaller since we shift by one @field_operator function fo_cartesian_offset(inp::Field{Tuple{K_},Float64})::Field{Tuple{K_},Float64} return inp(Koff[1]) end - fo_cartesian_offset(inp, backend=backend, out=out, offset_provider=Dict("Koff" => K)) - @test all(out.data .== 2.0:15.0) + fo_cartesian_offset(a, backend=backend, out=out_field, offset_provider=Dict("Koff" => K)) + @test all(out_field.data .== 2.0:15.0) end function test_fo_scalar_multiplication(backend::String) - inp = Field(Cell, collect(1.0:15.0)) - out = Field(Cell, zeros(Float64, 15)) + a = Field(Cell, collect(1.0:15.0)) + out_field = Field(Cell, zeros(Float64, 15)) @field_operator function fo_scalar_mult(inp::Field{Tuple{Cell_},Float64})::Field{Tuple{Cell_},Float64} return 4.0*inp end - fo_scalar_mult(inp, backend=backend, out=out, offset_provider=Dict("Koff" => K)) - @test all(out.data .== 4*(1.0:15.0)) + fo_scalar_mult(a, backend=backend, out=out_field, offset_provider=Dict("Koff" => K)) + @test all(out_field.data .== 4*(1.0:15.0)) end function test_fo_cartesian_offset_composed(backend::String) - inp = Field(K, collect(1.0:15.0)) - out = Field(K, zeros(Float64, 12)) # field is one smaller since we shift by one + a = Field(K, collect(1.0:15.0)) + out_field = Field(K, zeros(Float64, 12)) # field is one smaller since we shift by one @field_operator function fo_cartesian_offset_composed(inp::Field{Tuple{K_},Float64})::Field{Tuple{K_},Float64} tmp = inp(Koff[1]) return tmp(Koff[2]) end - fo_cartesian_offset_composed(inp, backend=backend, out=out, offset_provider=Dict("Koff" => K)) - @test all(out.data .== 4.0:15.0) + fo_cartesian_offset_composed(a, backend=backend, out=out_field, offset_provider=Dict("Koff" => K)) + @test all(out_field.data .== 4.0:15.0) end function test_fo_nested_if_else(backend::String) a = Field(Cell, collect(Int32, 1:15)) # TODO(tehrengruber): if we don't use the right dtype here we get a horrible error in python - out = Field(Cell, zeros(Int32, 15)) + out_field = Field(Cell, zeros(Int32, 15)) @field_operator function fo_nested_if_else(f::Field{Tuple{Cell_},Int32})::Field{Tuple{Cell_},Int32} tmp = f @@ -279,26 +279,27 @@ function test_fo_nested_if_else(backend::String) return tmp end - fo_nested_if_else(a, backend=backend, out=out) - @test all(out.data .== collect(22:36)) + fo_nested_if_else(a, backend=backend, out=out_field) + @test all(out_field.data .== collect(22:36)) end function test_fo_remapping(offset_provider::Dict{String,Connectivity}, backend::String) a = Field(Cell, collect(1.0:15.0)) - out = Field(Edge, zeros(Float64, 12)) expected_output = a[offset_provider["E2C"][:, 1]] # First column of the edge to cell connectivity table + out_field = Field(Edge, similar(expected_output)) + @field_operator function fo_remapping(a::Field{Tuple{Cell_},Float64})::Field{Tuple{Edge_},Float64} return a(E2C[1]) end - fo_remapping(a, offset_provider=offset_provider, backend=backend, out=out) - @test all(out.data .== expected_output) + fo_remapping(a, offset_provider=offset_provider, backend=backend, out=out_field) + @test all(out_field.data .== expected_output) end function test_fo_neighbor_sum(offset_provider::Dict{String,Connectivity}, backend::String) a = Field(Cell, collect(5.0:17.0)*3) - out = Field(Edge, zeros(Float64, 12)) + out_field = Field(Edge, zeros(Float64, 12)) # Function to sum only the positive elements of each inner vector (to exclude the -1 in the connectivity) function sum_positive_elements(v, field_data) @@ -316,8 +317,8 @@ function test_fo_neighbor_sum(offset_provider::Dict{String,Connectivity}, backen return neighbor_sum(a(E2C), axis=E2CDim) end - fo_neighbor_sum(a, offset_provider=offset_provider, backend=backend, out=out) - @test out == expected_output + fo_neighbor_sum(a, offset_provider=offset_provider, backend=backend, out=out_field) + @test out_field == expected_output end function compute_expected_output_comparing_values(offset_provider::Dict{String, Connectivity}, a::Field{Tuple{Cell_}, Float64}, operation::Function) @@ -340,7 +341,7 @@ end function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::String, generate_field::Function) a::Field = generate_field() - out = Field(Edge, zeros(Float64, 12)) + out_field = Field(Edge, zeros(Float64, 12)) # Compute the reference manually computing the maximum of the value of each neighbor expected_output = expected_output = compute_expected_output_comparing_values(offset_provider, a, maximum) @@ -349,13 +350,13 @@ function test_fo_max_over(offset_provider::Dict{String,Connectivity}, backend::S return max_over(a(E2C), axis=E2CDim) end - fo_max_over(a, offset_provider=offset_provider, backend=backend, out=out) - @test out == expected_output + fo_max_over(a, offset_provider=offset_provider, backend=backend, out=out_field) + @test out_field == expected_output end function test_fo_min_over(offset_provider::Dict{String,Connectivity}, backend::String, generate_field::Function) a::Field = generate_field() - out = Field(Edge, zeros(Float64, 12)) + out_field = Field(Edge, zeros(Float64, 12)) # Compute the reference manually computing the minimum of the value of each neighbor expected_output = compute_expected_output_comparing_values(offset_provider, a, minimum) @@ -364,39 +365,39 @@ function test_fo_min_over(offset_provider::Dict{String,Connectivity}, backend::S return min_over(a(E2C), axis=E2CDim) end - fo_min_over(a, offset_provider=offset_provider, backend=backend, out=out) - @test out == expected_output + fo_min_over(a, offset_provider=offset_provider, backend=backend, out=out_field) + @test out_field == expected_output end function test_fo_simple_broadcast(backend::String) - data = collect(1.0:15.0) broadcast_num_dims = 5 - a = Field(Cell, data) - out = Field((Cell, K), zeros(15, broadcast_num_dims)) + a = Field(Cell, collect(1.0:15.0)) # Compute the expected output by broadcasting a expected_output = [a[i] for i in 1:15, j in 1:broadcast_num_dims] + out_field = Field((Cell, K), similar(expected_output)) + @field_operator function fo_simple_broadcast(a::Field{Tuple{Cell_},Float64})::Field{Tuple{Cell_,K_},Float64} return broadcast(a, (Cell, K)) end - fo_simple_broadcast(a, backend=backend, out=out) - @test out == expected_output + fo_simple_broadcast(a, backend=backend, out=out_field) + @test out_field == expected_output end function test_fo_scalar_broadcast(backend::String) - out = Field((Cell, K), fill(0.0, (10, 10))) - # Compute the expected output by broadcasting the value expected_output = fill(5.0, (10, 10)) + out_field = Field((Cell, K), similar(expected_output)) + @field_operator function fo_scalar_broadcast()::Field{Tuple{Cell_,K_},Float64} return broadcast(5.0, (Cell, K)) end - fo_scalar_broadcast(backend=backend, out=out) - @test out == expected_output + fo_scalar_broadcast(backend=backend, out=out_field) + @test out_field == expected_output end function test_fo_where(backend::String) @@ -407,7 +408,7 @@ function test_fo_where(backend::String) true false; false false; true true ]) - out = Field((Cell, K), zeros(5, 2)) + out_field = similar_field(a) expected_output = [ 1 -1 -1 7 @@ -419,13 +420,13 @@ function test_fo_where(backend::String) return where(mask, a, b) end - fo_where(mask, a, b, backend=backend, out=out) - @test out == expected_output + fo_where(mask, a, b, backend=backend, out=out_field) + @test out_field == expected_output end function test_fo_astype(backend::String) a = Field((Cell, K), reshape(collect(1.0:12.0), (6, 2))) # Floating Point - out = Field((Cell, K), zeros(Int64, (6, 2))) + out_field = similar_field(a, Int64) # Integer expected_values = reshape(collect(1.0:12.0), (6, 2)) @@ -433,15 +434,15 @@ function test_fo_astype(backend::String) return convert(Int64, a) # Integer end - fo_astype(a, backend=backend, out=out) - @test out == expected_values - @test eltype(out.data) == Int64 + fo_astype(a, backend=backend, out=out_field) + @test out_field == expected_values + @test eltype(out_field.data) == Int64 @test eltype(a.data) == Float64 end function test_fo_sin(backend::String) a = Field((Cell, K), reshape(collect(1.0:12.0), (6, 2))) - out = Field((Cell, K), zeros((6, 2))) + out_field = similar_field(a) # Compute the expected output using the sin function expected_output = sin.(reshape(collect(1.0:12.0), (6, 2))) @@ -450,13 +451,13 @@ function test_fo_sin(backend::String) return sin.(a) end - fo_sin(a, backend=backend, out=out) - @test isapprox(out.data, expected_output, atol=1e-6) + fo_sin(a, backend=backend, out=out_field) + @test isapprox(out_field.data, expected_output, atol=1e-6) end function test_fo_asinh(backend::String) a = Field((Cell, K), reshape(collect(1.0:12.0), (6, 2))) - out = Field((Cell, K), zeros((6, 2))) + out_field = similar_field(a) # Compute the expected output using the asinh function expected_output = asinh.(reshape(collect(1.0:12.0), (6, 2))) @@ -465,8 +466,8 @@ function test_fo_asinh(backend::String) return asinh.(a) end - fo_asinh(a, backend=backend, out=out) - @test isapprox(out.data, expected_output, atol=1e-6) + fo_asinh(a, backend=backend, out=out_field) + @test isapprox(out_field.data, expected_output, atol=1e-6) end function test_fo_offset_array(backend::String) @@ -487,7 +488,7 @@ end function test_nested_fo(backend::String) a = Field(Cell, collect(1.0:15.0)) b = Field(Cell, ones(15)) - out = Field(Cell, zeros(15)) + out_field = similar_field(a) # Compute the Reference intermediate_result = a.data .+ b.data @@ -502,10 +503,10 @@ function test_nested_fo(backend::String) return res .+ a end - nested_fo(a, b, backend=backend, out=out) + nested_fo(a, b, backend=backend, out=out_field) # Test against the reference - @test out.data == expected_output + @test out_field.data == expected_output end # Define the Laplacian field operation in the global scope for accessibility across multiple tests. @@ -517,8 +518,8 @@ end in_field(Joff[-1]) end -function test_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) - in_field = domain_generator() +function test_lap(offset_provider::Dict{String, Dimension}, backend::String, field_generator::Function, debug::Bool=false) + in_field = field_generator() x_length, y_length = size(in_field.data) out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) expected_out = lap_reference(in_field.data) @@ -539,8 +540,8 @@ function test_lap(offset_provider::Dict{String, Dimension}, backend::String, dom # out_field.data[:, 1] == expected_out[:, 1] && out_field.data[:, end] == expected_out[:, end] end -function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, domain_generator::Function, debug::Bool=false) - in_field = domain_generator() +function test_lap_lap(offset_provider::Dict{String, Dimension}, backend::String, field_generator::Function, debug::Bool=false) + in_field = field_generator() x_length, y_length = size(in_field.data) out_field = Field((IDim, JDim), zeros(Float64, x_length, y_length)) expected_out = lap_lap_reference(in_field.data) From 6f6563e169075a6513a7ade0cb0ec8c69c627810 Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Tue, 23 Jul 2024 17:53:24 +0200 Subject: [PATCH 23/24] Use similar or similar_field wherever is possible --- test/gt2py_fo_exec.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index a7d9a9c..b78827d 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -203,7 +203,9 @@ end function test_fo_addition(backend::String) a = Field(Cell, collect(1.0:15.0)) b = Field(Cell, collect(-1.0:-1:-15.0)) - out_field = Field(Cell, zeros(Float64, 15)) + @assert size(a.data) == size(b.data) "Fields a and b do not have the same size of data." + + out_field = similar_field(a) @field_operator function fo_addition(a::Field{Tuple{Cell_},Float64}, b::Field{Tuple{Cell_},Float64})::Field{Tuple{Cell_},Float64} return a .+ b @@ -227,7 +229,7 @@ end function test_fo_scalar_multiplication(backend::String) a = Field(Cell, collect(1.0:15.0)) - out_field = Field(Cell, zeros(Float64, 15)) + out_field = similar_field(a) @field_operator function fo_scalar_mult(inp::Field{Tuple{Cell_},Float64})::Field{Tuple{Cell_},Float64} return 4.0*inp @@ -252,7 +254,7 @@ end function test_fo_nested_if_else(backend::String) a = Field(Cell, collect(Int32, 1:15)) # TODO(tehrengruber): if we don't use the right dtype here we get a horrible error in python - out_field = Field(Cell, zeros(Int32, 15)) + out_field = similar_field(a) @field_operator function fo_nested_if_else(f::Field{Tuple{Cell_},Int32})::Field{Tuple{Cell_},Int32} tmp = f From d8724a14cfedc39ec404583ef97459f6e435fa8d Mon Sep 17 00:00:00 2001 From: Lorenzo Varese <55581163+lorenzovarese@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:38:40 +0200 Subject: [PATCH 24/24] Update test/gt2py_fo_exec.jl Co-authored-by: Till Ehrengruber --- test/gt2py_fo_exec.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/gt2py_fo_exec.jl b/test/gt2py_fo_exec.jl index b78827d..8724e45 100644 --- a/test/gt2py_fo_exec.jl +++ b/test/gt2py_fo_exec.jl @@ -175,11 +175,10 @@ function setup_simple_connectivity()::Dict{String,Connectivity} end function setup_cartesian_offset_provider() - offset_provider = Dict{String, Dimension}( + return Dict{String, Dimension}( "Ioff" => IDim, "Joff" => JDim ) - return offset_provider end function field_increasing_values()