Beispiel #1
0
// Clean deletes temporary data structures
func (o *LinSolMumps) Clean() {

	// exit if not initialised
	if !o.is_initialised {
		return
	}

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

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

	// clean up
	if o.cmplx {
		o.mz.job = -2     // finalize code
		C.zmumps_c(&o.mz) // do finalize
	} else {
		o.m.job = -2     // finalize code
		C.dmumps_c(&o.m) // do finalize
	}

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolMumps.Clean   = %v\n", o.name, time.Now().Sub(o.tini))
	}
}
Beispiel #2
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
}
Beispiel #3
0
// Fact performs symbolic/numeric factorisation. This method also converts the triplet form
// to the column-compressed form, including the summation of duplicated entries
func (o *LinSolMumps) Fact() (err error) {

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

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

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

	// complex
	if o.cmplx {

		// MUMPS: factorisation
		o.mz.job = 2      // factorisation code
		C.zmumps_c(&o.mz) // factorise
		if o.mz.info[1-1] < 0 {
			return chk.Err(_linsol_mumps_err08, "Real", mumps_error(o.mz.info[1-1], o.mz.info[2-1]))
		}

		// real
	} else {

		// MUMPS: factorisation
		o.m.job = 2      // factorisation code
		C.dmumps_c(&o.m) // factorise
		if o.m.info[1-1] < 0 {
			return chk.Err(_linsol_mumps_err08, "Complex", mumps_error(o.m.info[1-1], o.m.info[2-1]))
		}
	}

	// duration
	if o.ton {
		io.Pfcyan("%s: Time spent in LinSolMumps.Fact  = %v\n", o.name, time.Now().Sub(o.tini))
	}
	return
}
Beispiel #4
0
// InitR initialises a LinSolMumps data structure for Real systems. It also performs some initial analyses.
func (o *LinSolMumps) InitR(tR *Triplet, symmetric, verbose, timing bool) (err error) {

	// check
	o.tR = tR
	if tR.pos == 0 {
		return chk.Err(_linsol_mumps_err01)
	}

	// flags
	o.name = "mumps"
	o.sym = symmetric
	o.cmplx = false
	o.verb = verbose
	o.ton = timing

	// start time
	if mpi.Rank() != 0 {
		o.verb = false
		o.ton = false
	}
	if o.ton {
		o.tini = time.Now()
	}

	// initialise Mumps
	o.m.comm_fortran = -987654 // use Fortran communicator by default
	o.m.par = 1                // host also works
	o.m.sym = 0                // 0=unsymmetric, 1=sym(pos-def), 2=symmetric(undef)
	if symmetric {
		o.m.sym = 2
	}
	o.m.job = -1     // initialisation code
	C.dmumps_c(&o.m) // initialise
	if o.m.info[1-1] < 0 {
		return chk.Err(_linsol_mumps_err02, mumps_error(o.m.info[1-1], o.m.info[2-1]))
	}

	// convert indices to C.int (not C.long) and
	// increment indices since Mumps is 1-based (FORTRAN)
	o.mi, o.mj = make([]int32, o.tR.pos), make([]int32, o.tR.pos)
	for k := 0; k < tR.pos; k++ {
		o.mi[k] = int32(o.tR.i[k]) + 1
		o.mj[k] = int32(o.tR.j[k]) + 1
	}

	// set pointers
	o.m.n = C.int(o.tR.m)
	o.m.nz_loc = C.int(o.tR.pos)
	o.m.irn_loc = (*C.int)(unsafe.Pointer(&o.mi[0]))
	o.m.jcn_loc = (*C.int)(unsafe.Pointer(&o.mj[0]))
	o.m.a_loc = (*C.double)(unsafe.Pointer(&o.tR.x[0]))

	// control
	if verbose {
		if mpi.Rank() == 0 {
			io.Pfgreen("\n . . . . . . . . . . . . . . LinSolMumps.InitR . . (MUMPS) . . . . . . . . . \n\n")
		}
		o.m.icntl[1-1] = 6 // output stream for error messages
		o.m.icntl[2-1] = 0 // output stream for statistics and warnings
		o.m.icntl[3-1] = 6 // output stream for global information
		o.m.icntl[4-1] = 2 // message level: 2==errors and warnings
	} else {
		o.m.icntl[1-1] = -1 // no output messages
		o.m.icntl[2-1] = -1 // no warnings
		o.m.icntl[3-1] = -1 // no global information
		o.m.icntl[4-1] = -1 // message level
	}
	o.m.icntl[5-1] = 0     // assembled matrix (needed for distributed matrix)
	o.m.icntl[6-1] = 7     // automatic (default) permuting strategy for diagonal terms
	o.m.icntl[14-1] = 5000 // % increase of working space
	o.m.icntl[18-1] = 3    // distributed matrix
	o.m.icntl[23-1] = 2000 // max 2000Mb per processor // TODO: check this
	o.SetOrdScal("", "")

	// analysis step
	o.m.job = 1      // analysis code
	C.dmumps_c(&o.m) // analyse
	if o.m.info[1-1] < 0 {
		return chk.Err(_linsol_mumps_err03, mumps_error(o.m.info[1-1], o.m.info[2-1]))
	}

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

	// success
	o.is_initialised = true
	return
}