Skip to content

Commit bff1ac3

Browse files
committed
add 1D GridSubdomain and use in 2D and 3D implementations
1 parent 8bb9150 commit bff1ac3

File tree

10 files changed

+198
-296
lines changed

10 files changed

+198
-296
lines changed

md1/md1.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,31 @@ func (nra NewtonRaphsonSolver) Root(x0 float64, f func(xGuess float64) float64)
162162
}
163163
return x_root, -nra.MaxIterations
164164
}
165+
166+
// GridSubdomain returns the indexing for a 1D subdomain contained within a larger gridded domain of equally spaced nGridPoints points.
167+
// - iStart contains the starting index of the first point contained within the subdomain.
168+
// - nSub is the number of consecutive grid points contained within the subdomain.
169+
//
170+
// This function is primarily used for higher dimension GridSubdomain calls in 2D and 3D packages
171+
func GridSubdomain(domMin, domMax float64, nGridPoints int, subMin, subMax float64) (iStart, nSub int) {
172+
if domMin > domMax || subMin > subMax || subMax > domMax || nGridPoints <= 1 {
173+
panic("invalid arguments to gridSubdomain")
174+
}
175+
dx := (domMax - domMin) / float64(nGridPoints-1) // The size of grid spaces.
176+
startOffset := subMin - domMin
177+
iStartf := startOffset / dx
178+
iStart = min(int(math.Ceil(iStartf)), nGridPoints-1)
179+
180+
endOffset := subMax - domMin
181+
iEndf := endOffset / dx
182+
iEnd := min(int(math.Ceil(iEndf)), nGridPoints-1)
183+
nSub = iEnd - iStart
184+
return iStart, nSub
185+
}
186+
187+
func min(a, b int) int {
188+
if a < b {
189+
return a
190+
}
191+
return b
192+
}

md1/md1_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// DO NOT EDIT.
2+
// This file was generated automatically
3+
// from gen.go. Please do not edit this file.
4+
5+
package md1
6+
7+
import (
8+
"math/rand"
9+
"testing"
10+
)
11+
12+
func Test_gridSubdomainInternal(t *testing.T) {
13+
rng := rand.New(rand.NewSource(1))
14+
for i := 0; i < 100000; i++ {
15+
dmin := float64(rng.Float64())
16+
dmax := dmin + float64(rng.Float64())
17+
dsize := dmax - dmin
18+
19+
smin := dmin + float64(rng.Float64())*dsize
20+
smaxsize := dmax - smin
21+
smax := smin + float64(rng.Float64())*smaxsize
22+
if i%8 == 0 {
23+
smax = dmax
24+
}
25+
if i%16 == 0 {
26+
smin = dmin
27+
}
28+
ssize := smax - smin
29+
for Nd := 2; Nd < 10; Nd++ {
30+
istart, nsub := GridSubdomain(dmin, dmax, Nd, smin, smax)
31+
if nsub > Nd {
32+
t.Error("subdomain contains more grid points than actual domain", nsub, Nd)
33+
} else if istart >= Nd {
34+
t.Error("istart >= Nd", istart, Nd)
35+
} else if istart+nsub > Nd {
36+
t.Error("istart+nsub>Nd", istart, nsub, istart+nsub, Nd)
37+
} else if nsub < 0 {
38+
t.Error("nsub<0", nsub)
39+
}
40+
dx := dsize / float64(Nd-1)
41+
calc_xmax := dmin + float64(istart+nsub-1)*dx
42+
calc_xmin := dmin + float64(istart)*dx
43+
if nsub > 0 && calc_xmax > smax {
44+
t.Error("xmax > smax", calc_xmax, smax)
45+
}
46+
if nsub > 0 && calc_xmin < smin {
47+
t.Error("xmin < smin", calc_xmin, smin)
48+
}
49+
if nsub > 0 && calc_xmax > dmax {
50+
t.Error("xmax > dmax", calc_xmax, dmax)
51+
}
52+
_ = ssize
53+
if t.Failed() {
54+
istart, nsub = GridSubdomain(dmin, dmax, Nd, smin, smax) // For debugging.
55+
t.Fatalf("failed on output: i=%d ns=%d input: d=(%.3f,%.3f) N=%d sub=(%.3f, %.3f) ix=%.3f",
56+
istart, nsub, dmin, dmax, Nd, smin, smax, calc_xmin)
57+
}
58+
}
59+
}
60+
}

