Пример #1
0
func main() {

	// catch errors
	var tst testing.T
	defer func() {
		if mpi.Rank() == 0 {
			if err := recover(); err != nil {
				io.PfRed("ERROR: %v\n", err)
			}
			if tst.Failed() {
				io.PfRed("test failed\n")
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// start global variables and log
	analysis := fem.NewFEM("data/bh16.sim", "", true, true, false, true, true, 0)

	// run simulation
	err := analysis.Run()
	if err != nil {
		tst.Error("Run failed\n")
		return
	}

	// check
	skipK := true
	tolK := 1e-12
	tolu := 1e-15
	tols := 1e-12
	fem.TestingCompareResultsU(&tst, "data/bh16.sim", "cmp/bh16.cmp", "", tolK, tolu, tols, skipK, true)
}
Пример #2
0
func main() {

	// catch errors
	var tst testing.T
	defer func() {
		if mpi.Rank() == 0 {
			if err := recover(); err != nil {
				io.PfRed("ERROR: %v\n", err)
			}
			if tst.Failed() {
				io.PfRed("test failed\n")
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// start global variables and log
	analysis := fem.NewFEM("data/p01.sim", "", true, true, false, true, true, 0)

	// run simulation
	err := analysis.Run()
	if err != nil {
		tst.Error("Run failed\n")
		return
	}
}
Пример #3
0
func check(problem int, tolf, tolg float64) {
	io.Pf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> problem %d <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", problem)
	opt := getfcn(problem)
	x := opt.RptXref
	f := make([]float64, opt.Nf)
	g := make([]float64, opt.Ng)
	h := make([]float64, opt.Nh)
	opt.MinProb(f, g, h, x, nil, 0)
	err := math.Abs(f[0] - opt.RptFref[0])
	io.Pforan("nx=%d nf=%d ng=%d nh=%d\n", opt.Nflt, opt.Nf, opt.Ng, opt.Nh)
	io.Pforan("x = %v\n", x)
	io.Pforan("f = %v  err = %v\n", f, err)
	io.Pforan("g = %v\n", g)
	io.Pforan("h = %v\n", h)
	for i := 0; i < opt.Ng; i++ {
		if g[i] < 0 {
			io.PfRed("unfeasible on g\n")
		}
	}
	for i := 0; i < opt.Nh; i++ {
		if math.Abs(h[i]) > opt.EpsH {
			io.PfRed("unfeasible on h\n")
		}
	}
	if err > tolf {
		io.PfRed("err is too big\n")
	}
}
Пример #4
0
func main() {

	// catch errors
	var tst testing.T
	defer func() {
		if mpi.Rank() == 0 {
			if err := recover(); err != nil {
				io.PfRed("ERROR: %v\n", err)
			}
			if tst.Failed() {
				io.PfRed("test failed\n")
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// start global variables and log
	if !fem.Start("data/p01.sim", true, true) {
		tst.Error("Start failed\n")
		return
	}

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

	// run simulation
	if !fem.Run() {
		tst.Error("Run failed\n")
		return
	}
}
func main() {

	// filename
	filename, fnkey := io.ArgToFilename(0, "sg111", ".sim", true)

	// fem
	if !fem.Start(filename, false, false, false) {
		io.PfRed("Start failed\n")
		return
	}
	dom, sum, ok := fem.AllocSetAndInit(0, true, true)
	if !ok {
		io.PfRed("AllocSetAndInit failed\n")
		return
	}

	// selected node and dof index
	nidx := 1
	didx := 1

	// gofem
	ntout := len(sum.OutTimes)
	uy := make([]float64, ntout)
	for tidx, _ := range sum.OutTimes {

		// read results from file
		if !dom.In(sum, tidx, true) {
			io.PfRed("plot_spo751: cannot read solution\n")
			return
		}

		// collect results for load versus time plot
		nod := dom.Nodes[nidx]
		eq := nod.Dofs[didx].Eq
		uy[tidx] = dom.Sol.Y[eq]

		// check
		if math.Abs(dom.Sol.T-sum.OutTimes[tidx]) > 1e-14 {
			io.PfRed("output times do not match time in solution array\n")
			return
		}
	}

	// plot fem results
	plt.SetForPng(0.8, 400, 200)
	plt.Plot(sum.OutTimes, uy, "'ro-', clip_on=0, label='gofem'")

	// analytical solution
	tAna := utl.LinSpace(0, 5, 101)
	uyAna := make([]float64, len(tAna))
	for i, t := range tAna {
		uyAna[i] = solution_uy(t, 1.0)
	}
	plt.Plot(tAna, uyAna, "'g-', clip_on=0, label='analytical'")

	// save
	plt.Gll("$t$", "$u_y$", "")
	plt.SaveD("/tmp", fnkey+".png")
}
Пример #6
0
func main() {

	// filename
	filename, fnkey := io.ArgToFilename(0, "rjoint01", ".sim", true)

	// fem
	if !fem.Start(filename, false, false, false) {
		io.PfRed("Start failed\n")
		return
	}
	dom, sum, ok := fem.AllocSetAndInit(0, true, true)
	if !ok {
		io.PfRed("AllocSetAndInit failed\n")
		return
	}

	// rjoint element
	eid := 2
	ele := dom.Elems[eid].(*fem.Rjoint)
	ipd := ele.OutIpsData()

	// load results from file
	n := len(sum.OutTimes)
	mtau0 := make([]float64, n)
	mtau1 := make([]float64, n)
	mtau2 := make([]float64, n)
	ompb0 := make([]float64, n)
	ompb1 := make([]float64, n)
	ompb2 := make([]float64, n)
	for i, _ := range sum.OutTimes {
		if !dom.In(sum, i, true) {
			io.PfRed("cannot read solution\n")
			return
		}
		res0 := ipd[0].Calc(dom.Sol)
		res1 := ipd[1].Calc(dom.Sol)
		res2 := ipd[2].Calc(dom.Sol)
		mtau0[i] = -res0["tau"]
		mtau1[i] = -res1["tau"]
		mtau2[i] = -res2["tau"]
		ompb0[i] = res0["ompb"]
		ompb1[i] = res1["ompb"]
		ompb2[i] = res2["ompb"]
	}

	// plot
	plt.SetForPng(0.8, 400, 200)
	plt.Plot(ompb0, mtau0, "'r-', marker='.', label='p0', clip_on=0")
	plt.Plot(ompb1, mtau1, "'g-', marker='.', label='p1', clip_on=0")
	plt.Plot(ompb2, mtau2, "'b-', marker='.', label='p2', clip_on=0")
	plt.Gll("$\\bar{\\omega}_p$", "$-\\tau$", "")
	plt.SaveD("/tmp", fnkey+".png")
}
Пример #7
0
// CheckFront0 returns front0 and number of failed/success
func CheckFront0(opt *Optimiser, verbose bool) (nfailed int, front0 []*Solution) {
	front0 = make([]*Solution, 0)
	var nsuccess int
	for _, sol := range opt.Solutions {
		var failed bool
		for _, oor := range sol.Oor {
			if oor > 0 {
				failed = true
				break
			}
		}
		if failed {
			nfailed++
		} else {
			nsuccess++
			if sol.FrontId == 0 {
				front0 = append(front0, sol)
			}
		}
	}
	if verbose {
		if nfailed > 0 {
			io.PfRed("N failed = %d out of %d\n", nfailed, opt.Nsol)
		} else {
			io.PfGreen("N success = %d out of %d\n", nsuccess, opt.Nsol)
		}
		io.PfYel("N front 0 = %d\n", len(front0))
	}
	return
}
Пример #8
0
// End must be called at the end to flush log file
func End() {
	if err := recover(); err != nil {
		io.PfRed("ERROR: %v\n", err)
	} else {
		fem.End()
	}
}
Пример #9
0
func main() {

	// dimensions
	lx, ly := 10.0, 3.0

	// define structured mesh data
	var gd gemlab.InData
	gd.Nparts = 4
	gd.Sregs = &gemlab.Sregs{
		Tags: []int{-1},
		Nxs:  []int{10},
		Nys:  []int{3},
		Nzs:  []int{3},
		Points: [][]float64{
			{0, 0}, {lx, 0}, {lx, ly}, {0, ly},
		},
		Conn:  [][]int{{0, 1, 2, 3}},
		Btags: [][]int{{-20, -11, -21, -10}},
	}

	// tag vertices along line (middle vertical line)
	gd.VtagsL = &gemlab.VtagsL{
		Tags: []int{-1},
		Xxa:  [][]float64{{lx / 2.0, 0}},
		Xxb:  [][]float64{{lx / 2.0, ly}},
	}

	fnk := "d2-coarse"
	if err := gemlab.Generate(fnk, &gd); err != nil {
		io.PfRed("%v\n", err.Error())
	}
}
Пример #10
0
func main() {

	// dimensions
	lx, ly, lz := 10.0, 3.0, 3.0

	// define structured mesh data
	var gd gemlab.InData
	gd.Nparts = 4
	gd.Sregs = &gemlab.Sregs{
		Tags: []int{-1},
		Nxs:  []int{10},
		Nys:  []int{3},
		Nzs:  []int{3},
		Points: [][]float64{
			{0, 0, 0}, {lx, 0, 0}, {lx, ly, 0}, {0, ly, 0},
			{0, 0, lz}, {lx, 0, lz}, {lx, ly, lz}, {0, ly, lz},
		},
		Conn:  [][]int{{0, 1, 2, 3, 4, 5, 6, 7}},
		Btags: [][]int{{-10, -11, -20, -21, -30, -31}},
	}

	fnk := "d3-coarse"
	if err := gemlab.Generate(fnk, &gd); err != nil {
		io.PfRed("%v\n", err.Error())
	}
}
Пример #11
0
func Test_cxint01(tst *testing.T) {

	//verbose()
	chk.PrintTitle("cxint01")

	var ops OpsData
	ops.SetDefault()
	ops.Pc = 1
	ops.Ncuts = 1

	A := []int{1, 2}
	B := []int{-1, -2}
	a := make([]int, len(A))
	b := make([]int, len(A))
	IntCrossover(a, b, A, B, 0, &ops)
	io.Pfred("A = %2d\n", A)
	io.PfRed("B = %2d\n", B)
	io.Pfcyan("a = %2d\n", a)
	io.Pfblue2("b = %2d\n", b)
	chk.Ints(tst, "a", a, []int{1, -2})
	chk.Ints(tst, "b", b, []int{-1, 2})
	io.Pf("\n")

	A = []int{1, 2, 3, 4, 5, 6, 7, 8}
	B = []int{-1, -2, -3, -4, -5, -6, -7, -8}
	a = make([]int, len(A))
	b = make([]int, len(A))
	ops.Cuts = []int{1, 3}
	IntCrossover(a, b, A, B, 0, &ops)
	io.Pfred("A = %2v\n", A)
	io.PfRed("B = %2v\n", B)
	io.Pfcyan("a = %2v\n", a)
	io.Pfblue2("b = %2v\n", b)
	chk.Ints(tst, "a", a, []int{1, -2, -3, 4, 5, 6, 7, 8})
	chk.Ints(tst, "b", b, []int{-1, 2, 3, -4, -5, -6, -7, -8})

	ops.Cuts = []int{5, 7}
	IntCrossover(a, b, A, B, 0, &ops)
	io.Pfred("A = %2v\n", A)
	io.PfRed("B = %2v\n", B)
	io.Pfcyan("a = %2v\n", a)
	io.Pfblue2("b = %2v\n", b)
	chk.Ints(tst, "a", a, []int{1, 2, 3, 4, 5, -6, -7, 8})
	chk.Ints(tst, "b", b, []int{-1, -2, -3, -4, -5, 6, 7, -8})
}
Пример #12
0
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)
	}
}
Пример #13
0
func Test_out02(tst *testing.T) {

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

	// test title
	//verbose()
	chk.PrintTitle("out02")

	// start simulation
	processing := fem.NewFEM("data/twoqua4.sim", "", true, true, false, false, chk.Verbose, 0)

	// run simulation
	err := processing.Run()
	if err != nil {
		tst.Errorf("Run failed:\n%v", err)
		return
	}

	// start post-processing
	Start("data/twoqua4.sim", 0, 0)

	// get second ip coordinates
	xip := Ipoints[1].X
	io.Pfcyan("xip = %v\n", xip)

	// define points
	Define("A", N{-1})
	Define("ips", Along{{xip[0], 0}, {xip[0], 1}})

	// load results
	LoadResults(nil)

	// solution
	var sol ana.CteStressPstrain
	sol.Init(fun.Prms{
		&fun.Prm{N: "qnH", V: -50},
		&fun.Prm{N: "qnV", V: -100},
	})

	// check displacements
	tolu := 1e-15
	x := GetCoords("A")
	ux := GetRes("ux", "A", 0)
	uy := GetRes("uy", "A", 0)
	io.Pforan("ux=%v uy=%v\n", ux, uy)
	for j, t := range Times {
		io.Pfyel("t=%g\n", t)
		sol.CheckDispl(tst, t, []float64{ux[j], uy[j]}, x, tolu)
	}
}
Пример #14
0
func main() {

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

	// input data
	var mshfn string
	mshfn, fnkey = io.ArgToFilename(0, "data/d2-coarse", ".msh", true)
	io.Pf("\n%s\n", io.ArgsTable(
		"mesh filename", "mshfn", mshfn,
	))

	// read mesh
	msh, err := inp.ReadMsh("", mshfn, 0)
	if err != nil {
		io.PfRed("cannot read mesh:\n%v", err)
		return
	}
	ndim = msh.Ndim
	verts = msh.Verts
	cells = msh.Cells
	dirout = "/tmp/gofem"

	// buffers
	geo := new(bytes.Buffer)
	vtu := new(bytes.Buffer)

	// generate topology
	topology(geo)

	// points data
	pdata_write(vtu)

	// cells data
	cdata_write(vtu)

	// write vtu file
	vtu_write(geo, vtu)
}
Пример #15
0
func main() {

	// filename
	filename, fnkey := io.ArgToFilename(0, "sg1121", ".sim", true)

	// results
	out.Start(filename, 0, 0)
	out.Define("A", out.N{30})
	out.LoadResults(nil)

	// plot FEM results
	out.Plot("t", "uy", "A", plt.Fmt{C: "k", Ls: "-", L: "gofem"}, -1)

	// old results
	b, err := io.ReadFile("cmp/sg1121gofemold.json")
	if err != nil {
		io.PfRed("cannot read comparison file\n")
		return
	}
	var gofemold struct {
		Time, Uy30 []float64
	}
	err = json.Unmarshal(b, &gofemold)
	if err != nil {
		io.PfRed("cannot unmarshal comparison file\n")
		return
	}

	// mechsys results
	_, res, err := io.ReadTable("cmp/sg1121mechsysN30.cmp")
	if err != nil {
		io.PfRed("cannot read mechsys comparison file\n")
		return
	}

	// save
	plt.SetForPng(0.8, 400, 200)
	out.Draw("/tmp", fnkey+".png", false, func(i, j, n int) {
		plt.Plot(gofemold.Time, gofemold.Uy30, "'r-', lw=2, label='gofemOld'")
		plt.Plot(res["Time"], res["uy"], "'b-', label='mechsys'")
	})
}
Пример #16
0
func main() {

	// catch errors
	var tst testing.T
	defer func() {
		if mpi.Rank() == 0 {
			if err := recover(); err != nil {
				io.PfRed("ERROR: %v\n", err)
			}
			if tst.Failed() {
				io.PfRed("test failed\n")
			}
		}
		mpi.Stop(false)
	}()
	mpi.Start(false)

	// start global variables and log
	if !fem.Start("data/spo751.sim", true, true) {
		tst.Error("Start failed\n")
		return
	}

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

	// run simulation
	if !fem.Run() {
		tst.Error("Run failed\n")
		return
	}

	// check
	skipK := true
	tolK := 1e-17
	tolu := 1e-12
	tols := 1e-14
	fem.TestingCompareResultsU(&tst, "data/spo751.sim", "cmp/spo751.cmp", tolK, tolu, tols, skipK, true)
}
Пример #17
0
func main() {

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

	// input data
	simfile, _ := io.ArgToFilename(0, "simfile.sim", true)
	zmin := io.ArgToFloat(1, 0.0)
	zmax := io.ArgToFloat(2, 3.0)
	npts := io.ArgToInt(3, 11)
	io.Pf("\n%s\n", io.ArgsTable(
		"simulation filename", "simfile", simfile,
		"min elevation", "zmin", zmin,
		"max elevation", "zmax", zmax,
		"number of points", "npts", npts,
	))

	// sim file
	sim := inp.ReadSim("", simfile, false)
	if sim == nil {
		io.PfRed("cannot read sim file\n")
		return
	}

	// layer
	var lay fem.GeoLayer
	lay.Zmin = zmin
	lay.Zmax = zmax
	lay.Cl = sim.WaterRho0 / sim.WaterBulk
	//if !lay.ReadPorousParameters(sim.Regions[0],
	// TODO

}
Пример #18
0
func main() {

	// input data
	simfile := "simfile.sim"
	zmin := 0.0
	zmax := 3.0
	npts := 11

	// parse flags
	flag.Parse()
	if len(flag.Args()) > 0 {
		simfile = flag.Arg(0)
	}
	if len(flag.Args()) > 1 {
		zmin = io.Atof(flag.Arg(1))
	}
	if len(flag.Args()) > 2 {
		zmax = io.Atob(flag.Arg(2))
	}
	if len(flag.Args()) > 3 {
		npts = io.Atoi(flag.Arg(3))
	}

	// print input data
	io.Pf("\nInput data\n")
	io.Pf("==========\n")
	io.Pf("  simfile  = %30s // simulation filename\n", simfile)
	io.Pf("  zmin     = %30s // min elevation\n", zmin)
	io.Pf("  zmax     = %30v // max elevation\n", zmax)
	io.Pf("  npts     = %30v // number of points\n", npts)
	io.Pf("\n")

	// sim file
	sim := inp.ReadSim("", simfile, false)
	if sim == nil {
		io.PfRed("cannot read sim file\n")
		return
	}

	// layer
	var lay fem.GeoLayer
	lay.Zmin = zmin
	lay.Zmax = zmax
	lay.Cl = sim.WaterRho0 / sim.WaterBulk
	//if !lay.ReadPorousParameters(sim.Regions[0],
	// TODO

}
Пример #19
0
// RunFEA runs FE analysis.
func RunFEA(x []float64, cpu int) (lsf, failed float64) {

	// FemData
	o := FEMDATA[cpu]

	// check for NaNs
	defer func() {
		if math.IsNaN(failed) || math.IsNaN(lsf) {
			io.PfRed("x = %+#v\n", x)
			chk.Panic("NaN: failed=%v lsf=%v\n", failed, lsf)
		}
	}()

	// adjust parameters
	for i, v := range o.Vars {
		v.Prm.Set(x[i])
	}
	for _, prm := range o.Sim.AdjDependent {
		if prm.N == "I22" {
			prm.Set(prm.S * prm.Other.V * prm.Other.V)
		}
	}
	o.Dom.RecomputeKM()

	// run
	err := o.Analysis.SolveOneStage(0, true)
	if err != nil {
		failed = 1
		return
	}

	// displacement based limit-state-function
	if o.AwdU > 0 {
		δ := o.Dom.Sol.Y[o.EqsU[0]]
		for i := 1; i < len(o.EqsU); i++ {
			δ = utl.Max(δ, o.Dom.Sol.Y[o.EqsU[i]])
		}
		lsf = o.AwdU - δ
	}
	return
}
Пример #20
0
func (o *PrincStrainsUp) dbg_plot(eid, ipid int, time float64) {
	if eid == o.DbgEid && ipid == o.DbgIpId {

		// skip if not selected time
		if o.DbgTime > -1 {
			if math.Abs(time-o.DbgTime) > 1e-7 {
				return
			}
		}

		// check Jacobian
		var cnd float64
		io.PfYel("\nchecking Jacobian: eid=%d ipid=%d\n", eid, ipid)
		cnd, err := o.nls.CheckJ(o.x, o.ChkJacTol, true, o.ChkSilent)
		if err != nil {
			io.PfRed("CheckJ failed:\n%v\n", err)
		}
		io.PfYel("after: cnd(J) = %v\n\n", cnd)
		io.Pfcyan("\nN  = %v\n", o.N)
		io.Pfcyan("Nb = %v\n", o.Nb)
		io.Pfcyan("A  = %v\n", o.A)
		io.Pfcyan("h  = %v\n", o.h)
		io.Pfcyan("Mb = %v\n", o.Mb)
		io.Pfcyan("a  = %v\n", o.a)
		io.Pfcyan("b  = %v\n", o.b)
		io.Pfcyan("c  = %v\n", o.c)
		io.Pfcyan("Lσ = %v\n", o.Lσ)
		io.Pforan("Ne = %v\n", o.Ne)
		io.Pforan("Mbe = %v\n", o.Mbe)
		io.Pforan("Fcoef = %v\n\n", o.Fcoef)

		// plot
		var plr Plotter
		plr.SetFig(false, false, 1.5, 400, "/tmp", io.Sf("fig_stress_eid%d_ipid%d", eid, ipid))
		plr.SetModel(o.Mdl)
		plr.PreCor = o.DbgPco
		plr.Plot([]string{"p,q,ys", "oct,ys"}, o.DbgRes, o.DbgSts, true, true)
	}
}
Пример #21
0
func main() {

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

	// input data
	matOld := io.ArgToString(0, "matOld.mat")
	matNew := io.ArgToString(1, "matNew.mat")
	convSymb := io.ArgToBool(2, true)
	io.Pf("\n%s\n", io.ArgsTable(
		"old material filename", "matOld", matOld,
		"new material filenamen", "matNew", matNew,
		"do convert symbols", "convSymb", convSymb,
	))

	// convert old => new
	inp.MatfileOld2New("", matNew, matOld, convSymb)
	io.Pf("conversion successful\n")
	io.Pfblue2("file <matNew.mat> created\n")
}
Пример #22
0
func main() {

	// input data file
	inpfn := "data/loccmdrv1.inp"
	flag.Parse()
	if len(flag.Args()) > 0 {
		inpfn = flag.Arg(0)
	}
	if io.FnExt(inpfn) == "" {
		inpfn += ".inp"
	}

	// read and parse input data
	var in Input
	b, err := io.ReadFile(inpfn)
	if err != nil {
		io.PfRed("cannot read %s\n", inpfn)
		return
	}
	err = json.Unmarshal(b, &in)
	if err != nil {
		io.PfRed("cannot parse %s\n", inpfn)
		return
	}
	in.PostProcess()

	// print input data
	io.Pf("%v\n", in)

	// load simulation
	sim := inp.ReadSim(in.Dir, in.SimFn, "cmd_", false)
	if sim == nil {
		io.PfRed("cannot load simulation\n")
		return
	}

	// get material data
	mat := sim.Mdb.Get(in.MatName)
	if mat == nil {
		io.PfRed("cannot get material\n")
		return
	}
	//io.Pfcyan("mat = %v\n", mat)

	// get and initialise model
	mdl, _ := msolid.GetModel(in.SimFn, in.MatName, mat.Model, false)
	if mdl == nil {
		io.PfRed("cannot allocate model\n")
		return
	}
	ndim := 3
	pstress := false
	mdl.Init(ndim, pstress, mat.Prms)
	//io.Pforan("mdl = %v\n", mdl)

	// load path
	var pth msolid.Path
	err = pth.ReadJson(ndim, path.Join(in.Dir, in.PathFn))
	if err != nil {
		io.PfRed("cannot read path file %v\n", err)
		return
	}
	//io.PfYel("pth = %v\n", pth)

	// driver
	var drv msolid.Driver
	drv.InitWithModel(ndim, mdl)

	// run
	err = drv.Run(&pth)
	if err != nil {
		io.Pfred("driver: Run failed: %v\n", err)
	}

	// plot
	//if false {
	if true {
		var plr msolid.Plotter
		plr.SetFig(false, in.FigEps, in.FigProp, in.FigWid, "/tmp", "cmd_"+in.SimFn)
		var epm msolid.EPmodel
		if m, ok := mdl.(msolid.EPmodel); ok {
			plr.SetModel(m)
			epm = m
		}
		if epm != nil {
			//plr.Phi = epm.Get_phi()
			b := epm.Get_bsmp()
			epm.Set_bsmp(0)
			plr.YsClr0 = "magenta"
			plr.Plot(in.PlotSet, drv.Res, nil, true, false)
			epm.Set_bsmp(b)
		}
		plr.YsClr0 = "green"
		plr.Plot(in.PlotSet, drv.Res, drv.Eps, false, true)
	}

	// plot ys
	if false {
		//if true {
		plt.Reset()
		m := mdl.(*msolid.SmpInvs)
		φ := m.Get_phi()
		σcCte := 10.0
		M := tsr.Phi2M(φ, "oct")
		rmin, rmax := 0.0, 1.28*M*σcCte
		nr, nα := 31, 81
		//nr,   nα   := 31, 1001
		npolarc := true
		simplec := false
		only0 := false
		grads := false
		showpts := false
		ferr := 10.0
		tsr.PlotOct("fig_isofun02.png", σcCte, rmin, rmax, nr, nα, φ, m.Isof.Fa, m.Isof.Ga,
			npolarc, simplec, only0, grads, showpts, true, true, ferr)
	}
}
Пример #23
0
func main() {

	// input data
	simfn := "elast.sim"
	matname := "lrm1"
	pcmax := 30.0
	npts := 101

	// parse flags
	flag.Parse()
	if len(flag.Args()) > 0 {
		simfn = flag.Arg(0)
	}
	if len(flag.Args()) > 1 {
		matname = flag.Arg(1)
	}
	if len(flag.Args()) > 2 {
		pcmax = io.Atof(flag.Arg(2))
	}
	if len(flag.Args()) > 3 {
		npts = io.Atoi(flag.Arg(3))
	}

	// 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("  matname = %30s // material name\n", matname)
	io.Pf("  pcmax   = %30v // max pc\n", pcmax)
	io.Pf("  npts    = %30v // number of points\n", npts)
	io.Pf("\n")

	// load simulation
	sim := inp.ReadSim("", simfn, "lrm_", false)
	if sim == nil {
		io.PfRed("cannot load simulation\n")
		return
	}

	// get material data
	mat := sim.Mdb.Get(matname)
	if mat == nil {
		io.PfRed("cannot get material\n")
		return
	}
	io.Pforan("mat = %v\n", mat)

	// get and initialise model
	mdl := mreten.GetModel(simfn, matname, mat.Model, false)
	if mdl == nil {
		io.PfRed("cannot allocate model\n")
		return
	}
	mdl.Init(mat.Prms)

	// plot drying path
	d_Pc := utl.LinSpace(0, pcmax, npts)
	d_Sl := make([]float64, npts)
	d_Sl[0] = 1
	var err error
	for i := 1; i < npts; i++ {
		d_Sl[i], err = mreten.Update(mdl, d_Pc[i-1], d_Sl[i-1], d_Pc[i]-d_Pc[i-1])
		if err != nil {
			io.PfRed("drying: cannot updated model\n%v\n", err)
			return
		}
	}
	plt.Plot(d_Pc, d_Sl, io.Sf("'b-', label='%s (dry)', clip_on=0", matname))

	// plot wetting path
	w_Pc := utl.LinSpace(pcmax, 0, npts)
	w_Sl := make([]float64, npts)
	w_Sl[0] = d_Sl[npts-1]
	for i := 1; i < npts; i++ {
		w_Sl[i], err = mreten.Update(mdl, w_Pc[i-1], w_Sl[i-1], w_Pc[i]-w_Pc[i-1])
		if err != nil {
			io.PfRed("wetting: cannot updated model\n%v\n", err)
			return
		}
	}
	plt.Plot(w_Pc, w_Sl, io.Sf("'c-', label='%s (wet)', clip_on=0", matname))

	// save results
	type Results struct{ Pc, Sl []float64 }
	res := Results{append(d_Pc, w_Pc...), append(d_Sl, w_Sl...)}
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	err = enc.Encode(&res)
	if err != nil {
		io.PfRed("cannot encode results\n")
		return
	}
	fn := path.Join(sim.Data.DirOut, matname+".dat")
	io.WriteFile(fn, &buf)
	io.Pf("file <%s> written\n", fn)

	// show figure
	plt.AxisYrange(0, 1)
	plt.Cross()
	plt.Gll("$p_c$", "$s_{\\ell}$", "")
	plt.Show()
}
Пример #24
0
func main() {

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

	// input data
	filename, fnkey := io.ArgToFilename(0, "data/equations.txt", "", true)
	io.Pf("\n%s\n", io.ArgsTable("INPUT ARGUMENTS",
		"file with equations", "filename", filename,
	))

	io.Pforan("fnkey = %v\n", fnkey)

	// open file
	f, err := io.OpenFileR(filename)
	if err != nil {
		return
	}

	// constants
	MAXNIDX := 100
	INDICES := []string{"i", "j", "k", "l", "m", "n", "r", "s", "p", "q"}

	// read file
	var buf bytes.Buffer
	io.ReadLinesFile(f, func(idx int, line string) (stop bool) {

		// indices
		l := line
		for i := 0; i < MAXNIDX; i++ {
			l = strings.Replace(l, io.Sf("[%d]", i), io.Sf("_{%d}", i), -1)
		}
		for _, idx := range INDICES {
			l = strings.Replace(l, io.Sf("[%s]", idx), io.Sf("_{%s}", idx), -1)
		}

		// constants
		l = strings.Replace(l, "math.Sqrt2", "\\sqrt{2}", -1)
		l = strings.Replace(l, "SQ2", "\\sqrt{2}", -1)

		// functions
		l = strings.Replace(l, "math.Sqrt", "\\sqrt", -1)
		l = strings.Replace(l, "math.Pow", "\\pow", -1)
		l = strings.Replace(l, "math.Exp", "\\exp", -1)
		l = strings.Replace(l, "math.Sin", "\\sin", -1)
		l = strings.Replace(l, "math.Cos", "\\cos", -1)

		// star
		l = strings.Replace(l, "*", " \\, ", -1)

		// colon-equal
		l = strings.Replace(l, ":=", "=", -1)

		// add to results
		io.Ff(&buf, "%s\n", l)
		return
	})

	// write file
	io.WriteFileVD("/tmp/gosl", fnkey+".tex", &buf)
}
Пример #25
0
func main() {

	// read README.md file
	md, err := io.ReadFile("README.md")
	if err != nil {
		io.PfRed("cannot read README.md\n")
		return
	}

	// process markdown
	//html := string(blackfriday.MarkdownCommon(md))

	flags := 0 |
		blackfriday.HTML_USE_XHTML |
		blackfriday.HTML_USE_SMARTYPANTS |
		blackfriday.HTML_SMARTYPANTS_LATEX_DASHES

	extensions := 0 |
		blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
		blackfriday.EXTENSION_TABLES |
		blackfriday.EXTENSION_FENCED_CODE |
		blackfriday.EXTENSION_AUTOLINK |
		blackfriday.EXTENSION_STRIKETHROUGH |
		blackfriday.EXTENSION_SPACE_HEADERS |
		blackfriday.EXTENSION_HEADER_IDS |
		blackfriday.EXTENSION_BACKSLASH_LINE_BREAK |
		blackfriday.EXTENSION_DEFINITION_LISTS

	renderer := blackfriday.HtmlRenderer(flags, "", "")
	html := string(blackfriday.MarkdownOptions(md, renderer, blackfriday.Options{Extensions: extensions}))

	// environment variable => figures path
	path := os.ExpandEnv("${GOPATH}/src/github.com/cpmech/gofem/")
	io.Pforan("path = %v\n", path)

	// set path of figures
	html = strings.Replace(html, "img src=\"", io.Sf("img src=\"%s/examples/", path), -1)

	// set header and footer
	html = `<!DOCTYPE HTML>
<html>
<head>
<title>Gofem &ndash; Examples</title>
<meta charset="utf-8" />

<style>
h1 {color:#0064cb; font-family:verdana; font-size:200%;}
h2 {color:#0064cb}
h3 {color:#0064cb}
a:hover {background-color:#5397dc;}
#container {
	width:500px;
	text-align:center;
}
#container img {
	max-width:100%;
	height:auto;
}
</style>

</head>
<body>
` + html + `
</body>
</html>`

	// write file
	io.WriteFileVD("/tmp", "gofem-README.html", bytes.NewBuffer([]byte(html)))
	//io.WriteFileVD("/tmp", "gofem-README.html", bytes.NewBuffer(html))
}
Пример #26
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)
	}
}
Пример #27
0
// MatfileNew2Old converts a new mat file to the old mat file format
//  convertsymbols -- convert back symbols with Greek characters to UTF-8
func MatfileNew2Old(dirout string, fnold, fnnew string, convertsymbols bool) {

	// read file
	b, err := io.ReadFile(fnnew)
	if err != nil {
		io.PfRed("cannot open file: %v", err.Error())
		return
	}

	// decode
	var mats_new MatDb
	err = json.Unmarshal(b, &mats_new)
	if err != nil {
		io.PfRed("cannot unmarshal file: %v", err.Error())
		return
	}

	// oldmatdata implements the old data format
	type oldmatdata struct {
		Name  string
		Desc  string
		Model string
		Prms  []string
		Vals  []float64
		Units []string
		Extra string
	}

	// convert
	var mats_old []oldmatdata
	for _, m := range mats_new.Materials {
		var oldmat oldmatdata
		oldmat.Name = m.Name
		oldmat.Desc = m.Desc
		oldmat.Model = m.Model
		oldmat.Extra = m.Extra
		for _, prm := range m.Prms {
			name := prm.N
			if convertsymbols {
				if n, ok := invertedconversiontable[prm.N]; ok {
					name = n
				}
			}
			oldmat.Prms = append(oldmat.Prms, name)
			oldmat.Vals = append(oldmat.Vals, prm.V)
			if len(prm.U) > 0 {
				oldmat.Units = append(oldmat.Units, prm.U)
			}
		}
		mats_old = append(mats_old, oldmat)
	}

	// encode
	buf, err := json.MarshalIndent(mats_old, "", "  ")
	if err != nil {
		return
	}

	// save file
	if dirout == "" {
		io.WriteFileS(fnold, string(buf))
		return
	}
	io.WriteFileSD(dirout, fnold, string(buf))
}
Пример #28
0
func main() {

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

	// input data
	mshfn, fnkey := io.ArgToFilename(0, "data/sgm57", ".msh", true)

	// old mesh
	var old OldMesh

	// read file
	b, err := io.ReadFile(mshfn)
	if err != nil {
		chk.Panic("%v", err)
	}

	// decode
	err = json.Unmarshal(b, &old)
	if err != nil {
		chk.Panic("%v", err)
	}

	// verts: find largest strings
	var ndim int
	L := make([]int, 5)
	for _, v := range old.Verts {
		L[0] = utl.Imax(L[0], len(io.Sf("%d", v.Id)))
		L[1] = utl.Imax(L[1], len(io.Sf("%d", v.Tag)))
		for j, x := range v.C {
			L[2+j] = utl.Imax(L[2+j], len(io.Sf("%g", x)))
		}
		ndim = len(v.C)
	}
	S := make([]string, 5)
	for i, l := range L {
		S[i] = io.Sf("%d", l)
	}

	// write vertices
	buf := new(bytes.Buffer)
	io.Ff(buf, "{\n  \"verts\":[\n")
	for i, v := range old.Verts {
		if i > 0 {
			io.Ff(buf, ",\n")
		}
		io.Ff(buf, "    {\"i\":%"+S[0]+"d, \"t\":%"+S[1]+"d, \"x\":[", v.Id, v.Tag)
		for j, x := range v.C {
			if j > 0 {
				io.Ff(buf, ", ")
			}
			io.Ff(buf, "%"+S[2+j]+"g", x)
		}
		io.Ff(buf, "] }")
	}

	// cells: find largest strings
	n := 30
	L = make([]int, n*2)
	for _, c := range old.Cells {
		L[0] = utl.Imax(L[0], len(io.Sf("%d", c.Id)))
		L[1] = utl.Imax(L[1], len(io.Sf("%d", c.Tag)))
		L[2] = utl.Imax(L[2], len(io.Sf("%d", c.Part)))
		for j, v := range c.Verts {
			L[3+j] = utl.Imax(L[3+j], len(io.Sf("%d", v)))
		}
	}
	S = make([]string, n*2)
	for i, l := range L {
		S[i] = io.Sf("%d", l)
	}
	io.Ff(buf, "\n  ],")

	// write cells
	io.Ff(buf, "\n  \"cells\":[\n")
	for i, c := range old.Cells {
		if i > 0 {
			io.Ff(buf, ",\n")
		}
		io.Ff(buf, "    {\"i\":%"+S[0]+"d, \"t\":%"+S[1]+"d, \"p\":%"+S[2]+"d, \"y\":%q, \"v\":[", c.Id, c.Tag, c.Part, c.Type)
		for j, v := range c.Verts {
			if j > 0 {
				io.Ff(buf, ", ")
			}
			io.Ff(buf, "%"+S[3+j]+"d", v)
		}
		io.Ff(buf, "]")
		if len(c.FTags) > 0 {
			io.Ff(buf, ", ")
			if ndim == 2 {
				io.Ff(buf, "\"et\":[")
			} else {
				io.Ff(buf, "\"ft\":[")
			}
			for j, t := range c.FTags {
				if j > 0 {
					io.Ff(buf, ", ")
				}
				io.Ff(buf, "%d", t)
			}
			io.Ff(buf, "]")
		}
		io.Ff(buf, " }")
	}
	io.Ff(buf, "\n  ]\n}")
	io.WriteFileVD("/tmp/gosl", fnkey+"-new.msh", buf)

	// check
	m, err := msh.Read("/tmp/gosl/" + fnkey + "-new.msh")
	if err != nil {
		chk.Panic("cannot read new mesh:\n%v", err)
	}
	m.Check()
}
Пример #29
0
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")
	}
}
Пример #30
0
// ReadSim reads all simulation data from a .sim JSON file
//  Notes:  1) this function initialises log file
//          2) returns nil on errors
func ReadSim(dir, fn, logPrefix string, erasefiles bool) *Simulation {

	// new sim
	var o Simulation

	// read file
	b, err := io.ReadFile(filepath.Join(dir, fn))
	if err != nil {
		io.PfRed("sim: cannot read simulation file %s/%s\n%v\n", dir, fn, err)
		return nil
	}

	// set default values
	o.Data.SetDefault()
	o.Solver.SetDefault()
	o.LinSol.SetDefault()

	// decode
	err = json.Unmarshal(b, &o)
	if err != nil {
		io.PfRed("sim: cannot unmarshal simulation file %s/%s\n%v\n", dir, fn, err)
		return nil
	}

	// derived data
	o.Data.PostProcess(dir, fn, erasefiles)
	o.LinSol.PostProcess()
	o.Solver.PostProcess()

	// init log file
	err = InitLogFile(o.Data.DirOut, logPrefix+o.Data.FnameKey)
	if err != nil {
		io.PfRed("sim: cannot create log file\n%v", err)
		return nil
	}

	// read materials database
	o.Mdb = ReadMat(o.Data.FnameDir, o.Data.Matfile)
	if LogErrCond(o.Mdb == nil, "sim: cannot read materials file") {
		return nil
	}

	// for all regions
	for i, reg := range o.Regions {

		// read mesh
		reg.Msh = ReadMsh(o.Data.FnameDir, reg.Mshfile)
		if LogErrCond(reg.Msh == nil, "cannot read mesh file") {
			return nil
		}

		// dependent variables
		reg.etag2idx = make(map[int]int)
		for j, ed := range reg.ElemsData {
			reg.etag2idx[ed.Tag] = j
		}

		// get ndim and max elevation
		if i == 0 {
			o.Ndim = reg.Msh.Ndim
			o.MaxElev = reg.Msh.Ymax
			if o.Ndim == 3 {
				o.MaxElev = reg.Msh.Zmax
			}
		} else {
			if LogErrCond(reg.Msh.Ndim != o.Ndim, "all meshes must have the same ndim. %d != %d") {
				return nil
			}
			if o.Ndim == 2 {
				o.MaxElev = max(o.MaxElev, reg.Msh.Ymax)
			} else {
				o.MaxElev = max(o.MaxElev, reg.Msh.Zmax)
			}
		}

		// get water data
		for _, mat := range o.Mdb.Materials {
			if mat.Model == "porous" {
				if prm := mat.Prms.Find("RhoL0"); prm != nil {
					o.WaterRho0 = prm.V
				}
				if prm := mat.Prms.Find("BulkL"); prm != nil {
					o.WaterBulk = prm.V
				}
			}
		}
	}

	// water level
	o.WaterLevel = max(o.Data.Wlevel, o.MaxElev)

	// for all stages
	var t float64
	for i, stg := range o.Stages {

		// fix Tf
		if stg.Control.Tf < 1e-14 {
			stg.Control.Tf = 1
		}

		// fix Dt
		if stg.Control.DtFcn == "" {
			if stg.Control.Dt < 1e-14 {
				stg.Control.Dt = 1
			}
			stg.Control.DtFunc = &fun.Cte{C: stg.Control.Dt}
		} else {
			stg.Control.DtFunc = o.Functions.Get(stg.Control.DtFcn)
			if LogErrCond(stg.Control.DtFunc == nil, "sim: cannot get Dt function named %s\n", stg.Control.DtFcn) {
				return nil
			}
			stg.Control.Dt = stg.Control.DtFunc.F(t, nil)
		}

		// fix DtOut
		if stg.Control.DtoFcn == "" {
			if stg.Control.DtOut < 1e-14 {
				stg.Control.DtOut = stg.Control.Dt
				stg.Control.DtoFunc = stg.Control.DtFunc
			} else {
				if stg.Control.DtOut < stg.Control.Dt {
					stg.Control.DtOut = stg.Control.Dt
				}
				stg.Control.DtoFunc = &fun.Cte{C: stg.Control.DtOut}
			}
		} else {
			stg.Control.DtoFunc = o.Functions.Get(stg.Control.DtoFcn)
			if LogErrCond(stg.Control.DtoFunc == nil, "sim: cannot get DtOut function named %s\n", stg.Control.DtoFcn) {
				return nil
			}
			stg.Control.DtOut = stg.Control.DtoFunc.F(t, nil)
		}

		// first stage
		if i == 0 {

			// gravity
			for _, econd := range stg.EleConds {
				for j, key := range econd.Keys {
					if key == "g" {
						if o.Gfcn == nil {
							o.Gfcn = o.Functions.Get(econd.Funcs[j])
							if LogErrCond(o.Gfcn == nil, "sim: cannot find gravity function in functions database") {
								return nil
							}
							break
						}
					}
				}
			}
			if o.Gfcn == nil {
				o.Gfcn = &fun.Cte{C: 10}
			}
		}

		// update time
		t += stg.Control.Tf
	}

	// log
	log.Printf("sim: file=%s/%s desc=%q nfunctions=%d nregions=%d nstages=%d linsol=%s itol=%g\n", dir, fn, o.Data.Desc, len(o.Functions), len(o.Regions), len(o.Stages), o.LinSol.Name, o.Solver.Itol)
	return &o
}