Beispiel #1
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *ElastRod) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return
}
Beispiel #2
0
/*  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
}
Beispiel #3
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *Rod) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {

	// zero K matrix
	la.MatFill(o.K, 0)
	la.MatFill(o.M, 0) // TODO: implement mass matrix

	// for each integration point
	var E float64
	nverts := o.Cell.Shp.Nverts
	for idx, ip := range o.IpsElem {

		// interpolation functions, gradients and variables @ ip
		err = o.ipvars(idx, sol)
		if err != nil {
			return
		}

		// auxiliary
		coef := ip[3]
		Jvec := o.Cell.Shp.Jvec3d
		G := o.Cell.Shp.Gvec
		J := o.Cell.Shp.J

		// add contribution to consistent tangent matrix
		for m := 0; m < nverts; m++ {
			for n := 0; n < nverts; n++ {
				for i := 0; i < o.Ndim; i++ {
					for j := 0; j < o.Ndim; j++ {
						r := i + m*o.Ndim
						c := j + n*o.Ndim
						E, err = o.Model.CalcD(o.States[idx], firstIt)
						if err != nil {
							return
						}
						o.K[r][c] += coef * o.A * E * G[m] * G[n] * Jvec[i] * Jvec[j] / J
					}
				}
			}
		}
	}

	// add K to sparse matrix Kb
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return
}
Beispiel #4
0
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},
		})
	}
}
Beispiel #5
0
// adds element K to global Jacobian matrix Kb
func (o Rod) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {

	// zero K matrix
	la.MatFill(o.K, 0)
	la.MatFill(o.M, 0)

	// for each integration point
	nverts := o.Shp.Nverts
	ndim := Global.Ndim
	for idx, ip := range o.IpsElem {

		// interpolation functions, gradients and variables @ ip
		if !o.ipvars(idx, sol) {
			return
		}

		// auxiliary
		coef := ip.W
		Jvec := o.Shp.Jvec3d
		G := o.Shp.Gvec
		J := o.Shp.J

		// add contribution to consistent tangent matrix
		for m := 0; m < nverts; m++ {
			for n := 0; n < nverts; n++ {
				for i := 0; i < ndim; i++ {
					for j := 0; j < ndim; j++ {
						r := i + m*ndim
						c := j + n*ndim
						E, err := o.Model.CalcD(o.States[idx], firstIt)
						if LogErr(err, "AddToKb") {
							return
						}
						o.K[r][c] += coef * o.A * E * G[m] * G[n] * Jvec[i] * Jvec[j] / J
					}
				}
			}
		}
	}

	// add K to sparse matrix Kb
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return true
}
Beispiel #6
0
// adds element K to global Jacobian matrix Kb
func (o Beam) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {
	if Global.Sim.Data.Steady {
		for i, I := range o.Umap {
			for j, J := range o.Umap {
				Kb.Put(I, J, o.K[i][j])
			}
		}
	} else {
		dc := Global.DynCoefs
		for i, I := range o.Umap {
			for j, J := range o.Umap {
				Kb.Put(I, J, o.M[i][j]*dc.α1+o.K[i][j])
			}
		}
	}
	return true
}
Beispiel #7
0
// adds element K to global Jacobian matrix Kb
func (o *Beam) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {
	if sol.Steady {
		for i, I := range o.Umap {
			for j, J := range o.Umap {
				Kb.Put(I, J, o.K[i][j])
			}
		}
		return
	}
	α1 := sol.DynCfs.α1
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.M[i][j]*α1+o.K[i][j])
		}
	}
	return
}
Beispiel #8
0
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)
}
Beispiel #9
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *ElemPhi) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {

	// auxiliary
	nverts := o.Cell.Shp.Nverts

	// zero K matrix
	la.MatFill(o.K, 0)
	dt := sol.Dt * 2

	// for each integration point
	for iip, ip := range o.IpsElem {

		// interpolation functions and gradients
		err = o.Cell.Shp.CalcAtIp(o.X, ip, true)
		if err != nil {
			return
		}

		// auxiliary variables
		coef := o.Cell.Shp.J * ip[3]
		S := o.Cell.Shp.S
		G := o.Cell.Shp.G

		// add to right hand side vector
		for m := 0; m < nverts; m++ {
			for n := 0; n < nverts; n++ {
				o.K[m][n] -= coef * (S[m]*S[n] + dt*dt/6.0*(o.v_0[iip][0]*G[m][0]+o.v_0[iip][1]*G[m][1])*(o.v_0[iip][0]*G[n][0]+o.v_0[iip][1]*G[n][1])) / dt
			}
		}
	}

	// add K to sparse matrix Kb
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return
}
Beispiel #10
0
func Assemble(K11, K12 *la.Triplet, F1 []float64, src Cb_src, g *Grid2D, e *Equations) {
	K11.Start()
	K12.Start()
	la.VecFill(F1, 0.0)
	kx, ky := 1.0, 1.0
	alp, bet, gam := 2.0*(kx/g.Dxx+ky/g.Dyy), -kx/g.Dxx, -ky/g.Dyy
	mol := []float64{alp, bet, bet, gam, gam}
	for i, I := range e.RF1 {
		col, row := I%g.Nx, I/g.Nx
		nodes := []int{I, I - 1, I + 1, I - g.Nx, I + g.Nx} // I, left, right, bottom, top
		if col == 0 {
			nodes[1] = nodes[2]
		}
		if col == g.Nx-1 {
			nodes[2] = nodes[1]
		}
		if row == 0 {
			nodes[3] = nodes[4]
		}
		if row == g.Ny-1 {
			nodes[4] = nodes[3]
		}
		for k, J := range nodes {
			j1, j2 := e.FR1[J], e.FR2[J] // 1 or 2?
			if j1 > -1 {                 // 11
				K11.Put(i, j1, mol[k])
			} else { // 12
				K12.Put(i, j2, mol[k])
			}
		}
		if src != nil {
			x := float64(col) * g.Dx
			y := float64(row) * g.Dy
			F1[i] += src(x, y)
		}
	}
}
Beispiel #11
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *ElemPhi) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {

	// auxiliary
	β1 := Global.DynCoefs.β1
	nverts := o.Shp.Nverts

	// zero K matrix
	la.MatFill(o.K, 0)

	// for each integration point
	for _, ip := range o.IpsElem {

		// interpolation functions and gradients
		if LogErr(o.Shp.CalcAtIp(o.X, ip, true), "InterpStarVars") {
			return
		}

		// auxiliary variables
		coef := o.Shp.J * ip.W
		S := o.Shp.S

		// add to right hand side vector
		for m := 0; m < nverts; m++ {
			for n := 0; n < nverts; n++ {
				o.K[m][n] += coef * S[m] * S[n] * β1
			}
		}
	}

	// add K to sparse matrix Kb
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return true
}
Beispiel #12
0
// 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
}
Beispiel #13
0
func IpBmatrix_sparse(B *la.Triplet, ndim, nne int, G [][]float64, radius float64, S []float64, axisym bool) {
	B.Start()
	if ndim == 3 {
		for i := 0; i < nne; i++ {
			B.Put(0, 0+i*3, G[i][0])
			B.Put(1, 1+i*3, G[i][1])
			B.Put(2, 2+i*3, G[i][2])
			B.Put(3, 0+i*3, G[i][1]/SQ2)
			B.Put(4, 1+i*3, G[i][2]/SQ2)
			B.Put(5, 2+i*3, G[i][0]/SQ2)
			B.Put(3, 1+i*3, G[i][0]/SQ2)
			B.Put(4, 2+i*3, G[i][1]/SQ2)
			B.Put(5, 0+i*3, G[i][2]/SQ2)
		}
		return
	}
	if axisym {
		for i := 0; i < nne; i++ {
			B.Put(0, 0+i*2, G[i][0])
			B.Put(1, 1+i*2, G[i][1])
			B.Put(2, 0+i*2, S[i]/radius)
			B.Put(3, 0+i*2, G[i][1]/SQ2)
			B.Put(3, 1+i*2, G[i][0]/SQ2)
		}
		return
	}
	for i := 0; i < nne; i++ {
		B.Put(0, 0+i*2, G[i][0])
		B.Put(1, 1+i*2, G[i][1])
		B.Put(3, 0+i*2, G[i][1]/SQ2)
		B.Put(3, 1+i*2, G[i][0]/SQ2)
	}
}
Beispiel #14
0
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)
}
Beispiel #15
0
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)
}
Beispiel #16
0
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))
	}
}
Beispiel #17
0
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) },
		)
	}
}
Beispiel #18
0
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) },
		)
	}
}
Beispiel #19
0
// contact_add_to_jac adds coupled equations due to contact modelling to Jacobian
func (o *ElemU) contact_add_to_jac(Kb *la.Triplet, sol *Solution) (err error) {

	// clear matrices
	for i := 0; i < o.Nq; i++ {
		for j := 0; j < o.Nq; j++ {
			o.Kqq[i][j] = 0
		}
		for j := 0; j < o.Nu; j++ {
			o.Kqu[i][j] = 0
			o.Kuq[j][i] = 0
		}
	}

	// compute surface integral
	var qb, db, Hb float64
	dddu := make([]float64, o.Ndim)
	for _, nbc := range o.NatBcs {

		// loop over ips of face
		for _, ipf := range o.IpsFace {

			// contact
			switch nbc.Key {
			case "contact":

				// interpolation functions and gradients @ face
				iface := nbc.IdxFace
				err = o.Cell.Shp.CalcAtFaceIp(o.X, ipf, iface)
				if err != nil {
					return
				}
				Sf := o.Cell.Shp.Sf
				nvec := o.Cell.Shp.Fnvec
				coef := ipf[3] * o.Thickness
				Jf := la.VecNorm(nvec)

				// variables extrapolated to face
				qb = o.fipvars(iface, sol)
				xf := o.Cell.Shp.FaceIpRealCoords(o.X, ipf, iface)
				la.VecAdd(xf, 1, o.us) // add displacement: x = X + u
				db = o.contact_g(xf)
				o.contact_dgdx(dddu, xf)

				// compute derivatives
				Hb = o.contact_rampD1(qb + o.κ*db)
				for i, m := range o.Cell.Shp.FaceLocalVerts[iface] {
					μ := o.Vid2contactId[m]
					for j, n := range o.Cell.Shp.FaceLocalVerts[iface] {
						ν := o.Vid2contactId[n]
						o.Kqq[μ][ν] += coef * Jf * Sf[i] * Sf[j] * (1.0 - Hb)
						for k := 0; k < o.Ndim; k++ {
							r := k + m*o.Ndim
							c := k + n*o.Ndim
							val := coef * Sf[i] * Sf[j] * Hb * o.κ * dddu[k] * Jf
							o.Kuq[r][ν] += coef * Sf[i] * Sf[j] * Hb * nvec[k]
							o.Kqu[μ][c] -= val
							o.K[r][c] += val
						}
					}
				}
			}
		}
	}

	// add Ks to sparse matrix Kb
	for i, I := range o.Qmap {
		for j, J := range o.Qmap {
			Kb.Put(I, J, o.Kqq[i][j])
		}
		for j, J := range o.Umap {
			Kb.Put(I, J, o.Kqu[i][j])
			Kb.Put(J, I, o.Kuq[j][i])
		}
	}
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return
}
Beispiel #20
0
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")
			}
		})
	}
}
Beispiel #21
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o ElemP) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {

	// clear matrices
	la.MatFill(o.Kpp, 0)
	ndim := Global.Ndim
	nverts := o.Shp.Nverts
	if o.DoExtrap {
		for i := 0; i < nverts; i++ {
			o.ρl_ex[i] = 0
			for j := 0; j < nverts; j++ {
				o.dρldpl_ex[i][j] = 0
			}
		}
	}

	// for each integration point
	Cl := o.Mdl.Cl
	β1 := Global.DynCoefs.β1
	var coef, plt, klr, ρL, ρl, Cpl, dCpldpl, dklrdpl float64
	for idx, ip := range o.IpsElem {

		// interpolation functions, gradients and variables @ ip
		if !o.ipvars(idx, sol) {
			return
		}
		coef = o.Shp.J * ip.W
		S := o.Shp.S
		G := o.Shp.G

		// tpm variables
		plt = β1*o.pl - o.ψl[idx]
		klr = o.Mdl.Cnd.Klr(o.States[idx].A_sl)
		ρL = o.States[idx].A_ρL
		if LogErr(o.Mdl.CalcLs(o.res, o.States[idx], o.pl, 0, true), "AddToKb") {
			return
		}
		ρl = o.res.A_ρl
		Cpl = o.res.Cpl
		dCpldpl = o.res.DCpldpl
		dklrdpl = o.res.Dklrdpl

		// Kpp := dRpl/dpl. see Eqs. (18), (A.2) and (A.3) of [1]
		for n := 0; n < nverts; n++ {
			for j := 0; j < ndim; j++ {
				o.tmp[j] = S[n]*dklrdpl*(ρL*o.g[j]-o.gpl[j]) + klr*(S[n]*Cl*o.g[j]-G[n][j])
			}
			for m := 0; m < nverts; m++ {
				o.Kpp[m][n] += coef * S[m] * S[n] * (dCpldpl*plt + β1*Cpl)
				for i := 0; i < ndim; i++ {
					for j := 0; j < ndim; j++ {
						o.Kpp[m][n] -= coef * G[m][i] * o.Mdl.Klsat[i][j] * o.tmp[j]
					}
				}
				if o.DoExtrap { // inner summation term in Eq. (22)
					o.dρldpl_ex[m][n] += o.Emat[m][idx] * Cpl * S[n]
				}
			}
			if o.DoExtrap { // Eq. (19)
				o.ρl_ex[n] += o.Emat[n][idx] * ρl
			}
		}
	}

	// add to Kb
	if o.HasSeep {

		// contribution from natural boundary conditions
		if !o.add_natbcs_to_jac(sol) {
			return
		}

		// add to sparse matrix Kb
		for i, I := range o.Pmap {
			for j, J := range o.Pmap {
				Kb.Put(I, J, o.Kpp[i][j])
			}
			for j, J := range o.Fmap {
				Kb.Put(I, J, o.Kpf[i][j])
				Kb.Put(J, I, o.Kfp[j][i])
			}
		}
		for i, I := range o.Fmap {
			for j, J := range o.Fmap {
				Kb.Put(I, J, o.Kff[i][j])
			}
		}

	} else {

		// add to sparse matrix Kb
		for i, I := range o.Pmap {
			for j, J := range o.Pmap {
				Kb.Put(I, J, o.Kpp[i][j])
			}
		}
	}
	return true
}
Beispiel #22
0
// adds element K to global Jacobian matrix Kb
func (o *Rjoint) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {

	// auxiliary
	rodH := o.Rod.Cell.Shp
	rodS := rodH.S
	rodNn := rodH.Nverts
	sldH := o.Sld.Cell.Shp
	sldNn := sldH.Nverts

	// zero K matrices
	for i, _ := range o.Rod.Umap {
		for j, _ := range o.Rod.Umap {
			o.Krr[i][j] = 0
		}
		for j, _ := range o.Sld.Umap {
			o.Krs[i][j] = 0
			o.Ksr[j][i] = 0
		}
	}
	la.MatFill(o.Kss, 0)

	// auxiliary
	var coef float64
	var DτDω float64
	var Dwb0Du_nj, Dwb1Du_nj, Dwb2Du_nj float64
	var DτDu_nj, DqbDu_nij float64
	var Dwb0Dur_nj, Dwb1Dur_nj, Dwb2Dur_nj float64
	var DqbDur_nij float64

	// loop over rod's integration points
	for idx, ip := range o.Rod.IpsElem {

		// auxiliary
		e0, e1, e2 := o.e0[idx], o.e1[idx], o.e2[idx]

		// interpolation functions and gradients
		err = rodH.CalcAtIp(o.Rod.X, ip, true)
		if err != nil {
			return
		}
		coef = ip[3] * rodH.J

		// model derivatives
		DτDω, err = o.Mdl.CalcD(o.States[idx], firstIt)
		if err != nil {
			return
		}

		// compute derivatives
		for j := 0; j < o.Ndim; j++ {

			// Krr and Ksr; derivatives with respect to ur_nj
			for n := 0; n < rodNn; n++ {

				// ∂wb/∂ur Eq (A.4)
				Dwb0Dur_nj = -rodS[n] * e0[j]
				Dwb1Dur_nj = -rodS[n] * e1[j]
				Dwb2Dur_nj = -rodS[n] * e2[j]

				// compute ∂■/∂ur derivatives
				c := j + n*o.Ndim
				for i := 0; i < o.Ndim; i++ {

					// ∂qb/∂ur Eq (A.2)
					DqbDur_nij = o.h*e0[i]*(DτDω*Dwb0Dur_nj) + o.k1*e1[i]*Dwb1Dur_nj + o.k2*e2[i]*Dwb2Dur_nj

					// Krr := ∂fr/∂ur Eq (58)
					for m := 0; m < rodNn; m++ {
						r := i + m*o.Ndim
						o.Krr[r][c] -= coef * rodS[m] * DqbDur_nij
					}

					//  Ksr := ∂fs/∂ur Eq (60)
					for m := 0; m < sldNn; m++ {
						r := i + m*o.Ndim
						for p := 0; p < rodNn; p++ {
							o.Ksr[r][c] += coef * o.Nmat[m][p] * rodS[p] * DqbDur_nij
						}
					}
				}
			}

			// Krs and Kss
			for n := 0; n < sldNn; n++ {

				// ∂wb/∂us Eq (A.5)
				Dwb0Du_nj, Dwb1Du_nj, Dwb2Du_nj = 0, 0, 0
				for m := 0; m < rodNn; m++ {
					Dwb0Du_nj += rodS[m] * o.Nmat[n][m] * e0[j]
					Dwb1Du_nj += rodS[m] * o.Nmat[n][m] * e1[j]
					Dwb2Du_nj += rodS[m] * o.Nmat[n][m] * e2[j]
				}

				// ∂τ/∂us_nj hightlighted term in Eq (A.3)
				DτDu_nj = DτDω * Dwb0Du_nj

				// compute ∂■/∂us derivatives
				c := j + n*o.Ndim
				for i := 0; i < o.Ndim; i++ {

					// ∂qb/∂us Eq (A.3)
					DqbDu_nij = o.h*e0[i]*DτDu_nj + o.k1*e1[i]*Dwb1Du_nj + o.k2*e2[i]*Dwb2Du_nj

					// Krs := ∂fr/∂us Eq (59)
					for m := 0; m < rodNn; m++ {
						r := i + m*o.Ndim
						o.Krs[r][c] -= coef * rodS[m] * DqbDu_nij
					}

					// Kss := ∂fs/∂us Eq (61)
					for m := 0; m < sldNn; m++ {
						r := i + m*o.Ndim
						for p := 0; p < rodNn; p++ {
							o.Kss[r][c] += coef * o.Nmat[m][p] * rodS[p] * DqbDu_nij
						}
					}
				}
			}
		}
	}

	// debug
	//if true {
	if false {
		o.debug_print_K()
	}

	// add K to sparse matrix Kb
	for i, I := range o.Rod.Umap {
		for j, J := range o.Rod.Umap {
			Kb.Put(I, J, o.Krr[i][j])
		}
		for j, J := range o.Sld.Umap {
			Kb.Put(I, J, o.Krs[i][j])
			Kb.Put(J, I, o.Ksr[j][i])
		}
	}
	for i, I := range o.Sld.Umap {
		for j, J := range o.Sld.Umap {
			Kb.Put(I, J, o.Kss[i][j])
		}
	}
	return
}
Beispiel #23
0
// adds element K to global Jacobian matrix Kb
func (o ElemUP) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {

	// clear matrices
	ndim := Global.Ndim
	u_nverts := o.U.Shp.Nverts
	p_nverts := o.P.Shp.Nverts
	la.MatFill(o.P.Kpp, 0)
	for i := 0; i < o.U.Nu; i++ {
		for j := 0; j < o.P.Np; j++ {
			o.Kup[i][j] = 0
			o.Kpu[j][i] = 0
		}
		for j := 0; j < o.U.Nu; j++ {
			o.U.K[i][j] = 0
		}
	}
	if o.P.DoExtrap {
		for i := 0; i < p_nverts; i++ {
			o.P.ρl_ex[i] = 0
			for j := 0; j < p_nverts; j++ {
				o.P.dρldpl_ex[i][j] = 0
			}
			for j := 0; j < o.U.Nu; j++ {
				o.dρldus_ex[i][j] = 0
			}
		}
	}

	// for each integration point
	dc := Global.DynCoefs
	var coef, plt, klr, ρL, Cl, divvs float64
	var ρl, ρ, Cpl, Cvs, dρdpl, dpdpl, dCpldpl, dCvsdpl, dklrdpl, dCpldusM, dρldusM, dρdusM float64
	var r, c int
	for idx, ip := range o.U.IpsElem {

		// interpolation functions, gradients and variables @ ip
		if !o.ipvars(idx, sol) {
			return
		}
		coef = o.U.Shp.J * ip.W
		S := o.U.Shp.S
		G := o.U.Shp.G
		Sb := o.P.Shp.S
		Gb := o.P.Shp.G

		// axisymmetric case
		radius := 1.0
		if Global.Sim.Data.Axisym {
			radius = o.U.Shp.AxisymGetRadius(o.U.X)
			coef *= radius
		}

		// auxiliary
		divvs = dc.α4*o.divus - o.U.divχs[idx] // divergence of Eq (35a) [1]

		// tpm variables
		plt = dc.β1*o.P.pl - o.P.ψl[idx] // Eq (35c) [1]
		klr = o.P.Mdl.Cnd.Klr(o.P.States[idx].A_sl)
		ρL = o.P.States[idx].A_ρL
		Cl = o.P.Mdl.Cl
		if LogErr(o.P.Mdl.CalcLs(o.P.res, o.P.States[idx], o.P.pl, o.divus, true), "AddToKb") {
			return
		}
		ρl = o.P.res.A_ρl
		ρ = o.P.res.A_ρ
		Cpl = o.P.res.Cpl
		Cvs = o.P.res.Cvs
		dρdpl = o.P.res.Dρdpl
		dpdpl = o.P.res.Dpdpl
		dCpldpl = o.P.res.DCpldpl
		dCvsdpl = o.P.res.DCvsdpl
		dklrdpl = o.P.res.Dklrdpl
		dCpldusM = o.P.res.DCpldusM
		dρldusM = o.P.res.DρldusM
		dρdusM = o.P.res.DρdusM

		// Kpu, Kup and Kpp
		for n := 0; n < p_nverts; n++ {
			for j := 0; j < ndim; j++ {

				// Kpu := ∂Rl^n/∂us^m and Kup := ∂Rus^m/∂pl^n; see Eq (47) of [1]
				for m := 0; m < u_nverts; m++ {
					c = j + m*ndim

					// add ∂rlb/∂us^m: Eqs (A.3) and (A.6) of [1]
					o.Kpu[n][c] += coef * Sb[n] * (dCpldusM*plt + dc.α4*Cvs) * G[m][j]

					// add ∂(ρl.wl)/∂us^m: Eq (A.8) of [1]
					for i := 0; i < ndim; i++ {
						o.Kpu[n][c] += coef * Gb[n][i] * S[m] * dc.α1 * ρL * klr * o.P.Mdl.Klsat[i][j]
					}

					// add ∂rl/∂pl^n and ∂p/∂pl^n: Eqs (A.9) and (A.11) of [1]
					o.Kup[c][n] += coef * (S[m]*Sb[n]*dρdpl*o.bs[j] - G[m][j]*Sb[n]*dpdpl)

					// for seepage face
					if o.P.DoExtrap {
						o.dρldus_ex[n][c] += o.P.Emat[n][idx] * dρldusM * G[m][j]
					}
				}

				// term in brackets in Eq (A.7) of [1]
				o.P.tmp[j] = Sb[n]*dklrdpl*o.hl[j] - klr*(Sb[n]*Cl*o.bs[j]+Gb[n][j])
			}

			// Kpp := ∂Rl^m/∂pl^n; see Eq (47) of [1]
			for m := 0; m < p_nverts; m++ {

				// add ∂rlb/dpl^n: Eq (A.5) of [1]
				o.P.Kpp[m][n] += coef * Sb[m] * Sb[n] * (dCpldpl*plt + dCvsdpl*divvs + dc.β1*Cpl)

				// add ∂(ρl.wl)/∂us^m: Eq (A.7) of [1]
				for i := 0; i < ndim; i++ {
					for j := 0; j < ndim; j++ {
						o.P.Kpp[m][n] -= coef * Gb[m][i] * o.P.Mdl.Klsat[i][j] * o.P.tmp[j]
					}
				}

				// inner summation term in Eq (22) of [2]
				if o.P.DoExtrap {
					o.P.dρldpl_ex[m][n] += o.P.Emat[m][idx] * Cpl * Sb[n]
				}
			}

			// Eq. (19) of [2]
			if o.P.DoExtrap {
				o.P.ρl_ex[n] += o.P.Emat[n][idx] * ρl
			}
		}

		// Kuu: add ∂rub^m/∂us^n; see Eqs (47) and (A.10) of [1]
		for m := 0; m < u_nverts; m++ {
			for i := 0; i < ndim; i++ {
				r = i + m*ndim
				for n := 0; n < u_nverts; n++ {
					for j := 0; j < ndim; j++ {
						c = j + n*ndim
						o.U.K[r][c] += coef * S[m] * (S[n]*dc.α1*ρ*tsr.It[i][j] + dρdusM*o.bs[i]*G[n][j])
					}
				}
			}
		}

		// consistent tangent model matrix
		if LogErr(o.U.MdlSmall.CalcD(o.U.D, o.U.States[idx], firstIt), "AddToKb") {
			return
		}

		// Kuu: add stiffness term ∂(σe・G^m)/∂us^n
		if o.U.UseB {
			IpBmatrix(o.U.B, ndim, u_nverts, G, radius, S)
			la.MatTrMulAdd3(o.U.K, coef, o.U.B, o.U.D, o.U.B) // K += coef * tr(B) * D * B
		} else {
			IpAddToKt(o.U.K, u_nverts, ndim, coef, G, o.U.D)
		}
	}

	// contribution from natural boundary conditions
	if o.P.HasSeep {
		if !o.P.add_natbcs_to_jac(sol) {
			return
		}
		if !o.add_natbcs_to_jac(sol) {
			return
		}
	}

	// add K to sparse matrix Kb
	//    _             _
	//   |  Kuu Kup  0   |
	//   |  Kpu Kpp Kpf  |
	//   |_ Kfu Kfp Kff _|
	//
	for i, I := range o.P.Pmap {
		for j, J := range o.P.Pmap {
			Kb.Put(I, J, o.P.Kpp[i][j])
		}
		for j, J := range o.P.Fmap {
			Kb.Put(I, J, o.P.Kpf[i][j])
			Kb.Put(J, I, o.P.Kfp[j][i])
		}
		for j, J := range o.U.Umap {
			Kb.Put(I, J, o.Kpu[i][j])
			Kb.Put(J, I, o.Kup[j][i])
		}
	}
	for i, I := range o.P.Fmap {
		for j, J := range o.P.Fmap {
			Kb.Put(I, J, o.P.Kff[i][j])
		}
	}
	for i, I := range o.U.Umap {
		for j, J := range o.U.Umap {
			Kb.Put(I, J, o.U.K[i][j])
		}
	}
	return true
}
Beispiel #24
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *ElemU) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (ok bool) {

	// zero K matrix
	la.MatFill(o.K, 0)

	// for each integration point
	dc := Global.DynCoefs
	ndim := Global.Ndim
	nverts := o.Shp.Nverts
	for idx, ip := range o.IpsElem {

		// interpolation functions, gradients and variables @ ip
		if !o.ipvars(idx, sol) {
			return
		}

		// check Jacobian
		if o.Shp.J < 0 {
			LogErrCond(true, "ElemU: eid=%d: Jacobian is negative = %g\n", o.Id(), o.Shp.J)
			return
		}

		// auxiliary
		coef := o.Shp.J * ip.W * o.Thickness
		S := o.Shp.S
		G := o.Shp.G

		// consistent tangent model matrix
		if LogErr(o.MdlSmall.CalcD(o.D, o.States[idx], firstIt), "AddToKb") {
			return
		}

		// add contribution to consistent tangent matrix
		if o.UseB {
			radius := 1.0
			if Global.Sim.Data.Axisym {
				radius = o.Shp.AxisymGetRadius(o.X)
				coef *= radius
			}
			IpBmatrix(o.B, ndim, nverts, G, radius, S)
			la.MatTrMulAdd3(o.K, coef, o.B, o.D, o.B) // K += coef * tr(B) * D * B
		} else {
			IpAddToKt(o.K, nverts, ndim, coef, G, o.D)
		}

		// dynamic term
		if !Global.Sim.Data.Steady {
			for m := 0; m < nverts; m++ {
				for i := 0; i < ndim; i++ {
					r := i + m*ndim
					for n := 0; n < nverts; n++ {
						c := i + n*ndim
						o.K[r][c] += coef * S[m] * S[n] * (o.Rho*dc.α1 + o.Cdam*dc.α4)
					}
				}
			}
		}
	}

	// add K to sparse matrix Kb
	for i, I := range o.Umap {
		for j, J := range o.Umap {
			Kb.Put(I, J, o.K[i][j])
		}
	}
	return true
}
Beispiel #25
0
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)
}
Beispiel #26
0
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)
}
Beispiel #27
0
// AddToKb adds element K to global Jacobian matrix Kb
func (o *ElemU) AddToKb(Kb *la.Triplet, sol *Solution, firstIt bool) (err error) {

	// zero K matrix
	la.MatFill(o.K, 0)

	// for each integration point
	nverts := o.Cell.Shp.Nverts
	for idx, ip := range o.IpsElem {

		// interpolation functions, gradients and variables @ ip
		err = o.ipvars(idx, sol)
		if err != nil {
			return
		}

		// check Jacobian
		if o.Cell.Shp.J < 0 {
			return chk.Err("ElemU: eid=%d: Jacobian is negative = %g\n", o.Id(), o.Cell.Shp.J)
		}

		// auxiliary
		coef := o.Cell.Shp.J * ip[3] * o.Thickness
		S := o.Cell.Shp.S
		G := o.Cell.Shp.G

		// consistent tangent model matrix
		err = o.MdlSmall.CalcD(o.D, o.States[idx], firstIt)
		if err != nil {
			return
		}

		// add contribution to consistent tangent matrix
		if o.UseB {
			radius := 1.0
			if sol.Axisym {
				radius = o.Cell.Shp.AxisymGetRadius(o.X)
				coef *= radius
			}
			IpBmatrix(o.B, o.Ndim, nverts, G, radius, S, sol.Axisym)
			la.MatTrMulAdd3(o.K, coef, o.B, o.D, o.B) // K += coef * tr(B) * D * B
		} else {
			IpAddToKt(o.K, nverts, o.Ndim, coef, G, o.D)
		}

		// dynamic term
		if !sol.Steady {
			α1 := sol.DynCfs.α1
			α4 := sol.DynCfs.α4
			for m := 0; m < nverts; m++ {
				for i := 0; i < o.Ndim; i++ {
					r := i + m*o.Ndim
					for n := 0; n < nverts; n++ {
						c := i + n*o.Ndim
						o.K[r][c] += coef * S[m] * S[n] * (o.Rho*α1 + o.Cdam*α4)
					}
				}
			}
		}
	}

	// add Ks to sparse matrix Kb
	switch {

	case o.HasContact:
		err = o.contact_add_to_jac(Kb, sol)

	case o.Xfem:
		err = o.xfem_add_to_jac(Kb, sol)

	default:
		for i, I := range o.Umap {
			for j, J := range o.Umap {
				Kb.Put(I, J, o.K[i][j])
			}
		}
	}
	return
}