md2/grid.go

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
package md2
66

7-
import (
8-
math "math"
9-
)
7+
import ms1 "github.com/soypat/geometry/md1"
108

119
// AppendGrid splits the argument bounds [Box] x,y axes by nx,ny, respectively
1210
// and generates points on the vertices generated by the division and appends them to dst, returning the result.
@@ -50,23 +48,8 @@ func GridSubdomain(domain Box, nxDomain, nyDomain int, subdomain Box) (iStart, n
5048
if !domain.ContainsBox(subdomain) {
5149
panic("subdomain not contained in domain")
5250
}
53-
dx := (domain.Max.X - domain.Min.X) / float64(nxDomain-1)
54-
dy := (domain.Max.Y - domain.Min.Y) / float64(nyDomain-1)
55-
56-
off := Sub(subdomain.Min, domain.Min)
57-
ix0 := iceil(off.X / dx)
58-
iy0 := iceil(off.Y / dy)
59-
iStart = ix0 + iy0*nxDomain
60-
61-
offEnd := Sub(subdomain.Max, domain.Min)
62-
ixf := int(offEnd.X / dx)
63-
iyf := int(offEnd.Y / dy)
64-
65-
nxSub = ixf - ix0 + 1
66-
nySub = iyf - iy0 + 1
67-
return iStart, nxSub, nySub
68-
}
69-
70-
func iceil(f float64) int {
71-
return int(math.Ceil(f))
51+
var ix0, iy0 int
52+
ix0, nxSub = ms1.GridSubdomain(domain.Min.X, domain.Max.X, nxDomain, subdomain.Min.X, subdomain.Max.X)
53+
iy0, nySub = ms1.GridSubdomain(domain.Min.Y, domain.Max.Y, nyDomain, subdomain.Min.Y, subdomain.Max.Y)
54+
return ix0 + iy0*nxDomain, nxSub, nySub
7255
}

md2/md2_test.go

Lines changed: 0 additions & 105 deletions
This file was deleted.

md3/grid.go

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
package md3
66

7-
import math "math"
7+
import (
8+
ms1 "github.com/soypat/geometry/md1"
9+
)
810

911
// AppendGrid splits the argument bounds [Box] x,y,z axes by nx,ny,nz, respectively
1012
// and generates points on the vertices generated by the division and appends them to dst, returning the result.
@@ -54,26 +56,9 @@ func GridSubdomain(domain Box, nxDomain, nyDomain, nzDomain int, subdomain Box)
5456
if !domain.ContainsBox(subdomain) {
5557
panic("subdomain not contained in domain")
5658
}
57-
dx := (domain.Max.X - domain.Min.X) / float64(nxDomain-1)
58-
dy := (domain.Max.Y - domain.Min.Y) / float64(nyDomain-1)
59-
dz := (domain.Max.Z - domain.Min.Z) / float64(nzDomain-1)
60-
off := Sub(subdomain.Min, domain.Min)
61-
ix0 := iceil(off.X / dx)
62-
iy0 := iceil(off.Y / dy)
63-
iz0 := iceil(off.Z / dz)
64-
iStart = ix0 + iy0*nxDomain + iz0*(nxDomain+nyDomain)
65-
66-
offEnd := Sub(subdomain.Max, domain.Min)
67-
ixf := int(offEnd.X / dx)
68-
iyf := int(offEnd.Y / dy)
69-
izf := int(offEnd.Z / dz)
70-
71-
nxSub = ixf - ix0 + 1
72-
nySub = iyf - iy0 + 1
73-
nzSub = izf - iz0 + 1
74-
return iStart, nxSub, nySub, nzSub
75-
}
76-
77-
func iceil(f float64) int {
78-
return int(math.Ceil(f))
59+
var ix0, iy0, iz0 int
60+
ix0, nxSub = ms1.GridSubdomain(domain.Min.X, domain.Max.X, nxDomain, subdomain.Min.X, subdomain.Max.X)
61+
iy0, nySub = ms1.GridSubdomain(domain.Min.Y, domain.Max.Y, nyDomain, subdomain.Min.Y, subdomain.Max.Y)
62+
iz0, nzSub = ms1.GridSubdomain(domain.Min.Z, domain.Max.Z, nzDomain, subdomain.Min.Z, subdomain.Max.Z)
63+
return ix0 + iy0*nxDomain + iz0*(nxDomain+nyDomain), nxSub, nySub, nzSub
7964
}

