예제 #1
0
파일: main.go 프로젝트: PaddySchmidt/gofem
func main() {

	// catch errors
	defer func() {
		if err := recover(); err != nil {
			if mpi.Rank() == 0 {
				chk.Verbose = true
				for i := 8; i > 3; i-- {
					chk.CallerInfo(i)
				}
				io.PfRed("ERROR: %v\n", err)
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// default input parameters

	// read input parameters
	fnamepath, _ := io.ArgToFilename(0, "", ".sim", true)
	verbose := io.ArgToBool(1, true)
	erasePrev := io.ArgToBool(2, true)
	saveSummary := io.ArgToBool(3, true)
	allowParallel := io.ArgToBool(4, true)
	alias := io.ArgToString(5, "")

	// message
	if mpi.Rank() == 0 && verbose {
		io.PfWhite("\nGofem v3 -- Go Finite Element Method\n\n")
		io.Pf("Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.\n")
		io.Pf("Use of this source code is governed by a BSD-style\n")
		io.Pf("license that can be found in the LICENSE file.\n\n")

		io.Pf("\n%v\n", io.ArgsTable(
			"filename path", "fnamepath", fnamepath,
			"show messages", "verbose", verbose,
			"erase previous results", "erasePrev", erasePrev,
			"save summary", "saveSummary", saveSummary,
			"allow parallel run", "allowParallel", allowParallel,
			"word to add to results", "alias", alias,
		))
	}

	// profiling?
	defer utl.DoProf(false)()

	// analysis data
	readSummary := false
	analysis := fem.NewFEM(fnamepath, alias, erasePrev, saveSummary, readSummary, allowParallel, verbose, 0)

	// run simulation
	err := analysis.Run()
	if err != nil {
		chk.Panic("Run failed:\n%v", err)
	}
}
예제 #2
0
func run_pareto_test(U, V, Φ []float64, ntrials int) (zu, zv []float64) {
	io.Pforan("\nu = %v\n", U)
	io.Pforan("v = %v\n", V)
	io.PfWhite("%5s%13s%13s\n", "φ", "u wins", "v wins")
	zu = make([]float64, len(Φ))
	zv = make([]float64, len(Φ))
	for i, φ := range Φ {
		u_wins := 0
		v_wins := 0
		for j := 0; j < ntrials; j++ {
			u_dominates := DblsParetoMinProb(U, V, φ)
			if u_dominates {
				u_wins++
			} else {
				v_wins++
			}
		}
		zu[i] = 100 * float64(u_wins) / float64(ntrials)
		zv[i] = 100 * float64(v_wins) / float64(ntrials)
		io.Pf("%5.2f%12.2f%%%12.2f%%\n", φ, zu[i], zv[i])
	}
	return
}
예제 #3
0
파일: solver.go 프로젝트: PatrickSchm/gofem
// Run runs FE simulation
func Run() (runisok bool) {

	// plot functions
	if Global.Sim.PlotF != nil && Global.Root {
		Global.Sim.Functions.PlotAll(Global.Sim.PlotF, Global.Dirout, Global.Fnkey)
	}

	// alloc domains
	var domains []*Domain
	for _, reg := range Global.Sim.Regions {
		dom := NewDomain(reg, Global.Distr)
		if dom == nil {
			break
		}
		domains = append(domains, dom)
	}
	if Stop() {
		return
	}

	// make sure to call linear solver clean up routines upon exit
	defer func() {
		for _, d := range domains {
			if !d.InitLSol {
				d.LinSol.Clean()
			}
		}
	}()

	// current time and output time
	t := 0.0
	tout := 0.0
	tidx := 0

	// summary of outputs; e.g. with output times
	cputime := time.Now()
	var sum Summary
	sum.OutTimes = []float64{t}
	defer func() {
		sum.Save()
		if Global.Verbose && !Global.Debug {
			io.Pf("\nfinal t  = %v\n", t)
			io.Pfblue2("cpu time = %v\n", time.Now().Sub(cputime))
		}
	}()

	// loop over stages
	for stgidx, stg := range Global.Sim.Stages {

		// time incrementers
		Dt := stg.Control.DtFunc
		DtOut := stg.Control.DtoFunc
		tf := stg.Control.Tf
		tout = t + DtOut.F(t, nil)

		// set stage
		for _, d := range domains {
			if LogErrCond(!d.SetStage(stgidx, Global.Sim.Stages[stgidx], Global.Distr), "SetStage failed") {
				break
			}
			d.Sol.T = t
			if !d.Out(tidx) {
				break
			}
		}
		if Stop() {
			return
		}
		tidx += 1

		// log models
		mconduct.LogModels()
		mreten.LogModels()
		mporous.LogModels()
		msolid.LogModels()

		// skip stage?
		if stg.Skip {
			continue
		}

		// time loop using Richardson's extrapolation
		// TODO: works with only one domain for now
		if Global.Sim.Solver.RE {
			var re RichardsonExtrap
			re.Init(domains[0], Dt)
			if !re.Run(domains[0], &sum, DtOut, &t, tf, tout, &tidx) {
				return
			}
			continue
		}

		// time loop
		ndiverg := 0 // number of steps diverging
		md := 1.0    // time step multiplier if divergence control is on
		var Δt, Δtout float64
		var lasttimestep bool
		for t < tf {

			// check for continued divergence
			if LogErrCond(ndiverg >= Global.Sim.Solver.NdvgMax, "continuous divergence after %d steps reached", ndiverg) {
				return
			}

			// time increment
			Δt = Dt.F(t, nil) * md
			if t+Δt >= tf {
				Δt = tf - t
				lasttimestep = true
			}
			if Δt < Global.Sim.Solver.DtMin {
				if md < 1 {
					LogErrCond(true, "Δt increment is too small: %g < %g", Δt, Global.Sim.Solver.DtMin)
					return false
				}
				return true
			}

			// dynamic coefficients
			if LogErr(Global.DynCoefs.CalcBoth(Δt), "cannot compute dynamic coefficients") {
				return
			}

			// time update
			t += Δt
			for _, d := range domains {
				d.Sol.T = t
			}
			Δtout = DtOut.F(t, nil)

			// message
			if Global.Verbose {
				if !Global.Sim.Data.ShowR && !Global.Debug {
					io.PfWhite("%30.15f\r", t)
				}
			}

			// for all domains
			docontinue := false
			for _, d := range domains {

				// backup solution if divergence control is on
				if Global.Sim.Solver.DvgCtrl {
					d.backup()
				}

				// run iterations
				diverging, ok := run_iterations(t, Δt, d, &sum)
				if !ok {
					return
				}

				// restore solution and reduce time step if divergence control is on
				if Global.Sim.Solver.DvgCtrl {
					if diverging {
						if Global.Verbose {
							io.Pfred(". . . iterations diverging (%2d) . . .\n", ndiverg+1)
						}
						d.restore()
						t -= Δt
						d.Sol.T = t
						md *= 0.5
						ndiverg += 1
						docontinue = true
						break
					}
					ndiverg = 0
					md = 1.0
				}
			}
			if docontinue {
				continue
			}

			// perform output
			if t >= tout || lasttimestep {
				sum.OutTimes = append(sum.OutTimes, t)
				for _, d := range domains {
					//if true {
					if false {
						debug_print_p_results(d)
					}
					if false {
						debug_print_up_results(d)
					}
					if !d.Out(tidx) {
						break
					}
				}
				if Stop() {
					return
				}
				tout += Δtout
				tidx += 1
			}
		}
	}
	return true
}
예제 #4
0
func main() {

	// catch errors
	defer func() {
		if err := recover(); err != nil {
			io.PfRed("ERROR: %v\n", err)
		}
	}()

	// input data
	simfn, _ := io.ArgToFilename(0, "data/twoqua4", ".sim", true)
	exnwl := io.ArgToBool(1, false)
	stgidx := io.ArgToInt(2, 0)
	io.Pf("\n%s\n", io.ArgsTable(
		"simulation filename", "simfn", simfn,
		"extrapolate nwl", "exnwl", exnwl,
		"stage index", "stgidx", stgidx,
	))

	// start analysis process
	out.Start(simfn, stgidx, 0)

	// global variables
	ndim = out.Dom.Msh.Ndim
	verts = out.Dom.Msh.Verts
	cells = out.Dom.Msh.Cells
	nodes = out.Dom.Nodes
	elems = out.Dom.Elems
	dirout = out.Dom.Sim.DirOut
	fnkey = out.Dom.Sim.Key
	steady = out.Dom.Sim.Data.Steady

	// flags
	has_u := out.Dom.YandC["ux"]
	has_pl := out.Dom.YandC["pl"]
	has_pg := out.Dom.YandC["pg"]
	has_sig := out.Ipkeys["sx"]
	has_nwl := out.Ipkeys["nwlx"]
	has_p := has_pl || has_pg
	lbb := has_u && has_p
	if out.Dom.Sim.Data.NoLBB {
		lbb = false
	}

	// buffers
	pvd := make(map[string]*bytes.Buffer)
	geo := make(map[string]*bytes.Buffer)
	vtu := make(map[string]*bytes.Buffer)
	if _, ok := out.Dom.YandC["ux"]; ok {
		pvd["u"] = new(bytes.Buffer)
		geo["u"] = new(bytes.Buffer)
		vtu["u"] = new(bytes.Buffer)
	}
	for ykey, _ := range out.Dom.Dof2Tnum {
		if ykey == "ux" || ykey == "uy" || ykey == "uz" {
			continue
		}
		pvd[ykey] = new(bytes.Buffer)
		geo[ykey] = new(bytes.Buffer)
		vtu[ykey] = new(bytes.Buffer)
		label2keys[ykey] = []string{ykey}
	}
	if len(out.Ipkeys) > 0 {
		pvd["ips"] = new(bytes.Buffer)
		geo["ips"] = new(bytes.Buffer)
		vtu["ips"] = new(bytes.Buffer)
	}
	if exnwl {
		pvd["ex_nwl"] = new(bytes.Buffer)
		geo["ex_nwl"] = new(bytes.Buffer)
		vtu["ex_nwl"] = new(bytes.Buffer)
	}

	// extrapolated values keys
	extrap_keys := []string{"nwlx", "nwly"}
	if ndim == 3 {
		extrap_keys = []string{"nwlx", "nwly", "nwlz"}
	}

	// headers
	for _, b := range pvd {
		pvd_header(b)
	}

	// process results
	for tidx, t := range out.Sum.OutTimes {

		// input results into domain
		err := out.Dom.Read(out.Sum, tidx, 0, true)
		if err != nil {
			chk.Panic("cannot load results into domain\n%v", err)
		}

		// message
		io.PfWhite("time     = %g\r", t)

		// generate topology
		if tidx == 0 {
			for label, b := range geo {
				topology(b, label == "ips", lbb)
			}

			// allocate integration points values
			ipvals = make([]map[string]float64, len(out.Ipoints))
			for i, _ := range out.Ipoints {
				ipvals[i] = make(map[string]float64)
			}
		}

		// get integration points values @ time t
		for i, p := range out.Ipoints {
			vals := p.Calc(out.Dom.Sol)
			for key, val := range vals {
				ipvals[i][key] = val
			}
		}

		// compute extrapolated values
		if exnwl {
			out.ComputeExtrapolatedValues(extrap_keys)
		}

		// for each data buffer
		for label, b := range vtu {

			// reset buffer
			b.Reset()

			// points data
			if label == "ips" {
				pdata_open(b)
				if has_sig {
					pdata_write(b, "sig", skeys, true)
				}
				if has_nwl {
					pdata_write(b, "nwl", nwlkeys, true)
				}
				for key, _ := range out.Ipkeys {
					if !is_sig[key] && !is_nwl[key] {
						pdata_write(b, key, []string{key}, true)
					}
				}
				pdata_close(b)
			} else {
				pdata_open(b)
				pdata_write(b, label, label2keys[label], false)
				pdata_close(b)
			}

			// cells data
			cdata_write(b, label == "ips")

			// write vtu file
			vtu_write(geo[label], b, tidx, label)
		}

		// pvd
		for label, b := range pvd {
			pvd_line(b, tidx, t, label)
		}
	}

	// write pvd files
	for label, b := range pvd {
		pvd_write(b, label)
	}
}
예제 #5
0
파일: main.go 프로젝트: PatrickSchm/gofem
func main() {

	// catch errors
	defer func() {
		if err := recover(); err != nil {
			if mpi.Rank() == 0 {
				chk.Verbose = true
				for i := 8; i > 3; i-- {
					chk.CallerInfo(i)
				}
				io.PfRed("ERROR: %v\n", err)
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// message
	if mpi.Rank() == 0 {
		io.PfWhite("\nGofem v3 -- Go Finite Element Method\n\n")
		io.Pf("Copyright 2015 Dorival Pedroso and Raul Durand. All rights reserved.\n")
		io.Pf("Use of this source code is governed by a BSD-style\n")
		io.Pf("license that can be found in the LICENSE file.\n\n")
	}

	// simulation filenamepath
	flag.Parse()
	var fnamepath string
	if len(flag.Args()) > 0 {
		fnamepath = flag.Arg(0)
	} else {
		chk.Panic("Please, provide a filename. Ex.: cylinder.sim")
	}

	// check extension
	if io.FnExt(fnamepath) == "" {
		fnamepath += ".sim"
	}

	// other options
	erasefiles := true
	verbose := true
	if len(flag.Args()) > 1 {
		erasefiles = io.Atob(flag.Arg(1))
	}
	if len(flag.Args()) > 2 {
		verbose = io.Atob(flag.Arg(2))
	}

	// profiling?
	defer utl.DoProf(false)()

	// start global variables and log
	if !fem.Start(fnamepath, erasefiles, verbose) {
		chk.Panic("Start failed\n")
		return
	}

	// make sure to flush log
	defer fem.End()

	// run simulation
	if !fem.Run() {
		io.PfRed("ERROR: cannot run simulation\n")
	}
}
예제 #6
0
func (o *RichardsonExtrap) Run(d *Domain, s *Summary, DtOut fun.Func, time *float64, tf, tout float64, tidx *int) (ok bool) {

	// stat
	defer func() {
		if Global.Root {
			log.Printf("total number of steps             	= %d\n", o.nsteps)
			log.Printf("number of accepted steps          	= %d\n", o.naccept)
			log.Printf("number of rejected steps          	= %d\n", o.nreject)
			log.Printf("number of Gustaffson's corrections	= %d\n", o.ngustaf)
		}
	}()

	// constants
	atol := Global.Sim.Solver.REatol
	rtol := Global.Sim.Solver.RErtol
	mmin := Global.Sim.Solver.REmmin
	mmax := Global.Sim.Solver.REmmax
	mfac := Global.Sim.Solver.REmfac

	// time loop
	t := *time
	defer func() { *time = t }()
	var ΔtOld, rerrOld float64
	for t < tf {

		// check for continued divergence
		if LogErrCond(o.ndiverg >= Global.Sim.Solver.NdvgMax, "continuous divergence after %d steps reached", o.ndiverg) {
			return
		}

		// check time increment
		if LogErrCond(o.Δt < Global.Sim.Solver.DtMin, "Δt increment is too small: %g < %g", o.Δt, Global.Sim.Solver.DtMin) {
			return
		}

		// compute dynamic coefficients
		if LogErr(Global.DynCoefs.CalcBoth(o.Δt), "cannot compute dynamic coefficients") {
			return
		}

		// check for maximum number of substeps
		o.nsteps += 1
		if LogErrCond(o.nsteps >= Global.Sim.Solver.REnssmax, "RE: max number of steps reached: %d", o.nsteps) {
			return
		}

		// backup domain
		d.backup()

		// single step with Δt
		d.Sol.T = t + o.Δt
		o.diverging, ok = run_iterations(t+o.Δt, o.Δt, d, s)
		if !ok {
			return
		}
		if Global.Sim.Solver.DvgCtrl {
			if o.divergence_control(d, "big step") {
				continue
			}
		}

		// save intermediate state
		for i := 0; i < d.Ny; i++ {
			o.Y_big[i] = d.Sol.Y[i]
		}

		// restore initial state
		d.restore()

		// 1st halved step
		d.Sol.T = t + o.Δt/2.0
		o.diverging, ok = run_iterations(t+o.Δt/2.0, o.Δt/2.0, d, s)
		if !ok {
			break
		}
		if Global.Sim.Solver.DvgCtrl {
			if o.divergence_control(d, "1st half step") {
				continue
			}
		}

		// 2nd halved step
		d.Sol.T = t + o.Δt
		o.diverging, ok = run_iterations(t+o.Δt, o.Δt/2.0, d, s)
		if !ok {
			break
		}
		if Global.Sim.Solver.DvgCtrl {
			if o.divergence_control(d, "2nd half step") {
				continue
			}
		}

		// Richardson's extrapolation error
		rerr := la.VecRmsError(d.Sol.Y, o.Y_big, atol, rtol, d.Sol.Y) / 3.0

		// step size change
		m := min(mmax, max(mmin, mfac*math.Pow(1.0/rerr, 1.0/2.0)))
		ΔtNew := m * o.Δt

		// accepted
		if rerr < 1.0 {

			// update variables
			o.naccept += 1
			t += o.Δt
			d.Sol.T = t

			// output
			if Global.Verbose {
				if !Global.Sim.Data.ShowR && !Global.Debug {
					io.PfWhite("%30.15f\r", t)
				}
			}
			//if true {
			if t >= tout || o.laststep {
				s.OutTimes = append(s.OutTimes, t)
				if !d.Out(*tidx) {
					return
				}
				tout += DtOut.F(t, nil)
				*tidx += 1
			}

			// reached final time
			if o.laststep {
				if Global.Verbose {
					io.Pfgreen("\n\nRichardson extrapolation succeeded\n")
				}
				return true
			}

			// predictive controller of Gustafsson
			if !Global.Sim.Solver.REnogus {
				if o.naccept > 1 {
					m = mfac * (o.Δt / ΔtOld) * math.Sqrt(1.0/rerr) * math.Sqrt(rerrOld/rerr)
					if m*o.Δt < ΔtNew {
						o.ngustaf += 1
					}
					ΔtNew = min(ΔtNew, m*o.Δt)
				}
				ΔtOld = o.Δt
				rerrOld = max(0.9, rerr) // 1e-2
			}

			// next step size
			if o.reject { // do not alow Δt to grow if previous was a reject
				ΔtNew = min(o.Δt, ΔtNew)
			}
			o.reject = false
			o.Δt = ΔtNew
			if t+ΔtNew-tf >= 0.0 {
				o.laststep = true
				o.Δt = tf - t
			}

			// rejected
		} else {

			// restore state
			d.restore()

			// set flags
			o.nreject += 1
			o.reject = true
			o.laststep = false

			// next step size
			o.Δt = ΔtNew
			if t+o.Δt > tf {
				o.Δt = tf - t
			}
		}
	}
	return true
}
예제 #7
0
func (o *RichardsonExtrap) Run(tf float64, dtFunc, dtoFunc fun.Func, verbose bool, dbgKb DebugKb_t) (err error) {

	// constants
	dat := o.doms[0].Sim.Solver
	atol := dat.REatol
	rtol := dat.RErtol
	mmin := dat.REmmin
	mmax := dat.REmmax
	mfac := dat.REmfac

	// control
	t := o.doms[0].Sol.T
	tout := t + dtoFunc.F(t, nil)
	steady := o.doms[0].Sim.Data.Steady

	// first output
	if o.sum != nil {
		err = o.sum.SaveDomains(t, o.doms, false)
		if err != nil {
			return chk.Err("cannot save results:\n%v", err)
		}
	}

	// domain and variables
	d := o.doms[0]
	o.Y_big = make([]float64, d.Ny)

	// time loop
	o.Δt = dtFunc.F(t, nil)
	o.Δtcpy = o.Δt
	var ΔtOld, rerrOld float64
	for t < tf {

		// check for continued divergence
		if o.ndiverg >= dat.NdvgMax {
			return chk.Err("continuous divergence after %d steps reached", o.ndiverg)
		}

		// check time increment
		if o.Δt < dat.DtMin {
			return chk.Err("Δt increment is too small: %g < %g", o.Δt, dat.DtMin)
		}

		// dynamic coefficients
		if !steady {
			err = o.dc.CalcBoth(o.Δt)
			if err != nil {
				return chk.Err("cannot compute dynamic coefficients:\n%v", err)
			}
		}

		// check for maximum number of substeps
		o.nsteps += 1
		if o.nsteps >= dat.REnssmax {
			return chk.Err("RE: max number of steps reached: %d", o.nsteps)
		}

		// backup domain
		d.backup()

		// single step with Δt
		d.Sol.T = t + o.Δt
		d.Sol.Dt = o.Δt
		o.diverging, err = run_iterations(t+o.Δt, o.Δt, d, o.dc, o.sum, dbgKb)
		if err != nil {
			return chk.Err("single step with Δt: run_iterations failed:\n%v", err)
		}
		if dat.DvgCtrl {
			if o.divergence_control(d, "big step", verbose) {
				continue
			}
		}

		// save intermediate state
		for i := 0; i < d.Ny; i++ {
			o.Y_big[i] = d.Sol.Y[i]
		}

		// restore initial state
		d.restore()

		// 1st halved step
		d.Sol.T = t + o.Δt/2.0
		d.Sol.Dt = o.Δt / 2.0
		o.diverging, err = run_iterations(t+o.Δt/2.0, o.Δt/2.0, d, o.dc, o.sum, dbgKb)
		if err != nil {
			return chk.Err("1st halved step: run_iterations failed:\n%v", err)
		}
		if dat.DvgCtrl {
			if o.divergence_control(d, "1st half step", verbose) {
				continue
			}
		}

		// 2nd halved step
		d.Sol.T = t + o.Δt
		d.Sol.Dt = o.Δt
		o.diverging, err = run_iterations(t+o.Δt, o.Δt/2.0, d, o.dc, o.sum, dbgKb)
		if err != nil {
			return chk.Err("2nd halved step: run_iterations failed:\n%v", err)
		}
		if dat.DvgCtrl {
			if o.divergence_control(d, "2nd half step", verbose) {
				continue
			}
		}

		// Richardson's extrapolation error
		rerr := la.VecRmsError(d.Sol.Y, o.Y_big, atol, rtol, d.Sol.Y) / 3.0

		// step size change
		m := utl.Min(mmax, utl.Max(mmin, mfac*math.Pow(1.0/rerr, 1.0/2.0)))
		ΔtNew := m * o.Δt

		// accepted
		if rerr < 1.0 {

			// update variables
			o.naccept += 1
			t += o.Δt
			d.Sol.T = t

			// output
			if verbose {
				if !dat.ShowR {
					io.PfWhite("%30.15f\r", t)
				}
			}
			if t >= tout || o.laststep {
				if o.sum != nil {
					err = o.sum.SaveDomains(t, o.doms, false)
					if err != nil {
						return chk.Err("cannot save results:\n%v", err)
					}
				}
				tout += dtoFunc.F(t, nil)
			}

			// reached final time
			if o.laststep {
				if verbose {
					io.Pfgreen("\n\nRichardson extrapolation succeeded\n")
				}
				return
			}

			// predictive controller of Gustafsson
			if !dat.REnogus {
				if o.naccept > 1 {
					m = mfac * (o.Δt / ΔtOld) * math.Sqrt(1.0/rerr) * math.Sqrt(rerrOld/rerr)
					if m*o.Δt < ΔtNew {
						o.ngustaf += 1
					}
					ΔtNew = utl.Min(ΔtNew, m*o.Δt)
				}
				ΔtOld = o.Δt
				rerrOld = utl.Max(0.9, rerr) // 1e-2
			}

			// next step size
			if o.reject { // do not alow Δt to grow if previous was a reject
				ΔtNew = utl.Min(o.Δt, ΔtNew)
			}
			o.reject = false
			o.Δt = ΔtNew
			if t+ΔtNew-tf >= 0.0 {
				o.laststep = true
				o.Δt = tf - t
			}

			// rejected
		} else {

			// restore state
			d.restore()

			// set flags
			o.nreject += 1
			o.reject = true
			o.laststep = false

			// next step size
			o.Δt = ΔtNew
			if t+o.Δt > tf {
				o.Δt = tf - t
			}
		}
	}
	return
}
예제 #8
0
파일: GenVtu.go 프로젝트: PatrickSchm/gofem
func main() {

	// finalise analysis process and catch errors
	defer out.End()

	// input data
	simfn := "data/twoqua4.sim"
	exnwl := false
	stgidx := 0

	// parse flags
	flag.Parse()
	if len(flag.Args()) > 0 {
		simfn = flag.Arg(0)
	}
	if len(flag.Args()) > 1 {
		exnwl = io.Atob(flag.Arg(1))
	}
	if len(flag.Args()) > 2 {
		stgidx = io.Atoi(flag.Arg(2))
	}

	// check extension
	if io.FnExt(simfn) == "" {
		simfn += ".sim"
	}

	// print input data
	io.Pf("\nInput data\n")
	io.Pf("==========\n")
	io.Pf("  simfn   = %30s // simulation filename\n", simfn)
	io.Pf("  exnwl   = %30v // extrapolate nwl\n", exnwl)
	io.Pf("  stgidx  = %30v // stage index\n", stgidx)
	io.Pf("\n")

	// start analysis process
	out.Start(simfn, stgidx, 0)

	// global variables
	ndim = out.Dom.Msh.Ndim
	verts = out.Dom.Msh.Verts
	cells = out.Dom.Msh.Cells
	nodes = out.Dom.Nodes
	elems = out.Dom.Elems
	dirout = fem.Global.Sim.Data.DirOut
	fnkey = fem.Global.Sim.Data.FnameKey
	steady = fem.Global.Sim.Data.Steady

	// flags
	has_u := out.Dom.YandC["ux"]
	has_pl := out.Dom.YandC["pl"]
	has_pg := out.Dom.YandC["pg"]
	has_sig := out.Ipkeys["sx"]
	has_nwl := out.Ipkeys["nwlx"]
	has_p := has_pl || has_pg
	lbb := has_u && has_p
	if fem.Global.Sim.Data.NoLBB {
		lbb = false
	}

	// buffers
	pvd := make(map[string]*bytes.Buffer)
	geo := make(map[string]*bytes.Buffer)
	vtu := make(map[string]*bytes.Buffer)
	if _, ok := out.Dom.YandC["ux"]; ok {
		pvd["u"] = new(bytes.Buffer)
		geo["u"] = new(bytes.Buffer)
		vtu["u"] = new(bytes.Buffer)
	}
	if _, ok := out.Dom.YandC["fl"]; ok {
		pvd["fl"] = new(bytes.Buffer)
		geo["fl"] = new(bytes.Buffer)
		vtu["fl"] = new(bytes.Buffer)
	}
	if _, ok := out.Dom.YandC["pl"]; ok {
		pvd["pl"] = new(bytes.Buffer)
		geo["pl"] = new(bytes.Buffer)
		vtu["pl"] = new(bytes.Buffer)
	}
	if _, ok := out.Dom.YandC["pg"]; ok {
		pvd["pg"] = new(bytes.Buffer)
		geo["pg"] = new(bytes.Buffer)
		vtu["pg"] = new(bytes.Buffer)
	}
	if len(out.Ipkeys) > 0 {
		pvd["ips"] = new(bytes.Buffer)
		geo["ips"] = new(bytes.Buffer)
		vtu["ips"] = new(bytes.Buffer)
	}
	if exnwl {
		pvd["ex_nwl"] = new(bytes.Buffer)
		geo["ex_nwl"] = new(bytes.Buffer)
		vtu["ex_nwl"] = new(bytes.Buffer)
	}

	// extrapolated values keys
	extrap_keys := []string{"nwlx", "nwly"}
	if ndim == 3 {
		extrap_keys = []string{"nwlx", "nwly", "nwlz"}
	}

	// headers
	for _, b := range pvd {
		pvd_header(b)
	}

	// process results
	for tidx, t := range out.Sum.OutTimes {

		// input results into domain
		if !out.Dom.In(out.Sum, tidx, true) {
			chk.Panic("cannot load results into domain; please check log file")
		}

		// message
		io.PfWhite("time     = %g\r", t)

		// generate topology
		if tidx == 0 {
			for label, b := range geo {
				topology(b, label == "ips", lbb)
			}

			// allocate integration points values
			ipvals = make([]map[string]float64, len(out.Ipoints))
			for i, _ := range out.Ipoints {
				ipvals[i] = make(map[string]float64)
			}
		}

		// get integration points values @ time t
		for i, p := range out.Ipoints {
			vals := p.Calc(out.Dom.Sol)
			for key, val := range vals {
				ipvals[i][key] = val
			}
		}

		// compute extrapolated values
		if exnwl {
			out.ComputeExtrapolatedValues(extrap_keys)
		}

		// for each data buffer
		for label, b := range vtu {

			// reset buffer
			b.Reset()

			// points data
			if label == "ips" {
				pdata_open(b)
				if has_sig {
					pdata_write(b, "sig", skeys, true)
				}
				if has_nwl {
					pdata_write(b, "nwl", nwlkeys, true)
				}
				for key, _ := range out.Ipkeys {
					if !is_sig[key] && !is_nwl[key] {
						pdata_write(b, key, []string{key}, true)
					}
				}
				pdata_close(b)
			} else {
				pdata_open(b)
				pdata_write(b, label, label2keys[label], false)
				pdata_close(b)
			}

			// cells data
			cdata_write(b, label == "ips")

			// write vtu file
			vtu_write(geo[label], b, tidx, label)
		}

		// pvd
		for label, b := range pvd {
			pvd_line(b, tidx, t, label)
		}
	}

	// write pvd files
	for label, b := range pvd {
		pvd_write(b, label)
	}
}
예제 #9
0
func (o *SolverImplicit) Run(tf float64, dtFunc, dtoFunc fun.Func, verbose bool, dbgKb DebugKb_t) (err error) {

	// auxiliary
	md := 1.0    // time step multiplier if divergence control is on
	ndiverg := 0 // number of steps diverging

	// control
	t := o.doms[0].Sol.T
	dat := o.doms[0].Sim.Solver
	tout := t + dtoFunc.F(t, nil)
	steady := o.doms[0].Sim.Data.Steady

	// first output
	if o.sum != nil {
		err = o.sum.SaveDomains(t, o.doms, false)
		if err != nil {
			return chk.Err("cannot save results:\n%v", err)
		}
	}

	// time loop
	var Δt float64
	var lasttimestep bool
	for t < tf {

		// check for continued divergence
		if ndiverg >= dat.NdvgMax {
			return chk.Err("continuous divergence after %d steps reached", ndiverg)
		}

		// time increment
		Δt = dtFunc.F(t, nil) * md
		if t+Δt >= tf {
			lasttimestep = true
		}
		if Δt < dat.DtMin {
			if md < 1 {
				return chk.Err("Δt increment is too small: %g < %g", Δt, dat.DtMin)
			}
		}
		t += Δt

		// dynamic coefficients
		if !steady {
			err = o.dc.CalcBoth(Δt)
			if err != nil {
				return chk.Err("cannot compute dynamic coefficients")
			}
		}

		// message
		if verbose {
			if !dat.ShowR {
				io.PfWhite("%30.15f\r", t)
			}
		}

		// for all domains
		docontinue := false
		for _, d := range o.doms {

			// backup solution if divergence control is on
			if dat.DvgCtrl {
				d.backup()
			}

			// run iterations
			d.Sol.T = t
			d.Sol.Dt = Δt
			diverging, err := run_iterations(t, Δt, d, o.dc, o.sum, dbgKb)
			if err != nil {
				return chk.Err("run_iterations failed:\n%v", err)
			}

			// restore solution and reduce time step if divergence control is on
			if dat.DvgCtrl {
				if diverging {
					if verbose {
						io.Pfred(". . . iterations diverging (%2d) . . .\n", ndiverg+1)
					}
					d.restore()
					t -= Δt
					d.Sol.T = t
					md *= 0.5
					ndiverg += 1
					docontinue = true
					break
				}
				ndiverg = 0
				md = 1.0
			}
		}
		if docontinue {
			continue
		}

		// perform output
		if t >= tout || lasttimestep {
			if o.sum != nil {
				err = o.sum.SaveDomains(t, o.doms, false)
				if err != nil {
					return chk.Err("cannot save results:\n%v", err)
				}
			}
			tout += dtoFunc.F(t, nil)
		}
	}
	return
}
예제 #10
0
func (o *SolverLinearImplicit) Run(tf float64, dtFunc, dtoFunc fun.Func, verbose bool, notused DebugKb_t) (err error) {

	// control
	t := o.dom.Sol.T
	tout := t + dtoFunc.F(t, nil)
	steady := o.dom.Sim.Data.Steady

	// first output
	if o.sum != nil {
		err = o.sum.SaveDomains(t, []*Domain{o.dom}, false)
		if err != nil {
			return chk.Err("cannot save results:\n%v", err)
		}
	}

	// auxiliary variables
	Y := o.dom.Sol.Y
	ψ := o.dom.Sol.Psi
	ζ := o.dom.Sol.Zet
	χ := o.dom.Sol.Chi
	dydt := o.dom.Sol.Dydt
	d2ydt2 := o.dom.Sol.D2ydt2

	// time loop
	first := true
	var Δt float64
	var lasttimestep bool
	for t < tf {

		// time increment
		Δt = dtFunc.F(t, nil)
		if t+Δt >= tf {
			lasttimestep = true
		}
		t += Δt

		// update time variable in solution array
		o.dom.Sol.T = t
		o.dom.Sol.Dt = Δt

		// dynamic coefficients
		if !steady {
			err = o.dc.CalcBoth(Δt)
			if err != nil {
				return chk.Err("cannot compute dynamic coefficients")
			}
		}

		// message
		if verbose {
			io.PfWhite("%30.15f\r", t)
		}

		// calculate global starred vectors and interpolate starred variables from nodes to integration points
		if !steady {

			// compute starred vectors
			for _, I := range o.dom.T1eqs {
				ψ[I] = Y[I] - o.dom.Sol.ΔY[I]
			}

			for _, I := range o.dom.T2eqs {
				ζ[I] = Y[I]
				χ[I] = Y[I]
			}

			// set internal starred variables
			for _, e := range o.dom.Elems {
				err = e.InterpStarVars(o.dom.Sol)
				if err != nil {
					err = chk.Err("cannot compute starred variables:\n%v", err)
					return
				}
			}
		}

		// solve linear problem
		err := solve_linear_problem(t, o.dom, o.dc, o.sum, first)
		if err != nil {
			return chk.Err("solve_linear_problem failed:\n%v", err)
		}
		first = false

		// update velocity and acceleration
		if !steady {
			for _, I := range o.dom.T1eqs {
				dydt[I] = Y[I] - ψ[I]
			}
			for _, I := range o.dom.T2eqs {
				dydt[I] = o.dc.α4*Y[I] - χ[I]
				d2ydt2[I] = o.dc.α1*Y[I] - ζ[I]
			}
		}

		// perform output
		if t >= tout || lasttimestep {
			if o.sum != nil {
				err = o.sum.SaveDomains(t, []*Domain{o.dom}, false)
				if err != nil {
					return chk.Err("cannot save results:\n%v", err)
				}
			}
			tout += dtoFunc.F(t, nil)
		}
	}
	return
}