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
// 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
}
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
// InitC initialises a LinSolMumps data structure for Complex systems. It also performs some initial analyses.
func (o *LinSolMumps) InitC(tC *TripletC, symmetric, verbose, timing bool) (err error) {

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

	// flags
	o.name = "mumps"
	o.sym = symmetric
	o.cmplx = true
	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()
	}

	// check xz
	if len(o.tC.xz) != 2*len(o.tC.i) {
		return chk.Err(_linsol_mumps_err05, len(o.tC.xz), len(o.tC.i))
	}

	// initialise Mumps
	o.mz.comm_fortran = -987654 // use Fortran communicator by default
	o.mz.par = 1                // host also works
	o.mz.sym = 0                // 0=unsymmetric, 1=sym(pos-def), 2=symmetric(undef)
	if symmetric {
		o.mz.sym = 2
	}
	o.mz.job = -1     // initialisation code
	C.zmumps_c(&o.mz) // initialise
	if o.mz.info[1-1] < 0 {
		return chk.Err(_linsol_mumps_err06, mumps_error(o.mz.info[1-1], o.mz.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.tC.pos), make([]int32, o.tC.pos)
	for k := 0; k < tC.pos; k++ {
		o.mi[k] = int32(o.tC.i[k]) + 1
		o.mj[k] = int32(o.tC.j[k]) + 1
	}

	// set pointers
	o.mz.n = C.int(o.tC.m)
	o.mz.nz_loc = C.int(o.tC.pos)
	o.mz.irn_loc = (*C.int)(unsafe.Pointer(&o.mi[0]))
	o.mz.jcn_loc = (*C.int)(unsafe.Pointer(&o.mj[0]))
	o.mz.a_loc = (*C.ZMUMPS_COMPLEX)(unsafe.Pointer(&o.tC.xz[0]))

	// only proc # 0 needs the RHS
	if mpi.Rank() == 0 {
		o.xRC = make([]float64, 2*o.tC.n)
		o.mz.rhs = (*C.ZMUMPS_COMPLEX)(unsafe.Pointer(&o.xRC[0]))
	}

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

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

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

	// success
	o.is_initialised = true
	return
}