示例#1
0
func parabolaTestPoints() []vec.Vector {
	sk := 0.1 // small value of k
	ssk := sk / math.Sqrt(2)
	// unique point
	zero := vec.ZeroVector(3)
	// basis vectors
	xb := []float64{sk, 0.0, 0.0}
	yb := []float64{0.0, sk, 0.0}
	zb := []float64{0.0, 0.0, sk}
	xyb := []float64{ssk, ssk, 0.0}
	xzb := []float64{ssk, 0.0, ssk}
	yzb := []float64{0.0, ssk, ssk}
	basis := []vec.Vector{xb, yb, zb, xyb, xzb, yzb}
	// create points from basis
	numRadialPoints := 3
	points := []vec.Vector{zero}
	for _, v := range basis {
		for i := 1; i <= numRadialPoints; i++ {
			pt := vec.ZeroVector(len(v))
			copy(pt, v)
			pt.Mul(float64(i), &pt)
			points = append(points, pt)
		}
	}
	return points
}
示例#2
0
// Produce a a slice of vectors whose values cover each first Brillouin zone
// point once.
func bzPoints(L, d int) []vec.Vector {
	cachedL, okL := pointsCache[L]
	if okL {
		cachedD, okD := cachedL[d]
		if okD {
			return cachedD
		}
	} else {
		pointsCache[L] = make(map[int][]vec.Vector)
	}
	points := make([]vec.Vector, pow(L, d))
	// start is the minumum value of any component of a point
	start := -math.Pi
	// (finish - step) is the maximum value of any component of a point
	finish := -start
	// step is the separation between point components
	step := (finish - start) / float64(L)
	k := vec.ZeroVector(d)
	kIndex := make([]int, d)
	// set initial value for k
	for i := 0; i < d; i++ {
		k[i] = start
		kIndex[i] = 0
	}
	// iterate over Brillouin zone
	done := false
	for i := 0; !done; i++ {
		points[i] = vec.ZeroVector(len(k))
		copy(points[i], k)
		done = bzAdvance(k, kIndex, start, step, L, d)
	}
	pointsCache[L][d] = points
	return points
}
示例#3
0
func VectorSum(pointsPerSide, gridDim, fnDim int, fn BzVectorFunc) vec.Vector {
	c := vec.ZeroVector(fnDim)
	add := func(next vec.Vector, total *vec.Vector) {
		for i := 0; i < fnDim; i++ {
			x := (*total)[i]
			y := next[i] - c[i]
			t := x + y
			c[i] = (t - x) - y
			(*total)[i] = t
		}
	}
	start := vec.ZeroVector(fnDim)
	return bzVectorReduce(add, start, pointsPerSide, gridDim, fnDim, fn)
}
示例#4
0
// Convert v back to Go format.
func VecFromGSL(v *C.gsl_vector) vec.Vector {
	dim := int(v.size)
	u := vec.ZeroVector(dim)
	for i := 0; i < dim; i++ {
		u[i] = float64(C.gsl_vector_get(v, C.size_t(i)))
	}
	return u
}
示例#5
0
// Combine fns into one function, suitable for passing to MultiDim.
// All funcs passed in must have the same dimension.
func Combine(fns []Diffable) DiffSystem {
	NumFuncs := len(fns)
	Dimension := fns[0].Dimension
	// F(v) = \sum_i fns[i].F(v) e_i
	// (e_i is unit vector in i'th direction)
	F := func(v vec.Vector) (vec.Vector, error) {
		var err error
		ret := vec.ZeroVector(NumFuncs)
		for i := 0; i < NumFuncs; i++ {
			ret[i], err = fns[i].F(v)
			if err != nil {
				return ret, err
			}
		}
		return ret, nil
	}
	// Df(v) = \sum_i fns[i].Df(v)
	Df := func(v vec.Vector) ([]vec.Vector, error) {
		var err error
		ret := make([]vec.Vector, NumFuncs)
		for i := 0; i < NumFuncs; i++ {
			ret[i], err = fns[i].Df(v)
			if err != nil {
				return ret, err
			}
		}
		return ret, nil
	}
	Fdf := func(v vec.Vector) (vec.Vector, []vec.Vector, error) {
		var err error
		ret_f := vec.ZeroVector(NumFuncs)
		ret_df := make([]vec.Vector, NumFuncs)
		for i := 0; i < NumFuncs; i++ {
			ret_f[i], err = fns[i].F(v)
			if err != nil {
				return ret_f, ret_df, err
			}
			ret_df[i], err = fns[i].Df(v)
			if err != nil {
				return ret_f, ret_df, err
			}
		}
		return ret_f, ret_df, nil
	}
	return DiffSystem{F, Df, Fdf, NumFuncs, Dimension}
}
示例#6
0
func VectorAvg(pointsPerSide, gridDim, fnDim int, fn BzVectorFunc) vec.Vector {
	N := math.Pow(float64(pointsPerSide), float64(gridDim))
	sum := VectorSum(pointsPerSide, gridDim, fnDim, fn)
	avg := vec.ZeroVector(fnDim)
	for i := 0; i < fnDim; i++ {
		avg[i] = sum[i] / N
	}
	return avg
}
示例#7
0
func bzVectorReduce(combine bzVectorConsumer, start vec.Vector, L, d, fnDim int, fn BzVectorFunc) vec.Vector {
	points := bzPoints(L, d)
	total := start
	out := vec.ZeroVector(fnDim)
	for i := 0; i < len(points); i++ {
		k := points[i]
		fn(k, &out)
		combine(out, &total)
	}
	return total
}
示例#8
0
// Gradient of fn at v within tolerance epsabs. h is the initial step size.
func Gradient(fn vec.FnDim0, v vec.Vector, h, epsabs float64) (vec.Vector, error) {
	grad := vec.ZeroVector(len(v))
	// calculate derivative of fn w.r.t. each component of v
	for i := 0; i < len(v); i++ {
		deriv, err := Derivative(fn, v, i, h, epsabs)
		if err != nil {
			return grad, err
		}
		grad[i] = deriv
	}
	return grad, nil
}
示例#9
0
// Calculate Mu_b - (-Omega_+(0))
func AbsErrorMu_b(env *tempAll.Environment, variables []string) solve.Diffable {
	F := func(v vec.Vector) (float64, error) {
		if v.ContainsNaN() {
			fmt.Printf("got NaN in AbsErrorMu_b (v=%v)\n", v)
			return 0.0, errors.New("NaN in input")
		}
		env.Set(v, variables)
		zv := vec.ZeroVector(3)
		omega0, err := tempCrit.OmegaPlus(env, zv)
		if err != nil {
			return 0.0, err
		}
		lhs := env.Mu_b
		rhs := -omega0
		return lhs - rhs, nil
	}
	h := 1e-5
	epsabs := 1e-4
	return solve.SimpleDiffable(F, len(variables), h, epsabs)
}
示例#10
0
// Return a list of all k points surveyed by OmegaCoeffs().
func OmegaCoeffsPoints(numRadial int, sk float64) []vec.Vector {
	ssk := sk / math.Sqrt(2)
	// basis vectors
	xb := []float64{sk, 0.0, 0.0}
	yb := []float64{0.0, sk, 0.0}
	zb := []float64{0.0, 0.0, sk}
	xyb := []float64{ssk, ssk, 0.0}
	xzb := []float64{ssk, 0.0, ssk}
	yzb := []float64{0.0, ssk, ssk}
	basis := []vec.Vector{xb, yb, zb, xyb, xzb, yzb}
	// create points from basis
	points := []vec.Vector{}
	for _, v := range basis {
		for i := 1; i <= numRadial; i++ {
			pt := vec.ZeroVector(len(v))
			copy(pt, v)
			pt.Mul(float64(i), &pt)
			points = append(points, pt)
		}
	}
	return points
}
示例#11
0
// Return a vector with the fit parameters [a_x, a_y, b, mu_pair] to the
// given functions.
func omegaFitHelper(env *tempAll.Environment, fn OmegaFunc, points []vec.Vector) (vec.Vector, error) {
	// evaluate omega_+/-(k) at each point
	omegas := []float64{}
	Xs := []vec.Vector{}
	for _, q := range points {
		omega, err := fn(env, q)
		if err != nil {
			continue
		}
		X := vec.ZeroVector(4)
		X[0] = q[0] * q[0]
		X[1] = q[1] * q[1]
		X[2] = q[2] * q[2]
		X[3] = -1
		Xs = append(Xs, X)
		omegas = append(omegas, omega)
	}
	if len(omegas) < 3 {
		return nil, fmt.Errorf("not enough omega_+/- values can be found")
	}
	return fit.Linear(omegas, Xs), nil
}
示例#12
0
func TestFitParabolaLinear(t *testing.T) {
	epsAbs := 1e-9
	ax, ay, b, mu_b := 1.01, 0.99, 0.1, -0.01
	omegaGenerator := func(q vec.Vector) float64 {
		return ax*q[0]*q[0] + ay*q[1]*q[1] + b*q[2]*q[2] - mu_b
	}
	points := parabolaTestPoints()
	y := make([]float64, len(points))
	X := make([]vec.Vector, len(points))
	for i, q := range points {
		y[i] = omegaGenerator(q)
		X[i] = vec.ZeroVector(4)
		X[i][0] = q[0] * q[0]
		X[i][1] = q[1] * q[1]
		X[i][2] = q[2] * q[2]
		X[i][3] = -1
	}
	coeffs := Linear(y, X)
	if math.Abs(coeffs[0]-ax) > epsAbs || math.Abs(coeffs[1]-ay) > epsAbs || math.Abs(coeffs[2]-b) > epsAbs || math.Abs(coeffs[3]-mu_b) > epsAbs {
		t.Fatalf("unexpected coefficients; got %s, expected %s", coeffs, []float64{ax, ay, b, mu_b})
	}
}
示例#13
0
// Solve the (D1, Mu_h, Mu_b) system with Beta and x fixed.
func SolveD1Mu_hMu_b(env *tempAll.Environment, epsAbs, epsRel float64) (vec.Vector, error) {
	/*
		// fix pair coefficients
		if env.A == 0.0 && env.B == 0.0 && env.FixedPairCoeffs {
			D1, Mu_h, Mu_b, Beta, Be_field := env.D1, env.Mu_h, env.Mu_b, env.Beta, env.Be_field
			env.Mu_b = 0.0 // Mu_b is 0 at T_c
			env.Be_field = 0.0
			_, err := tempCrit.CritTempSolve(env, epsAbs, epsRel)
			if err != nil {
				return nil, err
			}
			omegaFit, err := tempCrit.OmegaFit(env, tempCrit.OmegaPlus)
			if err != nil {
				return nil, err
			}
			env.A, env.B = omegaFit[0], omegaFit[2]
			env.PairCoeffsReady = true
			// uncache env
			env.D1, env.Mu_h, env.Mu_b, env.Beta, env.Be_field = D1, Mu_h, Mu_b, Beta, Be_field
		}
	*/
	maxIters := 1000
	oldMu_b := env.Mu_b
	for i := 0; i < maxIters; i++ {
		// iterate D1/Mu_h
		solution, err := SolveD1Mu_h(env, epsAbs, epsRel)
		if err != nil {
			return nil, err
		}
		// iterate Mu_b
		Be_field := env.Be_field
		env.Be_field = 0.0
		zv := vec.ZeroVector(3)
		omega0, err := tempCrit.OmegaPlus(env, zv)
		//omegaFit, err := tempCrit.OmegaFit(env, tempCrit.OmegaPlus)
		if err != nil {
			return nil, err
		}
		env.Mu_b = -omega0
		env.Be_field = Be_field
		//A, Mub_eff := omegaFit[0], omegaFit[3]
		//env.Mu_b = -omega0 + 2.0 * env.Be_field * env.A
		//Mub_eff := omegaFit[3]
		//env.Mu_b = Mub_eff
		//fmt.Printf("iterating Mu_b: now %f, before %f\n", env.Mu_b, oldMu_b)
		// check if done
		if math.Abs(env.Mu_b-oldMu_b) < epsAbs || !env.IterateD1Mu_hMu_b {
			return []float64{solution[0], solution[1], env.Mu_b}, nil
		}
		oldMu_b = env.Mu_b
	}
	return []float64{0.0, 0.0, 0.0}, fmt.Errorf("failed to find D1/Mu_h/Mu_b solution for env=%s\n", env.String())
	/*
		system, start := D1Mu_hMu_bSystem(env)
		solution, err := solve.MultiDim(system, start, epsAbs, epsRel)
		if err != nil {
			return nil, err
		}
		return solution, nil
	*/
}