// 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)) } }
// 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 }
// 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 }
// 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 }