ms1/ms1.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,31 @@ func (nra NewtonRaphsonSolver) Root(x0 float32, f func(xGuess float32) float32)
158158
}
159159
return x_root, -nra.MaxIterations
160160
}
161+
162+
// GridSubdomain returns the indexing for a 1D subdomain contained within a larger gridded domain of equally spaced nGridPoints points.
163+
// - iStart contains the starting index of the first point contained within the subdomain.
164+
// - nSub is the number of consecutive grid points contained within the subdomain.
165+
//
166+
// This function is primarily used for higher dimension GridSubdomain calls in 2D and 3D packages
167+
func GridSubdomain(domMin, domMax float32, nGridPoints int, subMin, subMax float32) (iStart, nSub int) {
168+
if domMin > domMax || subMin > subMax || subMax > domMax || nGridPoints <= 1 {
169+
panic("invalid arguments to gridSubdomain")
170+
}
171+
dx := (domMax - domMin) / float32(nGridPoints-1) // The size of grid spaces.
172+
startOffset := subMin - domMin
173+
iStartf := startOffset / dx
174+
iStart = min(int(math.Ceil(iStartf)), nGridPoints-1)
175+
176+
endOffset := subMax - domMin
177+
iEndf := endOffset / dx
178+
iEnd := min(int(math.Ceil(iEndf)), nGridPoints-1)
179+
nSub = iEnd - iStart
180+
return iStart, nSub
181+
}
182+
183+
func min(a, b int) int {
184+
if a < b {
185+
return a
186+
}
187+
return b
188+
}

ms1/ms1_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package ms1
2+
3+
import (
4+
"math/rand"
5+
"testing"
6+
)
7+
8+
func Test_gridSubdomainInternal(t *testing.T) {
9+
rng := rand.New(rand.NewSource(1))
10+
for i := 0; i < 100000; i++ {
11+
dmin := float32(rng.Float64())
12+
dmax := dmin + float32(rng.Float64())
13+
dsize := dmax - dmin
14+
15+
smin := dmin + float32(rng.Float64())*dsize
16+
smaxsize := dmax - smin
17+
smax := smin + float32(rng.Float64())*smaxsize
18+
if i%8 == 0 {
19+
smax = dmax
20+
}
21+
if i%16 == 0 {
22+
smin = dmin
23+
}
24+
ssize := smax - smin
25+
for Nd := 2; Nd < 10; Nd++ {
26+
istart, nsub := GridSubdomain(dmin, dmax, Nd, smin, smax)
27+
if nsub > Nd {
28+
t.Error("subdomain contains more grid points than actual domain", nsub, Nd)
29+
} else if istart >= Nd {
30+
t.Error("istart >= Nd", istart, Nd)
31+
} else if istart+nsub > Nd {
32+
t.Error("istart+nsub>Nd", istart, nsub, istart+nsub, Nd)
33+
} else if nsub < 0 {
34+
t.Error("nsub<0", nsub)
35+
}
36+
dx := dsize / float32(Nd-1)
37+
calc_xmax := dmin + float32(istart+nsub-1)*dx
38+
calc_xmin := dmin + float32(istart)*dx
39+
if nsub > 0 && calc_xmax > smax {
40+
t.Error("xmax > smax", calc_xmax, smax)
41+
}
42+
if nsub > 0 && calc_xmin < smin {
43+
t.Error("xmin < smin", calc_xmin, smin)
44+
}
45+
if nsub > 0 && calc_xmax > dmax {
46+
t.Error("xmax > dmax", calc_xmax, dmax)
47+
}
48+
_ = ssize
49+
if t.Failed() {
50+
istart, nsub = GridSubdomain(dmin, dmax, Nd, smin, smax) // For debugging.
51+
t.Fatalf("failed on output: i=%d ns=%d input: d=(%.3f,%.3f) N=%d sub=(%.3f, %.3f) ix=%.3f",
52+
istart, nsub, dmin, dmax, Nd, smin, smax, calc_xmin)
53+
}
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)