Exemple #1
0
// MatInvG returns the matrix inverse of 'a' in 'ai'. 'a' can be of any size,
// even non-square; in this case, the pseudo-inverse is returned
func MatInvG(ai, a [][]float64, tol float64) (err error) {
	if len(a) < 1 {
		return chk.Err(_matinvg_err1)
	}
	m, n := len(a), len(a[0])
	if m == n && m < 4 { // call simple function
		_, err = MatInv(ai, a, tol)
		return
	}
	am := MatToColMaj(a)
	ami := make([]float64, n*m) // column-major inverse matrix
	if m == n {                 // general matrix inverse
		status := C.lapack_square_inverse((*C.double)(unsafe.Pointer(&ami[0])), (C.long)(m), (*C.double)(unsafe.Pointer(&am[0])))
		if status != 0 {
			return chk.Err(_matinvg_err2, m, n, "lapack_square_inverse", status)
		}
	} else { // pseudo inverse
		status := C.lapack_pseudo_inverse((*C.double)(unsafe.Pointer(&ami[0])), (C.long)(m), (C.long)(n), (*C.double)(unsafe.Pointer(&am[0])), (C.double)(tol))
		if status != 0 {
			return chk.Err(_matinvg_err2, m, n, "lapack_pseudo_inverse", status)
		}
	}
	ColMajToMat(ai, ami)
	return
}
Exemple #2
0
// Init initialises the function
func (o *Halo) Init(prms Prms) (err error) {
	ndim := 2
	for _, p := range prms {
		if p.N == "zc" {
			ndim = 3
			break
		}
	}
	o.xc = make([]float64, ndim)
	e := prms.Connect(&o.r, "r", "halo function")
	e += prms.Connect(&o.xc[0], "xc", "halo function")
	e += prms.Connect(&o.xc[1], "yc", "halo function")
	if ndim == 3 {
		e += prms.Connect(&o.xc[2], "zc", "halo function")
	}
	if e != "" {
		err = chk.Err("%v\n", e)
		return
	}
	rtol := 1e-10
	if o.r < rtol {
		return chk.Err("halo: radius must be greater than %g", rtol)
	}
	return
}
Exemple #3
0
// SaveSol saves solution (o.Sol) to a file which name is set with tidx (time output index)
func (o Domain) SaveSol(tidx int, verbose bool) (err error) {

	// skip if root
	if o.Proc != 0 {
		return
	}

	// buffer and encoder
	var buf bytes.Buffer
	enc := GetEncoder(&buf, o.Sim.EncType)

	// encode Sol
	err = enc.Encode(o.Sol.T)
	if err != nil {
		return chk.Err("cannot encode Domain.Sol.T\n%v", err)
	}
	err = enc.Encode(o.Sol.Y)
	if err != nil {
		return chk.Err("cannot encode Domain.Sol.Y\n%v", err)
	}
	err = enc.Encode(o.Sol.Dydt)
	if err != nil {
		return chk.Err("cannot encode Domain.Sol.Dydt\n%v", err)
	}
	err = enc.Encode(o.Sol.D2ydt2)
	if err != nil {
		return chk.Err("cannot encode Domain.Sol.D2ydt2\n%v", err)
	}

	// save file
	fn := out_nod_path(o.Sim.DirOut, o.Sim.Key, o.Sim.EncType, tidx, o.Proc)
	return save_file(fn, &buf, verbose)
}
Exemple #4
0
// DeleteMany deletes users
func (o *Control) DeleteMany(w http.ResponseWriter, r *http.Request, datUser interface{}) (res *web.Results, err error) {

	// parse data
	if datUser == nil {
		err = chk.Err("user.Control.DeleteMany: invalid datUser = %v", datUser)
		return
	}
	user := datUser.(*User)

	// find users
	users, err := o.find(user, true)
	if err != nil {
		err = chk.Err("user.Control.DeleteMany: cannot find users with datUser = %v", datUser)
		return
	}

	// delete
	for _, c := range users {
		if c == nil {
			continue
		}
		err = o.collection.RemoveId(c.Id)
		if err != nil {
			chk.Err("user.Control.DeleteMany: cannot remove user = %v; err = %v", c, err)
			return
		}
	}
	return
}
Exemple #5
0
// Init initialises the model
func (o *RefDecSp1) Init(prms Prms) (err error) {

	// parameters
	e := prms.Connect(&o.β, "bet", "ref-dec-sp1 function")
	e += prms.Connect(&o.λ1, "lam1", "ref-dec-sp1 function")
	e += prms.Connect(&o.ya, "ya", "ref-dec-sp1 function")
	e += prms.Connect(&o.yb, "yb", "ref-dec-sp1 function")
	if e != "" {
		err = chk.Err("%v\n", e)
		return
	}

	// check
	if o.yb >= o.ya {
		return chk.Err("yb(%g) must be smaller than ya(%g)", o.yb, o.ya)
	}

	// constants
	o.c1 = o.β * o.λ1
	o.c2 = math.Exp(-o.β * o.ya)
	o.c3 = math.Exp(-o.β*o.yb) - o.c2
	o.c1timestmax = 400

	// check
	if math.IsInf(o.c2, 0) || math.IsInf(o.c3, 0) {
		return chk.Err("β*ya or β*yb is too large:\n β=%v, ya=%v, yb=%v\n c1=%v, c2=%v, c3=%v", o.β, o.ya, o.yb, o.c1, o.c2, o.c3)
	}
	return
}
Exemple #6
0
// CalcD computes D = dσ_new/dε_new (consistent)
func (o SmallElasticity) CalcD(D [][]float64, s *State) (err error) {
	if o.Pse {
		if o.Nsig != 4 {
			return chk.Err("for plane-stress analyses, D must be 4x4. nsig = %d is incorrect.\n", o.Nsig)
		}
		if o.Kgc != nil {
			return chk.Err("plane-stress analysis does not work with nonlinear K and G\n")
		}
		c := o.E / (1.0 - o.Nu*o.Nu)
		la.MatFill(D, 0)
		D[0][0] = c
		D[0][1] = c * o.Nu
		D[1][0] = c * o.Nu
		D[1][1] = c
		D[3][3] = c * (1.0 - o.Nu)
		return
	}
	if o.Kgc != nil {
		o.K, o.G = o.Kgc.Calc(s)
	}
	for i := 0; i < o.Nsig; i++ {
		for j := 0; j < o.Nsig; j++ {
			D[i][j] = o.K*tsr.Im[i]*tsr.Im[j] + 2*o.G*tsr.Psd[i][j]
		}
	}
	return
}
Exemple #7
0
// SolveC solves the linear Complex system A.x = b
//  NOTES:
//    1) sum_b_to_root is a flag for MUMPS; it tells Solve to sum the values in 'b' arrays to the root processor
func (o *LinSolMumps) SolveC(xR, xC, bR, bC []float64, sum_b_to_root bool) (err error) {

	// check
	if !o.cmplx {
		return chk.Err(_linsol_mumps_err11)
	}

	// start time
	if o.ton {
		o.tini = time.Now()
	}

	// message
	if o.verb {
		io.Pfgreen("\n . . . . . . . . . . . . . . LinSolMumps.SolveC . . . . . . . . . . . . . . . \n\n")
	}

	// MUMPS: set RHS in processor # 0
	if sum_b_to_root {
		mpi.SumToRoot(xR, bR)
		mpi.SumToRoot(xC, bC)
		// join complex values
		if mpi.Rank() == 0 {
			for i := 0; i < len(xR); i++ {
				o.xRC[i*2], o.xRC[i*2+1] = xR[i], xC[i]
			}
		}
	} else {
		// join complex values
		if mpi.Rank() == 0 {
			for i := 0; i < len(xR); i++ {
				o.xRC[i*2], o.xRC[i*2+1] = bR[i], bC[i]
			}
		}
	}

	// MUMPS: solve
	o.mz.job = 3      // solution code
	C.zmumps_c(&o.mz) // solve
	if o.mz.info[1-1] < 0 {
		return chk.Err(_linsol_mumps_err12, mumps_error(o.mz.info[1-1], o.mz.info[2-1]))
	}

	// MUMPS: split complex values
	if mpi.Rank() == 0 {
		for i := 0; i < len(xR); i++ {
			xR[i], xC[i] = o.xRC[i*2], o.xRC[i*2+1]
		}
	}

	// MUMPS: broadcast from root
	mpi.BcastFromRoot(xR)
	mpi.BcastFromRoot(xC)

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolMumps.Solve = %v\n", o.name, time.Now().Sub(o.tini))
	}
	return
}
Exemple #8
0
// SolveC solves the linear Complex system A.x = b
func (o *LinSolUmfpack) SolveC(xR, xC, bR, bC []float64, dummy bool) (err error) {

	// check
	if !o.cmplx {
		return chk.Err(_linsol_umfpack_err12)
	}

	// start time
	if o.ton {
		o.tini = time.Now()
	}

	// message
	if o.verb {
		io.Pfgreen("\n . . . . . . . . . . . . . . LinSolUmfpack.SolveC . . . . . . . . . . . . . . . \n\n")
	}

	// UMFPACK: pointers
	pxR := (*C.double)(unsafe.Pointer(&xR[0]))
	pxC := (*C.double)(unsafe.Pointer(&xC[0]))
	pbR := (*C.double)(unsafe.Pointer(&bR[0]))
	pbC := (*C.double)(unsafe.Pointer(&bC[0]))

	// UMFPACK: solve
	st := C.umfpack_zl_solve(C.UMFPACK_A, o.ap, o.ai, o.ax, o.az, pxR, pxC, pbR, pbC, o.unum, o.uctrl, nil)
	if st != C.UMFPACK_OK {
		chk.Err(_linsol_umfpack_err13, Uerr2Text[int(st)])
	}

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolUmfpack.Solve = %v\n", o.name, time.Now().Sub(o.tini))
	}
	return
}
Exemple #9
0
// SetInitial sets the initial state
func (o *Domain) SetInitial(stg *inp.Stage) (err error) {

	// check
	if len(stg.Initial.Fcns) != len(stg.Initial.Dofs) {
		return chk.Err("number of functions (fcns) must be equal to number of dofs for setting initial values. %d != %d", len(stg.Initial.Fcns), len(stg.Initial.Dofs))
	}

	// loop over functions
	for i, fname := range stg.Initial.Fcns {

		// get function
		fcn := o.Sim.Functions.Get(fname)
		if fcn == nil {
			return chk.Err("cannot get function named %q", fname)
		}

		// set nodes
		key := stg.Initial.Dofs[i]
		for _, nod := range o.Nodes {
			eq := nod.GetEq(key)
			if eq < 0 {
				return chk.Err("dof=%q cannot be found in node=%d for setting initial values", key, nod.Vert.Id)
			}
			o.Sol.Y[eq] = fcn.F(0, nod.Vert.C)
		}
	}
	return
}
Exemple #10
0
// Delete deletes one user
func (o *Control) Delete(w http.ResponseWriter, r *http.Request, datUser interface{}) (res *web.Results, err error) {

	// parse data
	if datUser == nil {
		err = chk.Err("user.Control.Delete: invalid datUser = %v", datUser)
		return
	}
	user := datUser.(*User)

	// find users
	users, err := o.find(user, false)
	if err != nil {
		err = chk.Err("user.Control.Delete: cannot find user with datUser = %v. err = %v", datUser, err)
		return
	}

	// check
	if users[0] == nil {
		chk.Err("user.Control.Delete: cannot find user to delete. datUser = %v", datUser)
		return
	}

	// delete
	err = o.collection.RemoveId(users[0].Id)
	if err != nil {
		chk.Err("user.Control.Delete: cannot remove user = %v; err = %v", users[0], err)
		return
	}
	return
}
Exemple #11
0
// get_porous_parameters extracts parameters based on region data
func get_porous_parameters(mdb *inp.MatDb, reg *inp.Region, ctag int) (RhoS0, nf0 float64, err error) {
	edat := reg.Etag2data(ctag)
	mat := mdb.Get(edat.Mat)
	if mat.Model != "group" {
		err = chk.Err("geost: material type describing layer must be 'group' with porous data")
		return
	}
	if matname, found := io.Keycode(mat.Extra, "p"); found {
		m := mdb.Get(matname)
		for _, p := range m.Prms {
			switch p.N {
			case "RhoS0":
				RhoS0 = p.V
			case "nf0":
				nf0 = p.V
			}
		}
	}
	if RhoS0 < 1e-7 {
		err = chk.Err("geost: initial density of solids RhoS0=%g is incorrect", RhoS0)
		return
	}
	if nf0 < 1e-7 {
		err = chk.Err("geost: initial porosity nf0=%g is incorrect", nf0)
	}
	return
}
Exemple #12
0
// Init initialises the function
func (o *Cdist) Init(prms Prms) (err error) {
	var xc, yc, zc float64
	is3d := false
	for _, p := range prms {
		switch p.N {
		case "xc":
			xc = p.V
		case "yc":
			yc = p.V
		case "zc":
			zc = p.V
			is3d = true
		case "r":
			o.r = p.V
		default:
			return chk.Err("cdist: parameter named %q is invalid", p.N)
		}
	}
	rtol := 1e-10
	if o.r < rtol {
		return chk.Err("cdist: radius must be greater than %g", rtol)
	}
	if is3d {
		o.xc = []float64{xc, yc, zc}
	} else {
		o.xc = []float64{xc, yc}
	}
	return
}
Exemple #13
0
// ReadSol reads Solution from a file which name is set with tidx (time output index)
func (o *Domain) ReadSol(dir, fnkey, enctype string, tidx int) (err error) {

	// open file
	fn := out_nod_path(dir, fnkey, enctype, tidx, 0) // 0 => reading always from proc # 0
	fil, err := os.Open(fn)
	if err != nil {
		return
	}
	defer func() { err = fil.Close() }()

	// get decoder
	dec := GetDecoder(fil, enctype)

	// decode Sol
	err = dec.Decode(&o.Sol.T)
	if err != nil {
		return chk.Err("cannot decode Domain.Sol.T\n%v", err)
	}
	err = dec.Decode(&o.Sol.Y)
	if err != nil {
		return chk.Err("cannot decode Domain.Sol.Y\n%v", err)
	}
	err = dec.Decode(&o.Sol.Dydt)
	if err != nil {
		return chk.Err("cannot decode Domain.Sol.Dydt\n%v", err)
	}
	err = dec.Decode(&o.Sol.D2ydt2)
	if err != nil {
		return chk.Err("cannot decode Domain.Sol.D2ydt2\n%v", err)
	}
	return
}
Exemple #14
0
// ReadIvs reads elements's internal values from a file which name is set with tidx (time output index)
func (o *Domain) ReadIvs(dir, fnkey, enctype string, tidx, proc int) (err error) {

	// open file
	fn := out_ele_path(dir, fnkey, enctype, tidx, proc)
	fil, err := os.Open(fn)
	if err != nil {
		return
	}
	defer func() { err = fil.Close() }()

	// decoder
	dec := GetDecoder(fil, enctype)

	// elements that are in file
	err = dec.Decode(&o.MyCids)
	if err != nil {
		return chk.Err("cannot decode elements ids:\n%v", err)
	}

	// decode internal variables
	for _, cid := range o.MyCids {
		elem := o.Cid2elem[cid]
		if elem == nil {
			return chk.Err("cannot find element with cid=%d", cid)
		}
		err = elem.Decode(dec)
		if err != nil {
			return chk.Err("cannot decode element:\n%v", err)
		}
	}
	return
}
Exemple #15
0
// Init initialises the model
func (o *RefDecSp1) Init(prms Prms) (err error) {

	// parameters
	for _, p := range prms {
		switch p.N {
		case "bet":
			o.β = p.V
		case "lam1":
			o.λ1 = p.V
		case "ya":
			o.ya = p.V
		case "yb":
			o.yb = p.V
		default:
			return chk.Err("ref-dec-sp1: parameter named %q is invalid", p.N)
		}
	}

	// check
	if o.yb >= o.ya {
		return chk.Err("yb(%g) must be smaller than ya(%g)", o.yb, o.ya)
	}

	// constants
	o.c1 = o.β * o.λ1
	o.c2 = math.Exp(-o.β * o.ya)
	o.c3 = math.Exp(-o.β*o.yb) - o.c2
	o.c1timestmax = 400

	// check
	if math.IsInf(o.c2, 0) || math.IsInf(o.c3, 0) {
		return chk.Err("β*ya or β*yb is too large:\n β=%v, ya=%v, yb=%v\n c1=%v, c2=%v, c3=%v", o.β, o.ya, o.yb, o.c1, o.c2, o.c3)
	}
	return
}
Exemple #16
0
// Append adds a new entry {x, id} to the bins structure
func (o *Bins) Append(x []float64, id int) (err error) {
	idx := o.CalcIdx(x)
	if idx < 0 {
		return chk.Err("point %v is out of range", x)
	}
	bin := o.FindBinByIndex(idx)
	if bin == nil {
		return chk.Err("bin index %v is out of range", idx)
	}
	entry := BinEntry{id, x}
	bin.Entries = append(bin.Entries, &entry)
	return
}
Exemple #17
0
// checkprm checks if parameter value is correct
func checkprm(name string, val, minval, maxval float64, usemin, usemax bool) (err error) {
	if usemin {
		if val < minval {
			return chk.Err("%q parameter: wrong value: %g < %g", name, val, minval)
		}
	}
	if usemax {
		if val > maxval {
			return chk.Err("%q parameter: wrong value: %g > %g", name, val, maxval)
		}
	}
	return
}
Exemple #18
0
// CalcΔεElast calculates Δε corresponding to an elastic loading with Δp and Δq
func CalcΔεElast(Δε []float64, K, G float64, Δp, Δq float64, axsym bool) (Δεv, Δεd float64, err error) {
	Δεv = -Δp / K
	Δεd = Δq / (3.0 * G)
	var Δεx, Δεy, Δεz float64
	if axsym { // axisymmetric
		compression := true
		if compression {
			Δεx = Δεv/3.0 + Δεd/2.0
			Δεy = Δεx
			Δεz = Δεv/3.0 - Δεd
		} else {
			Δεx = Δεv/3.0 - Δεd/2.0
			Δεy = Δεv/3.0 + Δεd
			Δεz = Δεx
		}
	} else { // plane-strain with Δεy = Δεx / 2
		c := 9.0 * Δεd * Δεd / (4.0 * Δεv * Δεv)
		α := 0.0
		if math.Abs(c-1.0) > 1e-15 {
			d := 3.0 * (4.0*c - 1.0)
			if d < 0.0 {
				return 0, 0, chk.Err("discriminant < 0:  c=%v  d=%v", c, d)
			}
			α1 := (1.0 + 2.0*c + math.Sqrt(d)) / (2.0 - 2.0*c)
			α2 := (1.0 + 2.0*c - math.Sqrt(d)) / (2.0 - 2.0*c)
			α = α1
			io.Pfyel("d, α1, α2 = %v, %v, %v\n", d, α1, α2)
		}
		io.Pfyel("c, α = %v, %v\n", c, α)
		Δεy = Δεv / (1.0 + α)
		Δεx = α * Δεy
		Δεz = 0
	}
	//io.Pfpink("Δp=%v, Δq=%v => Δεv=%v, Δεd=%v => Δεx=%v, Δεy=%v, Δεz=%v\n", Δp, Δq, Δεv, Δεd, Δεx, Δεy, Δεz)
	Δε[0] = Δεx
	Δε[1] = Δεy
	Δε[2] = Δεz
	Δε[3] = 0
	Δεv_ := tsr.M_εv(Δε)
	Δεd_ := tsr.M_εd(Δε)
	if math.Abs(Δεv-Δεv_) > 1e-15 {
		return 0, 0, chk.Err(_path_err09, Δεv, Δεv_)
	}
	if Δεd < 0 {
		Δεd_ = -Δεd_ // allow negative values
	}
	if math.Abs(Δεd-Δεd_) > 1e-15 {
		return 0, 0, chk.Err(_path_err10, Δεd, Δεd_)
	}
	return
}
Exemple #19
0
// Init initialises this structure
func (o *SmallElasticity) Init(ndim int, pstress bool, prms fun.Prms) (err error) {
	o.Nsig = 2 * ndim
	o.Pse = pstress
	var has_E, has_ν, has_l, has_G, has_K bool
	for _, p := range prms {
		switch p.N {
		case "E":
			o.E, has_E = p.V, true
		case "nu":
			o.Nu, has_ν = p.V, true
		case "l":
			o.L, has_l = p.V, true
		case "G":
			o.G, has_G = p.V, true
		case "K":
			o.K, has_K = p.V, true
		}
		if skgc, found := io.Keycode(p.Extra, "kgc"); found {
			o.Kgc = GetKgc(skgc, prms)
			if o.Kgc == nil {
				return chk.Err("cannot find kgc model named %s", skgc)
			}
			err = o.Kgc.Init(prms)
			if err != nil {
				return
			}
		}
	}
	switch {
	case has_E && has_ν:
		o.L = Calc_l_from_Enu(o.E, o.Nu)
		o.G = Calc_G_from_Enu(o.E, o.Nu)
		o.K = Calc_K_from_Enu(o.E, o.Nu)
	case has_l && has_G:
		o.E = Calc_E_from_lG(o.L, o.G)
		o.Nu = Calc_nu_from_lG(o.L, o.G)
		o.K = Calc_K_from_lG(o.L, o.G)
	case has_K && has_G:
		o.E = Calc_E_from_KG(o.K, o.G)
		o.Nu = Calc_nu_from_KG(o.K, o.G)
		o.L = Calc_l_from_KG(o.K, o.G)
	case has_K && has_ν:
		o.E = Calc_E_from_Knu(o.K, o.Nu)
		o.G = Calc_G_from_Knu(o.K, o.Nu)
		o.L = Calc_l_from_Knu(o.K, o.Nu)
	default:
		return chk.Err("combination of Elastic constants is incorrect. options are {E,nu}, {l,G}, {K,G} and {K,nu}\n")
	}
	return
}
Exemple #20
0
// SetIniStress sets the initial state with initial stresses
func (o *Domain) SetIniStress(stg *inp.Stage) (err error) {

	// set elements with homogeneous stress state
	dat := stg.IniStress
	if dat.Hom {

		// isotropic state
		if dat.Iso {
			for _, e := range o.ElemIntvars {

				// build map with isotropic and homogeneus state
				coords := e.Ipoints()
				nip := len(coords)
				v := utl.DblVals(nip, dat.S0)
				ivs := map[string][]float64{"sx": v, "sy": v, "sz": v}

				// set element's states
				err = e.SetIniIvs(o.Sol, ivs)
				if err != nil {
					return chk.Err("homogeneous/isotropic: element's internal values setting failed:\n%v", err)
				}
			}
			return
		}

		// plane-strain state
		if dat.Psa {
			sz := dat.Nu * (dat.Sh + dat.Sv)
			for _, e := range o.ElemIntvars {

				// build map with plane-strain and homogeneus state
				coords := e.Ipoints()
				nip := len(coords)
				vx := utl.DblVals(nip, dat.Sh)
				vy := utl.DblVals(nip, dat.Sv)
				vz := utl.DblVals(nip, sz)
				ivs := map[string][]float64{"sx": vx, "sy": vy, "sz": vz}

				// set element's states
				err = e.SetIniIvs(o.Sol, ivs)
				if err != nil {
					return chk.Err("homogeneous/plane-strain: element's internal values setting failed:\n%v", err)
				}
			}
			return
		}
	}
	return
}
Exemple #21
0
// SetOrdScal sets the ordering and scaling methods for MUMPS
func (o *LinSolMumps) SetOrdScal(ordering, scaling string) (err error) {
	var ord, sca int
	if ordering == "" {
		ordering = "amf"
	}
	switch ordering {
	case "amd":
		ord = 0
	case "amf":
		ord = 2
	case "scotch":
		ord = 3
	case "pord":
		ord = 4
	case "metis":
		ord = 5
	case "qamd":
		ord = 6
	case "auto":
		ord = 7
	default:
		return chk.Err(_linsol_mumps_err13, ordering)
	}
	if scaling == "" {
		scaling = "rcit"
	}
	switch scaling {
	case "no":
		sca = 0 // no scaling
	case "diag":
		sca = 1 // diagonal scaling
	case "rcit":
		sca = 7 // row/col iterative
	case "rrcit":
		sca = 8 // rigorous row/col it
	case "auto":
		sca = 77 // automatic
	default:
		return chk.Err(_linsol_mumps_err14, scaling)
	}
	if o.cmplx {
		o.mz.icntl[7-1] = C.int(ord) // ordering
		o.mz.icntl[8-1] = C.int(sca) // scaling
	} else {
		o.m.icntl[7-1] = C.int(ord) // ordering
		o.m.icntl[8-1] = C.int(sca) // scaling
	}
	return
}
Exemple #22
0
// MatSvd returns the singular value decomposition of a matrix such that:
//  Note:
//  a = u * s * v
//  u[m][m], s[n], vt[n][n] must be pre-allocated
func MatSvd(u [][]float64, s []float64, vt [][]float64, a [][]float64, tol float64) (err error) {
	if len(a) < 1 {
		return chk.Err(_matinvg_err1)
	}
	m, n := len(a), len(a[0])
	um, vtm := make([]float64, m*m), make([]float64, n*n)
	am := MatToColMaj(a)
	status := C.lapack_svd((*C.double)(unsafe.Pointer(&um[0])), (*C.double)(unsafe.Pointer(&s[0])), (*C.double)(unsafe.Pointer(&vtm[0])), (C.long)(m), (C.long)(n), (*C.double)(unsafe.Pointer(&am[0])))
	if status != 0 {
		return chk.Err(_matinvg_err3, m, n, "lapack_svd", status)
	}
	ColMajToMat(u, um)
	ColMajToMat(vt, vtm)
	return
}
Exemple #23
0
// Init initialises distributions in Variables
func (o *Variables) Init() (err error) {
	for _, d := range *o {
		d.Distr, err = GetDistrib(d.D)
		if err != nil {
			chk.Err("cannot find distribution:\n%v", err)
			return
		}
		err = d.Distr.Init(d)
		if err != nil {
			chk.Err("cannot initialise variables:\n%v", err)
			return
		}
	}
	return
}
Exemple #24
0
// SolveR solves the linear Real system A.x = b
//  NOTES:
//    1) sum_b_to_root is a flag for MUMPS; it tells Solve to sum the values in 'b' arrays to the root processor
func (o *LinSolMumps) SolveR(xR, bR []float64, sum_b_to_root bool) (err error) {

	// check
	if !o.is_initialised {
		return chk.Err("linear solver must be initialised first\n")
	}
	if o.cmplx {
		return chk.Err(_linsol_mumps_err09)
	}

	// start time
	if o.ton {
		o.tini = time.Now()
	}

	// message
	if o.verb {
		io.Pfgreen("\n . . . . . . . . . . . . . . LinSolMumps.SolveR . . . . . . . . . . . . . . . \n\n")
	}

	// MUMPS: set RHS in processor # 0
	if sum_b_to_root {
		mpi.SumToRoot(xR, bR)
	} else {
		if mpi.Rank() == 0 {
			copy(xR, bR) // x := b
		}
	}

	// only proc # 0 needs the RHS
	if mpi.Rank() == 0 {
		o.m.rhs = (*C.double)(unsafe.Pointer(&xR[0]))
	}

	// MUMPS: solve
	o.m.job = 3      // solution code
	C.dmumps_c(&o.m) // solve
	if o.m.info[1-1] < 0 {
		return chk.Err(_linsol_mumps_err10, mumps_error(o.m.info[1-1], o.m.info[2-1]))
	}
	mpi.BcastFromRoot(xR) // broadcast from root

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolMumps.Solve = %v\n", o.name, time.Now().Sub(o.tini))
	}
	return
}
Exemple #25
0
// InitC initialises a LinSolUmfpack data structure for Complex systems. It also performs some initial analyses.
func (o *LinSolUmfpack) InitC(tC *TripletC, symmetric, verbose, timing bool) (err error) {

	// check
	o.tC = tC
	if tC.pos == 0 {
		return chk.Err(_linsol_umfpack_err02)
	}

	// flags
	o.name = "umfpack"
	o.sym = symmetric
	o.cmplx = true
	o.verb = verbose
	o.ton = timing

	// start time
	if o.ton {
		o.tini = time.Now()
	}

	// check x and z
	if len(o.tC.x) != len(o.tC.i) || len(o.tC.z) != len(o.tC.i) {
		return chk.Err(_linsol_umfpack_err03, len(o.tC.x), len(o.tC.z), len(o.tC.i))
	}

	// pointers
	o.ti = (*C.LONG)(unsafe.Pointer(&o.tC.i[0]))
	o.tj = (*C.LONG)(unsafe.Pointer(&o.tC.j[0]))
	o.tx = (*C.double)(unsafe.Pointer(&o.tC.x[0]))
	o.tz = (*C.double)(unsafe.Pointer(&o.tC.z[0]))
	o.ap = (*C.LONG)(unsafe.Pointer(&make([]int, o.tC.n+1)[0]))
	o.ai = (*C.LONG)(unsafe.Pointer(&make([]int, o.tC.pos)[0]))
	o.ax = (*C.double)(unsafe.Pointer(&make([]float64, o.tC.pos)[0]))
	o.az = (*C.double)(unsafe.Pointer(&make([]float64, o.tC.pos)[0]))

	// control
	o.uctrl = (*C.double)(unsafe.Pointer(&make([]float64, C.UMFPACK_CONTROL)[0]))
	C.umfpack_zl_defaults(o.uctrl)

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolUmfpack.InitC = %v\n", o.name, time.Now().Sub(o.tini))
	}

	// success
	o.is_initialised = true
	return
}
Exemple #26
0
// CalcDist computes distances beetween all vertices and initialises 'Next' matrix
func (o *Graph) CalcDist() (err error) {
	nv := len(o.Dist)
	for i := 0; i < nv; i++ {
		for j := 0; j < nv; j++ {
			if i == j {
				o.Dist[i][j] = 0
			} else {
				o.Dist[i][j] = GRAPH_INF
			}
			o.Next[i][j] = -1
		}
	}
	var d float64
	for k, edge := range o.Edges {
		i, j := edge[0], edge[1]
		d = 1.0
		if o.Verts != nil {
			d = 0.0
			xa, xb := o.Verts[i], o.Verts[j]
			for dim := 0; dim < len(xa); dim++ {
				d += math.Pow(xa[dim]-xb[dim], 2.0)
			}
			d = math.Sqrt(d)
		}
		if o.WeightsE != nil {
			d *= o.WeightsE[k]
		}
		o.Dist[i][j] = d
		o.Next[i][j] = j
		if o.Dist[i][j] < 0 {
			return chk.Err("distance between vertices cannot be negative: %g", o.Dist[i][j])
		}
	}
	return
}
Exemple #27
0
// SortQuadruples sorts i, x, y, and z by "i", "x", "y", or "z"
//  Note: either i, x, y, or z can be nil; i.e. at least one of them must be non nil
func SortQuadruples(i []int, x, y, z []float64, by string) (I []int, X, Y, Z []float64, err error) {
	q := BuildQuadruples(i, x, y, z)
	switch by {
	case "i":
		sort.Sort(QuadruplesByI{q})
	case "x":
		sort.Sort(QuadruplesByX{q})
	case "y":
		sort.Sort(QuadruplesByY{q})
	case "z":
		sort.Sort(QuadruplesByZ{q})
	default:
		return nil, nil, nil, nil, chk.Err("sort quadruples command must be 'i', 'x', 'y', or 'z'. by == '%s' is invalid", by)
	}
	if i != nil {
		I = q.I()
	}
	if x != nil {
		X = q.X()
	}
	if y != nil {
		Y = q.Y()
	}
	if z != nil {
		Z = q.Z()
	}
	return
}
Exemple #28
0
// GetDistrib returns a distribution from factory
func GetDistrib(dtype DistType) (d Distribution, err error) {
	allocator, ok := distallocators[dtype]
	if !ok {
		return nil, chk.Err("cannot find distribution: %+v", dtype)
	}
	return allocator(), nil
}
Exemple #29
0
// GenInvsDeriv1 computes the first order derivatives of p and q w.r.t L (shifted eigenvalues)
//  Note: L are the eigenvalues (shifted or not)
func GenInvsDeriv1(dpdL, dqdL []float64, L, n []float64, dndL [][]float64, a float64) (p, q float64, err error) {
	// invariants
	p = a * (L[0]*n[0]*n[0] + L[1]*n[1]*n[1] + L[2]*n[2]*n[2])
	d := L[0]*L[0]*n[0]*n[0] + L[1]*L[1]*n[1]*n[1] + L[2]*L[2]*n[2]*n[2] - p*p
	if d < 0 {
		if math.Abs(d) > SMPINVSTOL {
			err = chk.Err("difference==%g (>%g) is negative and cannot be used to computed q=sqrt(d). L=%v", d, SMPINVSTOL, L)
			return
		}
		d = 0
	}
	q = GENINVSQEPS + math.Sqrt(d)
	// derivatives
	var t_k, dtdL_ki float64
	for i := 0; i < 3; i++ {
		dpdL[i] = a * n[i] * n[i]
		dqdL[i] = 0
		for k := 0; k < 3; k++ {
			t_k = L[k] * n[k]
			dtdL_ki = L[k] * dndL[k][i]
			if k == i {
				dtdL_ki += n[k]
			}
			dpdL[i] += 2.0 * a * t_k * dndL[k][i]
			dqdL[i] += t_k * dtdL_ki
		}
		dqdL[i] = (dqdL[i] - p*dpdL[i]) / q
	}
	return
}
Exemple #30
0
// find finds users with given Id, Name, Email, Phone and Tag (in this order of preference)
// Note: empty user will return all users
func (o *Control) find(user *User, many bool) (users []*User, err error) {

	// search key
	var key bson.M
	switch {
	case user.Id != "":
		key = bson.M{"_id": user.Id}
	case user.Name != "":
		key = bson.M{"name": user.Name}
	case user.Email != "":
		key = bson.M{"email": user.Email}
	case user.Phone != "":
		key = bson.M{"phone": user.Phone}
	case user.Tag > 0:
		key = bson.M{"tag": user.Tag}
	}

	// search
	query := o.collection.Find(key).Sort("-timestamp")
	n, err := query.Count()
	if err != nil {
		return
	}
	if n < 1 {
		err = chk.Err("cannot find entry in database")
		return
	}
	if many {
		query.All(&users)
		return
	}
	users = []*User{&User{}}
	err = query.One(users[0])
	return
}