def set(self, m3d): ny = self.ny y0 = self.y0 tracer = self.tracer input = self.input text = "" if input is not None: file = util.get_hdf5_file(m3d, self, input) text = text + "set from input file:\n {}\n".format(file.filename) else: values = [t[1] for t in tracer] text = text + "set from init values:\n" text = text + " {:10} {}\n".format("name", "value") for i in range(ny): # Name, Value, Unit, Description name = str(tracer[i][0]) value = float(tracer[i][1]) if input is not None: util.set_vector_from_hdf5_file(m3d, y0[i], file, name) else: y0[i].set(value) text = text + " {:10.10} {:<16e}\n".format(name, value) text = text.rstrip() util.debug(m3d, self, text, level=1)
def __init__(self, m3d): # get 'grid_mask' variable from file filepath = util.get_key(m3d, self, m3d.config, "Grid", str) gridfile = util.get_hdf5_file(m3d, self, filepath) grid = util.get_key(m3d, self, gridfile, "grid_mask", Dataset) #gridfile["grid_mask"] # masks self.mask3d = mask3d = (grid[...] != grid.fillvalue) self.mask2d = mask2d = mask3d[0, ...] # not needed any more gridfile.close() # vector and profiles self.nv = nv = mask3d.sum() # vector length self.np = mask2d.sum() # profile count self.npi = mask3d.sum(axis=0)[mask2d] # each profile length # index permutation from nc/3d to tmm/1d nc3d = mask3d[...].astype(">i4") (nz, ny, nx) = nc3d.shape nc3d[mask3d] = range(nv) nc3d[mask3d] = nc3d[mask3d] + 1 nc1d = nc3d.reshape(nz, ny * nx).T.flat self.nc2tmm = nc1d[nc1d != 0] - 1 # debug util.debug(m3d, self, self, level=1)
def __init__(self, m3d): self.config = config = m3d.config.get("BGC") if config is None: self.use_bgc = False else: self.use_bgc = True self.name = util.get_key(m3d, self, config, "Name", str) # load bgc module # must be placed in metos3d/bgc/<<name>>/<<sources>> # must be compiled with: f2py -c <<sources>> -m <<name>> # call to bgc routine must apply to: # fortran: metos3dbgc(ny, nx, nu, nb, nd, dt, q, t, y, u, b, d) # python: metos3dbgc(dt,q,t,y,u,b,d,[ny,nx,nu,nb,nd]) # module name: exchange '-' to '_' modname = self.name.replace("-", "_") self.mod = importlib.import_module("bgc." + self.name + "." + modname) self.init_parameter(m3d) self.init_boundary_data(m3d) self.init_domain_data(m3d) # debug util.debug(m3d, self, self, level=1)
def solve(self, m3d): util.debug(m3d, self, "Solve ...", level=1) tracer = m3d.tracer time = m3d.time ny = tracer.ny y0 = tracer.y0 nl = self.nl yl = self.yl i = 0 # print("rank: {}, i: {}, y[i]: {}, y0[i]: {}".format(m3d.rank, i, yl[i], y0[i])) util.copy_vector_list(y0, yl) # print("rank: {}, i: {}, y[i]: {}, y0[i]: {}".format(m3d.rank, i, yl[i], y0[i])) # for i in range(ny): # print("rank: {}, i: {}, y[i]: {}, y0[i]: {}".format(m3d.rank, i, yl[i], y0[i])) ## yl[i] = y0[i] # y0[i].copy(yl[i]) ## yl[i].copy(y0[i]) # print("rank: {}, i: {}, y[i]: {}, y0[i]: {}".format(m3d.rank, i, yl[i], y0[i])) # import sys # sys.exit(1) for i in range(nl): util.debug(m3d, self, "{}".format(i), level=1) time.step(m3d, yl)
def __init__(self, m3d): comm = m3d.comm grid = m3d.grid # store own copy of comm for __str__ self.comm = m3d.comm self.size = size = comm.size self.rank = rank = comm.rank # vector length, profile count, profile depths nv = grid.nv np = grid.np npi = grid.npi # profiles to processes starts = npi.cumsum() - npi weights = starts + 0.5 * npi ranks = numpy.floor((weights / nv) * size) # profiles per process punique, pindex, pcount = numpy.unique(ranks, return_index=True, return_counts=True) pprev = pcount.cumsum() - pcount # vector shares vcount = numpy.array( [npi[i:i + c].sum() for i, c in zip(pindex, pcount)]) vprev = vcount.cumsum() - vcount # my rank self.nploc = pcount[rank] self.npprev = pprev[rank] self.nvloc = vcount[rank] self.nvprev = vprev[rank] # index pointers for bgc # numpy.append(0, numpy.cumsum(nnzrow)).astype("i4") self.npiloc = npi[self.npprev:self.npprev + self.nploc] self.indptr = numpy.append(0, numpy.cumsum(npi)) self.indptrloc = numpy.append(0, numpy.cumsum(self.npiloc)) # self.np_indptr = numpy.append(0, numpy.cumsum(npi[self.npprev:self.npprev+self.nploc])) # self. # compute max diff to optimal self.opt = opt = float(nv) / size self.maxdiff = maxdiff = numpy.amax( numpy.abs(numpy.array(vcount) - opt)) # debug util.debug(m3d, self, self, level=1)
def set(self, m3d): text = "" if self.use_boundary: nb = self.nb nbi = self.nbi b = self.b boundary = self.boundary path = self.boundary_path text = text + "boundary:\n" text = text + " {:10.10} {}\n".format("name", "file") for i in range(nb): # Name, Count, Description, Unit, File varname = boundary[i][0] filename = boundary[i][4] file = util.get_hdf5_file(m3d, self, path + filename) text = text + " {:10.10} {}\n".format(varname, path + filename) for j in range(nbi[i]): pass util.set_vector_from_hdf5_file(m3d, b[i][j], file, varname, index=j) if self.use_domain: nd = self.nd ndi = self.ndi d = self.d domain = self.domain path = self.domain_path text = text + "domain:\n" text = text + " {:10.10} {}\n".format("name", "file") for i in range(nd): # Name, Count, Description, Unit, File varname = domain[i][0] filename = domain[i][4] file = util.get_hdf5_file(m3d, self, path + filename) text = text + " {:10.10} {}\n".format(varname, path + filename) for j in range(ndi[i]): util.set_vector_from_hdf5_file(m3d, d[i][j], file, varname, index=j) text = text.rstrip() util.debug(m3d, self, text, level=1)
def __init__(self, m3d): self.config = config = m3d.config.get("TMM") if config is None: self.use_tmm = False else: self.use_tmm = True self.path = util.get_key(m3d, self, config, "Path", str) self.init_explicit(m3d) self.init_implicit(m3d) # debug util.debug(m3d, self, self, level=1)
def __init__(self, m3d): config = util.get_key(m3d, self, m3d.config, "Solver", dict) self.type = util.get_key(m3d, self, config, "Type", str) self.nl = util.get_key(m3d, self, config, "Count", int) self.mon = util.get_key(m3d, self, config, "Monitor", bool) self.yl = [] for y in m3d.tracer.y0: self.yl.append(y.duplicate()) # debug util.debug(m3d, self, self, level=1)
def __init__(self, m3d): config = util.get_key(m3d, self, m3d.config, "Time", dict) self.t0 = util.get_key(m3d, self, config, "Start", float) self.nt = util.get_key(m3d, self, config, "Count", int) self.dt = util.get_key(m3d, self, config, "Step", float) tracer = m3d.tracer ny = tracer.ny y0 = tracer.y0 bgc = m3d.bgc b = bgc.b nb = bgc.nb nbi = bgc.nbi bj = [] for bi in b: bj.append(bi[0].duplicate()) self.bj = bj d = bgc.d nd = bgc.nd ndi = bgc.ndi dj = [] for di in d: dj.append(di[0].duplicate()) self.dj = dj yj = [] yexpj = [] qj = [] for yi in y0: yj.append(yi.duplicate()) yexpj.append(yi.duplicate()) qi = yi.duplicate() qi.zeroEntries() qi.assemble() qj.append(qi) self.yj = yj self.yexpj = yexpj self.qj = qj # debug util.debug(m3d, self, self, level=1)
def __init__(self, m3d): config = util.get_key(m3d, self, m3d.config, "Tracer", dict) self.tracer = tracer = util.get_key(m3d, self, config, "Name, Value, Unit, Description", list) self.output = config.get("Output") self.input = config.get("Input") # global and local vector length nv = m3d.grid.nv nvloc = m3d.load.nvloc self.ny = ny = len(tracer) self.y0 = util.create_petsc_vectors(ny, (nvloc, nv)) # debug util.debug(m3d, self, self, level=1)
def run(self): """ runs a simulation, loop over model years, spin up perform time steps, interpolate, boundary and domain data, matrices, evaluate bgc model, apply transport, u = [u1, ..., um] bj = [[]] dj = [[]] yj = [yj1, ..., yjny] qj = [qj1, ..., qjny] Aimpj = diag([Aimpj, ..., Aimpj]) Aexpj = diag([Aexpj, ..., Aexpj]) yjp1 = Aimpj * (Aexpj * yj + qj(dt, tj, yj, u, bj, dj)) yjp1 = [yjp11, ..., yjp1ny] """ util.debug(self, self, "--- set " + 100 * "-", level=1) self.tracer.set(self) self.bgc.set(self) self.tmm.set(self) util.debug(self, self, "--- solve " + 100 * "-", level=1) self.solver.solve(self) util.debug(self, self, "--- save " + 100 * "-", level=1) self.tracer.save(self)
def __init__(self, argv): """ check computation model ... print version, print number of processes, attributes ... creates instances ... initialize metos3d context, Parameters: argv: list with command arguments, file path of yaml conf file """ # version and runtime context self.version = version = VERSION self.comm = comm = PETSc.COMM_WORLD self.size = size = comm.size self.rank = rank = comm.rank # config self.config = util.get_config_from_yaml_file(self, argv) # debug level self.debug = util.get_key(self, self, self.config, "Debug", int) util.debug(self, self, "--- init " + 100 * "-", level=1) util.debug(self, self, self, level=1) # init self.grid = Grid(self) self.load = Load(self) self.tracer = Tracer(self) self.bgc = BGC(self) self.tmm = TMM(self) self.time = Time(self) self.solver = Solver(self)
def step(self, m3d, yl): util.debug(m3d, self, "time step ...", level=1) tracer = m3d.tracer ny = tracer.ny y0 = tracer.y0 bgc = m3d.bgc u = bgc.u tmm = m3d.tmm t0 = self.t0 dt = self.dt nt = self.nt yj = self.yj qj = self.qj yexpj = self.yexpj bj = self.bj dj = self.dj if m3d.tmm.use_tmm: if m3d.tmm.use_explicit: self.Aexpj = m3d.tmm.Aexp[0].duplicate() if m3d.tmm.use_implicit: self.Aimpj = m3d.tmm.Aimp[0].duplicate() Aexpj = self.Aexpj Aimpj = self.Aimpj for i in range(ny): yj[i] = yl[i] tstart = time.time() for j in range(nt): tstartdelta = time.time() tj = t0 + j * dt if bgc.use_bgc: # util.debug(m3d, self, "use_bgc", level=1) if bgc.use_boundary: util.debug(m3d, self, "use_boundary", level=1) b = bgc.b nb = bgc.nb nbi = bgc.nbi # interpolate for ib in range(nb): alpha, ialpha, beta, ibeta = util.interpolate( nbi[ib], tj) # bj[ib] = alpha * b[ib][ialpha] + beta * b[ib][ibeta] bj[ib] = b[ib][ialpha] # VecCopy bj[ib] = alpha * bj[ib] # VecScale bj[ib] = bj[ib] + beta * b[ib][ibeta] # VecAXPY if bgc.use_domain: util.debug(m3d, self, "use_domain", level=1) d = bgc.d nd = bgc.nd ndi = bgc.ndi # interpolate for id in range(nd): alpha, ialpha, beta, ibeta = util.interpolate( ndi[id], tj) # dj[id] = alpha * d[id][ialpha] + beta * d[id][ibeta] dj[id] = d[id][ialpha] # VecCopy dj[id] = alpha * dj[id] # VecScale dj[id] = dj[id] + beta * d[id][ibeta] # VecAXPY # qj[0].view() m3d.bgc.q(m3d, dt, qj, tj, yj, u, bj, dj) # yj[0].view() # qj[0].view() # import sys # print(dt) # print(qj) # print(yj) # qj[0].view() # print(qj[0][:]) # print(qj[1][:]) # print(yj[0][:]) # print(yj[1][:]) # print(u) # print(bj) # print(dj) # sys.stdout.flush() # sys.exit(1) # if bgc.use_bgc: qj is set to sms # else: qj stays zero if tmm.use_tmm: # util.debug(m3d, self, "use_tmm", level=1) if tmm.use_explicit: # util.debug(m3d, self, "use_explicit", level=1) nexp = tmm.nexp Aexp = tmm.Aexp # interpolate alpha, ialpha, beta, ibeta = util.interpolate(nexp, tj) # print((alpha, ialpha, beta, ibeta)) # Aexpj = alpha * Aexp[ialpha] + beta * Aexp[ibeta] Aexpj = Aexp[ialpha] # MatCopy Aexpj = alpha * Aexpj # MatScale Aexpj = Aexpj + beta * Aexp[ibeta] # MatAXPY # Aexp[ialpha].view() # print(Aexpj.assembled) # apply explicit # m3d.tmm.apply(m3d, Aexpj, yj) for i in range(ny): # Aexpj.multAdd(yj[i], qj[i], yexpj[i]) yexpj[i] = Aexpj * yj[i] + qj[i] # yexpj[0].view() # print(yj[0][:10]) # print(qj[0][:10]) # print(yexpj[0][:10]) # print((Aexp[0]*yj[0])[:10]) # else: # # we need to copy at least one time # yexpj = yj # #add bgc # if bgc.use_bgc: # util.debug(m3d, self, "use_bgc", level=1) # for i in range(ny): # yexpj[i] = yexpj[i] + qj[i] ## yexpj = yexpj + qj if tmm.use_implicit: # util.debug(m3d, self, "use_implicit", level=1) nimp = tmm.nimp Aimp = tmm.Aimp # interpolate alpha, ialpha, beta, ibeta = util.interpolate(nimp, tj) # Aimpj = alpha * Aimp[ialpha] + beta * Aimp[ibeta] Aimpj = Aimp[ialpha] # MatCopy Aimpj = alpha * Aimpj # MatScale Aimpj = Aimpj + beta * Aimp[ibeta] # MatAXPY # apply implicit # m3d.tmm.apply(m3d, Aimpj, yj) # yj = Aimpj*yexpj for i in range(ny): yj[i] = Aimpj * yexpj[i] # yj[0].view() tenddelta = time.time() util.debug(m3d, self, "j: {:05d}, tj: {:f}, delta: {:.3f}, s: {:.3f}".format( j, tj, tenddelta - tstartdelta, tenddelta - tstart), level=1)
def set(self, m3d): if not self.use_tmm: util.debug(m3d, self, "none", level=1) return else: nv = m3d.grid.nv nvloc = m3d.load.nvloc # explicit self.nexp = 0 self.Aexp = [] if self.use_explicit: util.debug(m3d, self, "explicit ...", level=1) # Name, Count, File self.nexp = nexp = self.explicit[1] filepath = self.path + self.explicit[2] # we assume petsc mat aij format in a hdf5 file f = util.get_hdf5_file(m3d, self, filepath) nrow = f["nrow"].size ncol = f["ncol"].size nnz = f["nnz"].size nnzrow = f["nnzrow"] nnzrow_max = numpy.max(nnzrow) # however, we use index pointers for the petsc call indptr = numpy.append(0, numpy.cumsum(nnzrow)).astype("i4") colidx = f["colidx"] if not nv == nrow == ncol: util.error( m3d, "Dimensions of explicit matrix: {} do not match vector length: {}" .format((nrow, ncol), nv)) sys.exit(1) for i in range(nexp): aij = f["aij"][i, ...] A = PETSc.Mat() A.create() A.setType("aij") # PETSc.Mat.Type.AIJ, A.setSizes(((nvloc, nv), (nvloc, nv))) A.setUp() start, end = A.owner_range A.setPreallocationNNZ((nnzrow_max, nnzrow_max)) A.setValuesCSR(indptr[start:end + 1] - indptr[start], colidx[indptr[start]:indptr[end]], aij[indptr[start]:indptr[end]]) A.assemble() self.Aexp.append(A) # implcit self.nimp = 0 self.Aimp = [] if self.use_implicit: util.debug(m3d, self, "implicit ...", level=1) self.nimp = nimp = self.implicit[1] filepath = self.path + self.implicit[2] # we assume petsc mat aij format in a hdf5 file f = util.get_hdf5_file(m3d, self, filepath) nrow = f["nrow"].size ncol = f["ncol"].size nnz = f["nnz"].size nnzrow = f["nnzrow"] nnzrow_max = numpy.max(nnzrow) # however, we use index pointers for the petsc call indptr = numpy.append(0, numpy.cumsum(nnzrow)).astype("i4") colidx = f["colidx"] if not nv == nrow == ncol: util.error( m3d, "Dimensions of implicit matrix: {} do not match vector length: {}" .format((nrow, ncol), nv)) sys.exit(1) for i in range(nimp): aij = f["aij"][i, ...] A = PETSc.Mat() A.create() A.setType("aij") # PETSc.Mat.Type.AIJ, A.setSizes(((nvloc, nv), (nvloc, nv))) A.setUp() start, end = A.owner_range A.setPreallocationNNZ((nnzrow_max, nnzrow_max)) A.setValuesCSR(indptr[start:end + 1] - indptr[start], colidx[indptr[start]:indptr[end]], aij[indptr[start]:indptr[end]]) A.assemble() self.Aimp.append(A)
def save(self, m3d): util.debug(m3d, self, "Tracer: save {}".format(""), level=1)