func main() { // input matrix in Triplet format // including repeated positions. e.g. (0,0) var A la.Triplet A.Init(5, 5, 13) A.Put(0, 0, 1.0) // << repeated A.Put(0, 0, 1.0) // << repeated A.Put(1, 0, 3.0) A.Put(0, 1, 3.0) A.Put(2, 1, -1.0) A.Put(4, 1, 4.0) A.Put(1, 2, 4.0) A.Put(2, 2, -3.0) A.Put(3, 2, 1.0) A.Put(4, 2, 2.0) A.Put(2, 3, 2.0) A.Put(1, 4, 6.0) A.Put(4, 4, 1.0) // right-hand-side b := []float64{8.0, 45.0, -3.0, 3.0, 19.0} // solve x, err := la.SolveRealLinSys(&A, b) if err != nil { io.Pfred("solver failed:\n%v", err) return } // output la.PrintMat("a", A.ToMatrix(nil).ToDense(), "%5g", false) la.PrintVec("b", b, "%v ", false) la.PrintVec("x", x, "%v ", false) }
func CompareJac(tst *testing.T, ffcn Cb_f, Jfcn Cb_J, x []float64, tol float64, distr bool) { n := len(x) // numerical fx := make([]float64, n) w := make([]float64, n) // workspace ffcn(fx, x) var Jnum la.Triplet Jnum.Init(n, n, n*n) Jacobian(&Jnum, ffcn, x, fx, w, distr) jn := Jnum.ToMatrix(nil) // analytical var Jana la.Triplet Jana.Init(n, n, n*n) Jfcn(&Jana, x) ja := Jana.ToMatrix(nil) // compare //la.PrintMat(fmt.Sprintf("Jana(%d)",mpi.Rank()), ja.ToDense(), "%13.6f", false) //la.PrintMat(fmt.Sprintf("Jnum(%d)",mpi.Rank()), jn.ToDense(), "%13.6f", false) max_diff := la.MatMaxDiff(jn.ToDense(), ja.ToDense()) if max_diff > tol { tst.Errorf("[1;31mmax_diff = %g[0m\n", max_diff) } else { io.Pf("[1;32mmax_diff = %g[0m\n", max_diff) } }
func main() { // input matrix in Triplet format // including repeated positions. e.g. (0,0) var A la.Triplet A.Init(5, 5, 13) A.Put(0, 0, 1.0) // << repeated A.Put(0, 0, 1.0) // << repeated A.Put(1, 0, 3.0) A.Put(0, 1, 3.0) A.Put(2, 1, -1.0) A.Put(4, 1, 4.0) A.Put(1, 2, 4.0) A.Put(2, 2, -3.0) A.Put(3, 2, 1.0) A.Put(4, 2, 2.0) A.Put(2, 3, 2.0) A.Put(1, 4, 6.0) A.Put(4, 4, 1.0) // right-hand-side b := []float64{8.0, 45.0, -3.0, 3.0, 19.0} // allocate solver lis := la.GetSolver("umfpack") defer lis.Clean() // info symmetric := false verbose := false timing := false // initialise solver (R)eal err := lis.InitR(&A, symmetric, verbose, timing) if err != nil { io.Pfred("solver failed:\n%v", err) return } // factorise err = lis.Fact() if err != nil { io.Pfred("solver failed:\n%v", err) return } // solve (R)eal var dummy bool x := make([]float64, len(b)) err = lis.SolveR(x, b, dummy) // x := inv(a) * b if err != nil { io.Pfred("solver failed:\n%v", err) return } // output la.PrintMat("a", A.ToMatrix(nil).ToDense(), "%5g", false) la.PrintVec("b", b, "%v ", false) la.PrintVec("x", x, "%v ", false) }
// CompareJacMpi compares Jacobian matrix (e.g. for testing) func CompareJacMpi(tst *testing.T, ffcn Cb_f, Jfcn Cb_J, x []float64, tol float64, distr bool) { // numerical n := len(x) fx := make([]float64, n) w := make([]float64, n) // workspace ffcn(fx, x) var Jnum la.Triplet Jnum.Init(n, n, n*n) JacobianMpi(&Jnum, ffcn, x, fx, w, distr) jn := Jnum.ToMatrix(nil) // analytical var Jana la.Triplet Jana.Init(n, n, n*n) Jfcn(&Jana, x) ja := Jana.ToMatrix(nil) // compare max_diff := la.MatMaxDiff(jn.ToDense(), ja.ToDense()) if max_diff > tol { tst.Errorf("[1;31mmax_diff = %g[0m\n", max_diff) } else { io.Pf("[1;32mmax_diff = %g[0m\n", max_diff) } }
// CheckJ check Jacobian matrix // Ouptut: cnd -- condition number (with Frobenius norm) func (o *NlSolver) CheckJ(x []float64, tol float64, chkJnum, silent bool) (cnd float64, err error) { // Jacobian matrix var Jmat [][]float64 if o.useDn { Jmat = la.MatAlloc(o.neq, o.neq) err = o.JfcnDn(Jmat, x) if err != nil { return 0, chk.Err(_nls_err5, "dense", err.Error()) } } else { if o.numJ { err = Jacobian(&o.Jtri, o.Ffcn, x, o.fx, o.w, false) if err != nil { return 0, chk.Err(_nls_err5, "sparse", err.Error()) } } else { err = o.JfcnSp(&o.Jtri, x) if err != nil { return 0, chk.Err(_nls_err5, "sparse(num)", err.Error()) } } Jmat = o.Jtri.ToMatrix(nil).ToDense() } //la.PrintMat("J", Jmat, "%23g", false) // condition number cnd, err = la.MatCondG(Jmat, "F", 1e-10) if err != nil { return cnd, chk.Err(_nls_err6, err.Error()) } if math.IsInf(cnd, 0) || math.IsNaN(cnd) { return cnd, chk.Err(_nls_err7, cnd) } // numerical Jacobian if !chkJnum { return } var Jtmp la.Triplet ws := make([]float64, o.neq) err = o.Ffcn(o.fx, x) if err != nil { return } Jtmp.Init(o.neq, o.neq, o.neq*o.neq) Jacobian(&Jtmp, o.Ffcn, x, o.fx, ws, false) Jnum := Jtmp.ToMatrix(nil).ToDense() for i := 0; i < o.neq; i++ { for j := 0; j < o.neq; j++ { chk.PrintAnaNum(io.Sf("J[%d][%d]", i, j), tol, Jmat[i][j], Jnum[i][j], !silent) } } maxdiff := la.MatMaxDiff(Jmat, Jnum) if maxdiff > tol { err = chk.Err(_nls_err8, maxdiff) } return }
/* Jacobian ======== Calculates (with N=n-1): df0dx0, df0dx1, df0dx2, ... df0dxN df1dx0, df1dx1, df1dx2, ... df1dxN . . . . . . . . . . . . . dfNdx0, dfNdx1, dfNdx2, ... dfNdxN INPUT: ffcn : f(x) function x : station where dfdx has to be calculated fx : f @ x w : workspace with size == n == len(x) RETURNS: J : dfdx @ x [must be pre-allocated] */ func Jacobian(J *la.Triplet, ffcn Cb_f, x, fx, w []float64, distr bool) (err error) { ndim := len(x) start, endp1 := 0, ndim if distr { id, sz := mpi.Rank(), mpi.Size() start, endp1 = (id*ndim)/sz, ((id+1)*ndim)/sz if J.Max() == 0 { J.Init(ndim, ndim, (endp1-start)*ndim) } } else { if J.Max() == 0 { J.Init(ndim, ndim, ndim*ndim) } } J.Start() // NOTE: cannot split calculation by columns unless the f function is // independently calculated by each MPI processor. // Otherwise, the AllReduce in f calculation would // join pieces of f from different processors calculated for // different x values (δx[col] from different columns). /* for col := start; col < endp1; col++ { xsafe := x[col] delta := math.Sqrt(EPS * max(CTE1, math.Abs(xsafe))) x[col] = xsafe + delta ffcn(w, x) // fnew io.Pforan("x = %v, f = %v\n", x, w) for row := 0; row < ndim; row++ { J.Put(row, col, (w[row]-fx[row])/delta) } x[col] = xsafe } */ var df float64 for col := 0; col < ndim; col++ { xsafe := x[col] delta := math.Sqrt(EPS * max(CTE1, math.Abs(xsafe))) x[col] = xsafe + delta err = ffcn(w, x) // w := f(x+δx[col]) if err != nil { return } for row := start; row < endp1; row++ { df = w[row] - fx[row] //if math.Abs(df) > EPS { J.Put(row, col, df/delta) //} } x[col] = xsafe } return }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() if mpi.Rank() == 0 { chk.PrintTitle("Test SumToRoot 01") } M := [][]float64{ {1000, 1000, 1000, 1011, 1021, 1000}, {1000, 1000, 1000, 1012, 1022, 1000}, {1000, 1000, 1000, 1013, 1023, 1000}, {1011, 1012, 1013, 1000, 1000, 1000}, {1021, 1022, 1023, 1000, 1000, 1000}, {1000, 1000, 1000, 1000, 1000, 1000}, } id, sz, m := mpi.Rank(), mpi.Size(), len(M) start, endp1 := (id*m)/sz, ((id+1)*m)/sz if sz > 6 { chk.Panic("this test works with at most 6 processors") } var J la.Triplet J.Init(m, m, m*m) for i := start; i < endp1; i++ { for j := 0; j < m; j++ { J.Put(i, j, M[i][j]) } } la.PrintMat(fmt.Sprintf("J @ proc # %d", id), J.ToMatrix(nil).ToDense(), "%10.1f", false) la.SpTriSumToRoot(&J) var tst testing.T if mpi.Rank() == 0 { chk.Matrix(&tst, "J @ proc 0", 1.0e-17, J.ToMatrix(nil).ToDense(), [][]float64{ {1000, 1000, 1000, 1011, 1021, 1000}, {1000, 1000, 1000, 1012, 1022, 1000}, {1000, 1000, 1000, 1013, 1023, 1000}, {1011, 1012, 1013, 1000, 1000, 1000}, {1021, 1022, 1023, 1000, 1000, 1000}, {1000, 1000, 1000, 1000, 1000, 1000}, }) } }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() myrank := mpi.Rank() if myrank == 0 { chk.PrintTitle("Test MUMPS Sol 02") } ndim := 10 id, sz := mpi.Rank(), mpi.Size() start, endp1 := (id*ndim)/sz, ((id+1)*ndim)/sz if mpi.Size() > ndim { chk.Panic("the number of processors must be smaller than or equal to %d", ndim) } b := make([]float64, ndim) var t la.Triplet t.Init(ndim, ndim, ndim*ndim) for i := start; i < endp1; i++ { j := i if i > 0 { j = i - 1 } for ; j < ndim; j++ { val := 10.0 - float64(j) if i > j { val -= 1.0 } t.Put(i, j, val) } b[i] = float64(i + 1) } x_correct := []float64{-1, 8, -65, 454, -2725, 13624, -54497, 163490, -326981, 326991} sum_b_to_root := true la.RunMumpsTestR(&t, 1e-4, b, x_correct, sum_b_to_root) }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() myrank := mpi.Rank() if myrank == 0 { chk.PrintTitle("Test MUMPS Sol 01a") } var t la.Triplet switch mpi.Size() { case 1: t.Init(5, 5, 13) t.Put(0, 0, 1.0) t.Put(0, 0, 1.0) t.Put(1, 0, 3.0) t.Put(0, 1, 3.0) t.Put(2, 1, -1.0) t.Put(4, 1, 4.0) t.Put(1, 2, 4.0) t.Put(2, 2, -3.0) t.Put(3, 2, 1.0) t.Put(4, 2, 2.0) t.Put(2, 3, 2.0) t.Put(1, 4, 6.0) t.Put(4, 4, 1.0) case 2: if myrank == 0 { t.Init(5, 5, 6) t.Put(0, 0, 1.0) t.Put(0, 0, 1.0) t.Put(1, 0, 3.0) t.Put(0, 1, 3.0) t.Put(2, 1, -1.0) t.Put(4, 1, 4.0) } else { t.Init(5, 5, 7) t.Put(1, 2, 4.0) t.Put(2, 2, -3.0) t.Put(3, 2, 1.0) t.Put(4, 2, 2.0) t.Put(2, 3, 2.0) t.Put(1, 4, 6.0) t.Put(4, 4, 1.0) } default: chk.Panic("this test needs 1 or 2 procs") } b := []float64{8.0, 45.0, -3.0, 3.0, 19.0} x_correct := []float64{1, 2, 3, 4, 5} sum_b_to_root := false la.RunMumpsTestR(&t, 1e-14, b, x_correct, sum_b_to_root) }
// Jacobian computes Jacobian (sparse) matrix // Calculates (with N=n-1): // df0dx0, df0dx1, df0dx2, ... df0dxN // df1dx0, df1dx1, df1dx2, ... df1dxN // . . . . . . . . . . . . . // dfNdx0, dfNdx1, dfNdx2, ... dfNdxN // INPUT: // ffcn : f(x) function // x : station where dfdx has to be calculated // fx : f @ x // w : workspace with size == n == len(x) // RETURNS: // J : dfdx @ x [must be pre-allocated] func Jacobian(J *la.Triplet, ffcn Cb_f, x, fx, w []float64) (err error) { ndim := len(x) start, endp1 := 0, ndim if J.Max() == 0 { J.Init(ndim, ndim, ndim*ndim) } J.Start() var df float64 for col := 0; col < ndim; col++ { xsafe := x[col] delta := math.Sqrt(EPS * max(CTE1, math.Abs(xsafe))) x[col] = xsafe + delta err = ffcn(w, x) // w := f(x+δx[col]) if err != nil { return } for row := start; row < endp1; row++ { df = w[row] - fx[row] J.Put(row, col, df/delta) } x[col] = xsafe } return }
func InitK11andK12(K11, K12 *la.Triplet, e *Equations) { K11.Init(e.N1, e.N1, e.N1*5) K12.Init(e.N1, e.N2, e.N1*5) }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() if mpi.Rank() == 0 { chk.PrintTitle("Test ODE 04b (MPI)") io.Pfcyan("Hairer-Wanner VII-p376 Transistor Amplifier (MPI)\n") io.Pfcyan("(from E Hairer's website, not the system in the book)\n") } if mpi.Size() != 3 { chk.Panic(">> error: this test requires 3 MPI processors\n") return } // RIGHT-HAND SIDE OF THE AMPLIFIER PROBLEM w := make([]float64, 8) // workspace fcn := func(f []float64, x float64, y []float64, args ...interface{}) error { d := args[0].(*HWtransData) UET := d.UE * math.Sin(d.W*x) FAC1 := d.BETA * (math.Exp((y[3]-y[2])/d.UF) - 1.0) FAC2 := d.BETA * (math.Exp((y[6]-y[5])/d.UF) - 1.0) la.VecFill(f, 0) switch mpi.Rank() { case 0: f[0] = y[0] / d.R9 case 1: f[1] = (y[1]-d.UB)/d.R8 + d.ALPHA*FAC1 f[2] = y[2]/d.R7 - FAC1 case 2: f[3] = y[3]/d.R5 + (y[3]-d.UB)/d.R6 + (1.0-d.ALPHA)*FAC1 f[4] = (y[4]-d.UB)/d.R4 + d.ALPHA*FAC2 f[5] = y[5]/d.R3 - FAC2 f[6] = y[6]/d.R1 + (y[6]-d.UB)/d.R2 + (1.0-d.ALPHA)*FAC2 f[7] = (y[7] - UET) / d.R0 } mpi.AllReduceSum(f, w) return nil } // JACOBIAN OF THE AMPLIFIER PROBLEM jac := func(dfdy *la.Triplet, x float64, y []float64, args ...interface{}) error { d := args[0].(*HWtransData) FAC14 := d.BETA * math.Exp((y[3]-y[2])/d.UF) / d.UF FAC27 := d.BETA * math.Exp((y[6]-y[5])/d.UF) / d.UF if dfdy.Max() == 0 { dfdy.Init(8, 8, 16) } NU := 2 dfdy.Start() switch mpi.Rank() { case 0: dfdy.Put(2+0-NU, 0, 1.0/d.R9) dfdy.Put(2+1-NU, 1, 1.0/d.R8) dfdy.Put(1+2-NU, 2, -d.ALPHA*FAC14) dfdy.Put(0+3-NU, 3, d.ALPHA*FAC14) dfdy.Put(2+2-NU, 2, 1.0/d.R7+FAC14) case 1: dfdy.Put(1+3-NU, 3, -FAC14) dfdy.Put(2+3-NU, 3, 1.0/d.R5+1.0/d.R6+(1.0-d.ALPHA)*FAC14) dfdy.Put(3+2-NU, 2, -(1.0-d.ALPHA)*FAC14) dfdy.Put(2+4-NU, 4, 1.0/d.R4) dfdy.Put(1+5-NU, 5, -d.ALPHA*FAC27) case 2: dfdy.Put(0+6-NU, 6, d.ALPHA*FAC27) dfdy.Put(2+5-NU, 5, 1.0/d.R3+FAC27) dfdy.Put(1+6-NU, 6, -FAC27) dfdy.Put(2+6-NU, 6, 1.0/d.R1+1.0/d.R2+(1.0-d.ALPHA)*FAC27) dfdy.Put(3+5-NU, 5, -(1.0-d.ALPHA)*FAC27) dfdy.Put(2+7-NU, 7, 1.0/d.R0) } return nil } // MATRIX "M" c1, c2, c3, c4, c5 := 1.0e-6, 2.0e-6, 3.0e-6, 4.0e-6, 5.0e-6 var M la.Triplet M.Init(8, 8, 14) M.Start() NU := 1 switch mpi.Rank() { case 0: M.Put(1+0-NU, 0, -c5) M.Put(0+1-NU, 1, c5) M.Put(2+0-NU, 0, c5) M.Put(1+1-NU, 1, -c5) M.Put(1+2-NU, 2, -c4) M.Put(1+3-NU, 3, -c3) case 1: M.Put(0+4-NU, 4, c3) M.Put(2+3-NU, 3, c3) M.Put(1+4-NU, 4, -c3) case 2: M.Put(1+5-NU, 5, -c2) M.Put(1+6-NU, 6, -c1) M.Put(0+7-NU, 7, c1) M.Put(2+6-NU, 6, c1) M.Put(1+7-NU, 7, -c1) } // WRITE FILE FUNCTION idxstp := 1 var b bytes.Buffer out := func(first bool, dx, x float64, y []float64, args ...interface{}) error { if mpi.Rank() == 0 { if first { fmt.Fprintf(&b, "%6s%23s%23s%23s%23s%23s%23s%23s%23s%23s\n", "ns", "x", "y0", "y1", "y2", "y3", "y4", "y5", "y6", "y7") } fmt.Fprintf(&b, "%6d%23.15E", idxstp, x) for j := 0; j < len(y); j++ { fmt.Fprintf(&b, "%23.15E", y[j]) } fmt.Fprintf(&b, "\n") idxstp += 1 } return nil } defer func() { if mpi.Rank() == 0 { io.WriteFileD("/tmp/gosl", "hwamplifierB.res", &b) } }() // INITIAL DATA D, xa, xb, ya := HWtransIni() // SET ODE SOLVER silent := false fixstp := false //method := "Dopri5" method := "Radau5" ndim := len(ya) //numjac := true numjac := false var osol ode.ODE osol.Pll = true if numjac { osol.Init(method, ndim, fcn, nil, &M, out, silent) } else { osol.Init(method, ndim, fcn, jac, &M, out, silent) } osol.IniH = 1.0e-6 // initial step size // SET TOLERANCES atol, rtol := 1e-11, 1e-5 osol.SetTol(atol, rtol) // RUN t0 := time.Now() if fixstp { osol.Solve(ya, xa, xb, 0.01, fixstp, &D) } else { osol.Solve(ya, xa, xb, xb-xa, fixstp, &D) } if mpi.Rank() == 0 { io.Pfmag("elapsed time = %v\n", time.Now().Sub(t0)) } }
func Test_linipm02(tst *testing.T) { //verbose() chk.PrintTitle("linipm02") // linear program // min 2*x0 + x1 // s.t. -x0 + x1 ≤ 1 // x0 + x1 ≥ 2 → -x0 - x1 ≤ -2 // x0 - 2*x1 ≤ 4 // x1 ≥ 0 // standard (step 1) add slack // s.t. -x0 + x1 + x2 = 1 // -x0 - x1 + x3 = -2 // x0 - 2*x1 + x4 = 4 // standard (step 2) // replace x0 := x0_ - x5 // because it's unbounded // min 2*x0_ + x1 - 2*x5 // s.t. -x0_ + x1 + x2 + x5 = 1 // -x0_ - x1 + x3 + x5 = -2 // x0_ - 2*x1 + x4 - x5 = 4 // x0_,x1,x2,x3,x4,x5 ≥ 0 var T la.Triplet T.Init(3, 6, 12) T.Put(0, 0, -1) T.Put(0, 1, 1) T.Put(0, 2, 1) T.Put(0, 5, 1) T.Put(1, 0, -1) T.Put(1, 1, -1) T.Put(1, 3, 1) T.Put(1, 5, 1) T.Put(2, 0, 1) T.Put(2, 1, -2) T.Put(2, 4, 1) T.Put(2, 5, -1) Am := T.ToMatrix(nil) A := Am.ToDense() c := []float64{2, 1, 0, 0, 0, -2} b := []float64{1, -2, 4} // print LP la.PrintMat("A", A, "%6g", false) la.PrintVec("b", b, "%6g", false) la.PrintVec("c", c, "%6g", false) io.Pf("\n") // solve LP var ipm LinIpm defer ipm.Clean() ipm.Init(Am, b, c, nil) err := ipm.Solve(chk.Verbose) if err != nil { tst.Errorf("ipm failed:\n%v", err) return } // check io.Pf("\n") bres := make([]float64, len(b)) la.MatVecMul(bres, 1, A, ipm.X) io.Pforan("bres = %v\n", bres) chk.Vector(tst, "A*x=b", 1e-8, bres, b) // fix and check x x := ipm.X[:2] x[0] -= ipm.X[5] io.Pforan("x = %v\n", x) chk.Vector(tst, "x", 1e-8, x, []float64{0.5, 1.5}) // plot if true && chk.Verbose { f := func(x []float64) float64 { return c[0]*x[0] + c[1]*x[1] } g := func(x []float64, i int) float64 { return A[i][0]*x[0] + A[i][1]*x[1] - b[i] } np := 41 vmin, vmax := []float64{-2.0, -2.0}, []float64{2.0, 2.0} PlotTwoVarsContour("/tmp/gosl", "test_linipm02", x, np, nil, true, vmin, vmax, f, func(x []float64) float64 { return g(x, 0) }, func(x []float64) float64 { return g(x, 1) }, ) } }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() myrank := mpi.Rank() if myrank == 0 { chk.PrintTitle("Test MUMPS Sol 01b") } var t la.Triplet b := []float64{8.0, 45.0, -3.0, 3.0, 19.0} switch mpi.Size() { case 1: t.Init(5, 5, 13) t.Put(0, 0, 1.0) t.Put(0, 0, 1.0) t.Put(1, 0, 3.0) t.Put(0, 1, 3.0) t.Put(2, 1, -1.0) t.Put(4, 1, 4.0) t.Put(1, 2, 4.0) t.Put(2, 2, -3.0) t.Put(3, 2, 1.0) t.Put(4, 2, 2.0) t.Put(2, 3, 2.0) t.Put(1, 4, 6.0) t.Put(4, 4, 1.0) case 2: la.VecFill(b, 0) if myrank == 0 { t.Init(5, 5, 8) t.Put(0, 0, 1.0) t.Put(0, 0, 1.0) t.Put(1, 0, 3.0) t.Put(0, 1, 3.0) t.Put(2, 1, -1.0) t.Put(4, 1, 1.0) t.Put(4, 1, 1.5) t.Put(4, 1, 1.5) b[0] = 8.0 b[1] = 40.0 b[2] = 1.5 } else { t.Init(5, 5, 8) t.Put(1, 2, 4.0) t.Put(2, 2, -3.0) t.Put(3, 2, 1.0) t.Put(4, 2, 2.0) t.Put(2, 3, 2.0) t.Put(1, 4, 6.0) t.Put(4, 4, 0.5) t.Put(4, 4, 0.5) b[1] = 5.0 b[2] = -4.5 b[3] = 3.0 b[4] = 19.0 } default: chk.Panic("this test needs 1 or 2 procs") } x_correct := []float64{1, 2, 3, 4, 5} sum_b_to_root := true la.RunMumpsTestR(&t, 1e-14, b, x_correct, sum_b_to_root) }
func main() { mpi.Start(false) defer func() { mpi.Stop(false) }() if mpi.Rank() == 0 { chk.PrintTitle("ode04: Hairer-Wanner VII-p376 Transistor Amplifier\n") } if mpi.Size() != 3 { chk.Panic(">> error: this test requires 3 MPI processors\n") return } // data UE, UB, UF, ALPHA, BETA := 0.1, 6.0, 0.026, 0.99, 1.0e-6 R0, R1, R2, R3, R4, R5 := 1000.0, 9000.0, 9000.0, 9000.0, 9000.0, 9000.0 R6, R7, R8, R9 := 9000.0, 9000.0, 9000.0, 9000.0 W := 2.0 * 3.141592654 * 100.0 // initial values xa := 0.0 ya := []float64{0.0, UB, UB / (R6/R5 + 1.0), UB / (R6/R5 + 1.0), UB, UB / (R2/R1 + 1.0), UB / (R2/R1 + 1.0), 0.0} // endpoint of integration xb := 0.05 //xb = 0.0123 // OK //xb = 0.01235 // !OK // right-hand side of the amplifier problem w := make([]float64, 8) // workspace fcn := func(f []float64, dx, x float64, y []float64, args ...interface{}) error { UET := UE * math.Sin(W*x) FAC1 := BETA * (math.Exp((y[3]-y[2])/UF) - 1.0) FAC2 := BETA * (math.Exp((y[6]-y[5])/UF) - 1.0) la.VecFill(f, 0) switch mpi.Rank() { case 0: f[0] = y[0] / R9 case 1: f[1] = (y[1]-UB)/R8 + ALPHA*FAC1 f[2] = y[2]/R7 - FAC1 case 2: f[3] = y[3]/R5 + (y[3]-UB)/R6 + (1.0-ALPHA)*FAC1 f[4] = (y[4]-UB)/R4 + ALPHA*FAC2 f[5] = y[5]/R3 - FAC2 f[6] = y[6]/R1 + (y[6]-UB)/R2 + (1.0-ALPHA)*FAC2 f[7] = (y[7] - UET) / R0 } mpi.AllReduceSum(f, w) return nil } // Jacobian of the amplifier problem jac := func(dfdy *la.Triplet, dx, x float64, y []float64, args ...interface{}) error { FAC14 := BETA * math.Exp((y[3]-y[2])/UF) / UF FAC27 := BETA * math.Exp((y[6]-y[5])/UF) / UF if dfdy.Max() == 0 { dfdy.Init(8, 8, 16) } NU := 2 dfdy.Start() switch mpi.Rank() { case 0: dfdy.Put(2+0-NU, 0, 1.0/R9) dfdy.Put(2+1-NU, 1, 1.0/R8) dfdy.Put(1+2-NU, 2, -ALPHA*FAC14) dfdy.Put(0+3-NU, 3, ALPHA*FAC14) dfdy.Put(2+2-NU, 2, 1.0/R7+FAC14) case 1: dfdy.Put(1+3-NU, 3, -FAC14) dfdy.Put(2+3-NU, 3, 1.0/R5+1.0/R6+(1.0-ALPHA)*FAC14) dfdy.Put(3+2-NU, 2, -(1.0-ALPHA)*FAC14) dfdy.Put(2+4-NU, 4, 1.0/R4) dfdy.Put(1+5-NU, 5, -ALPHA*FAC27) case 2: dfdy.Put(0+6-NU, 6, ALPHA*FAC27) dfdy.Put(2+5-NU, 5, 1.0/R3+FAC27) dfdy.Put(1+6-NU, 6, -FAC27) dfdy.Put(2+6-NU, 6, 1.0/R1+1.0/R2+(1.0-ALPHA)*FAC27) dfdy.Put(3+5-NU, 5, -(1.0-ALPHA)*FAC27) dfdy.Put(2+7-NU, 7, 1.0/R0) } return nil } // matrix "M" c1, c2, c3, c4, c5 := 1.0e-6, 2.0e-6, 3.0e-6, 4.0e-6, 5.0e-6 var M la.Triplet M.Init(8, 8, 14) M.Start() NU := 1 switch mpi.Rank() { case 0: M.Put(1+0-NU, 0, -c5) M.Put(0+1-NU, 1, c5) M.Put(2+0-NU, 0, c5) M.Put(1+1-NU, 1, -c5) M.Put(1+2-NU, 2, -c4) M.Put(1+3-NU, 3, -c3) case 1: M.Put(0+4-NU, 4, c3) M.Put(2+3-NU, 3, c3) M.Put(1+4-NU, 4, -c3) case 2: M.Put(1+5-NU, 5, -c2) M.Put(1+6-NU, 6, -c1) M.Put(0+7-NU, 7, c1) M.Put(2+6-NU, 6, c1) M.Put(1+7-NU, 7, -c1) } // flags silent := false fixstp := false //method := "Dopri5" method := "Radau5" ndim := len(ya) numjac := false // structure to hold numerical results res := ode.Results{Method: method} // ODE solver var osol ode.Solver osol.Pll = true // solve problem if numjac { osol.Init(method, ndim, fcn, nil, &M, ode.SimpleOutput, silent) } else { osol.Init(method, ndim, fcn, jac, &M, ode.SimpleOutput, silent) } osol.IniH = 1.0e-6 // initial step size // set tolerances atol, rtol := 1e-11, 1e-5 osol.SetTol(atol, rtol) // run t0 := time.Now() if fixstp { osol.Solve(ya, xa, xb, 0.01, fixstp, &res) } else { osol.Solve(ya, xa, xb, xb-xa, fixstp, &res) } // plot if mpi.Rank() == 0 { io.Pfmag("elapsed time = %v\n", time.Now().Sub(t0)) plt.SetForEps(2.0, 400) args := "'b-', marker='.', lw=1, clip_on=0" ode.Plot("/tmp/gosl/ode", "hwamplifier_mpi.eps", &res, nil, xa, xb, "", args, func() { _, T, err := io.ReadTable("data/radau5_hwamplifier.dat") if err != nil { chk.Panic("%v", err) } for j := 0; j < ndim; j++ { plt.Subplot(ndim+1, 1, j+1) plt.Plot(T["x"], T[io.Sf("y%d", j)], "'k+',label='reference',ms=10") } }) } }
func TestJacobian03(tst *testing.T) { //verbose() chk.PrintTitle("TestJacobian 03") // grid var g fdm.Grid2D //g.Init(1.0, 1.0, 4, 4) g.Init(1.0, 1.0, 6, 6) //g.Init(1.0, 1.0, 11, 11) // equations numbering var e fdm.Equations peq := utl.IntUnique(g.L, g.R, g.B, g.T) e.Init(g.N, peq) // K11 and K12 var K11, K12 la.Triplet fdm.InitK11andK12(&K11, &K12, &e) // assembly F1 := make([]float64, e.N1) fdm.Assemble(&K11, &K12, F1, nil, &g, &e) // prescribed values U2 := make([]float64, e.N2) for _, eq := range g.L { U2[e.FR2[eq]] = 50.0 } for _, eq := range g.R { U2[e.FR2[eq]] = 0.0 } for _, eq := range g.B { U2[e.FR2[eq]] = 0.0 } for _, eq := range g.T { U2[e.FR2[eq]] = 50.0 } // functions k11 := K11.ToMatrix(nil) k12 := K12.ToMatrix(nil) ffcn := func(fU1, U1 []float64) error { // K11*U1 + K12*U2 - F1 la.VecCopy(fU1, -1, F1) // fU1 := (-F1) la.SpMatVecMulAdd(fU1, 1, k11, U1) // fU1 += K11*U1 la.SpMatVecMulAdd(fU1, 1, k12, U2) // fU1 += K12*U2 return nil } Jfcn := func(dfU1dU1 *la.Triplet, U1 []float64) error { fdm.Assemble(dfU1dU1, &K12, F1, nil, &g, &e) return nil } U1 := make([]float64, e.N1) CompareJac(tst, ffcn, Jfcn, U1, 0.0075) print_jac := false if print_jac { W1 := make([]float64, e.N1) fU1 := make([]float64, e.N1) ffcn(fU1, U1) var Jnum la.Triplet Jnum.Init(e.N1, e.N1, e.N1*e.N1) Jacobian(&Jnum, ffcn, U1, fU1, W1) la.PrintMat("K11 ", K11.ToMatrix(nil).ToDense(), "%g ", false) la.PrintMat("Jnum", Jnum.ToMatrix(nil).ToDense(), "%g ", false) } test_ffcn := false if test_ffcn { Uc := []float64{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0, 25.0, 325.0 / 22.0, 100.0 / 11.0, 50.0 / 11.0, 0.0, 50.0, 775.0 / 22.0, 25.0, 375.0 / 22.0, 100.0 / 11.0, 0.0, 50.0, 450.0 / 11.0, 725.0 / 22.0, 25.0, 325.0 / 22.0, 0.0, 50.0, 500.0 / 11.0, 450.0 / 11.0, 775.0 / 22.0, 25.0, 0.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, } for i := 0; i < e.N1; i++ { U1[i] = Uc[e.RF1[i]] } fU1 := make([]float64, e.N1) min, max := la.VecMinMax(fU1) io.Pf("min/max fU1 = %v\n", min, max) } }
func Test_linipm01(tst *testing.T) { //verbose() chk.PrintTitle("linipm01") // linear programming problem // min -4*x0 - 5*x1 // s.t. 2*x0 + x1 ≤ 3 // x0 + 2*x1 ≤ 3 // x0,x1 ≥ 0 // standard: // 2*x0 + x1 + x2 = 3 // x0 + 2*x1 + x3 = 3 // x0,x1,x2,x3 ≥ 0 var T la.Triplet T.Init(2, 4, 6) T.Put(0, 0, 2.0) T.Put(0, 1, 1.0) T.Put(0, 2, 1.0) T.Put(1, 0, 1.0) T.Put(1, 1, 2.0) T.Put(1, 3, 1.0) Am := T.ToMatrix(nil) A := Am.ToDense() c := []float64{-4, -5, 0, 0} b := []float64{3, 3} // print LP la.PrintMat("A", A, "%6g", false) la.PrintVec("b", b, "%6g", false) la.PrintVec("c", c, "%6g", false) io.Pf("\n") // solve LP var ipm LinIpm defer ipm.Clean() ipm.Init(Am, b, c, nil) err := ipm.Solve(chk.Verbose) if err != nil { tst.Errorf("ipm failed:\n%v", err) return } // check io.Pf("\n") io.Pforan("x = %v\n", ipm.X) io.Pfcyan("λ = %v\n", ipm.L) io.Pforan("s = %v\n", ipm.S) x := ipm.X[:2] bres := make([]float64, 2) la.MatVecMul(bres, 1, A, x) io.Pforan("bres = %v\n", bres) chk.Vector(tst, "x", 1e-9, x, []float64{1, 1}) chk.Vector(tst, "A*x=b", 1e-8, bres, b) // plot if true && chk.Verbose { f := func(x []float64) float64 { return c[0]*x[0] + c[1]*x[1] } g := func(x []float64, i int) float64 { return A[i][0]*x[0] + A[i][1]*x[1] - b[i] } np := 41 vmin, vmax := []float64{-2.0, -2.0}, []float64{2.0, 2.0} PlotTwoVarsContour("/tmp/gosl", "test_linipm01", x, np, nil, true, vmin, vmax, f, func(x []float64) float64 { return g(x, 0) }, func(x []float64) float64 { return g(x, 1) }, ) } }