Scale-dbl

From Arbeitsgruppe Kuiper
Jump to navigation Jump to search

A little Python tool to scale fields stored in PLUTO's dbl-files.

If you use it for creating new initial conditions for a -restart (what else?), you have to run it in the source run-folder, then move the modified dbl-file(s) (having a "scaled" in the file name) to the new run-folder and rename them to their standard form.

#!/usr/bin/env python3
#
# Scale the contents of a PLUTO's dbl-file,
# must be run inside the data directory.
#
# L.B. 2024

import os
from sys import exit,argv
import numpy as np

me = os.path.basename(argv[0])

if len(argv) < 4:
    exit(f"usage: {me} <n_out> <fact> <field_1> ...\nwith <n_out> being int, <fact> float and <fields> being strings")

out_nr = int(argv[1])  # the number of the dbl-file
fact = float(argv[2])  # the multiplication factor
fields = argv[3:]      # fields as listed in 'dbl.out'

with open("dbl.out","r") as dbl_out:
    for line in dbl_out:
        line = line.split()
        # nout t dt nstep single_file little var1 var2 ..
        # cf. 12.1.1 in https://plutocode.ph.unito.it/userguide.pdf
        if line[5] != "little":
            exit(f"{me}: need doubles in little endian, quitting...")
        if int(line[0]) == out_nr:
            field_nrs = []
            fields_ok = []
            for field in fields:
                if field in line:
                    fields_ok.append(field)
                    field_nrs.append(line.index(field)-6)
                else:
                    print(f"{me}: field '{field}' not found")
            if not field_nrs:
                exit(f"{me}: none of the fields found, quitting...")
            fields = fields_ok
            single = line[4]=="single_file"
            break
    else:
        exit(f"{me}: dbl-file number {out_nr} does not exist, quitting...")


# get number of cells from file 'grid.out':
N = 1
with open("grid.out","r") as grid_out:
    for line in grid_out:
        if line[0] == "#":  # information is in comment block
            line = line.split()
            if len(line)>1 and line[1][0]=="X":
                N *= int(line[line.index("point(s),")-1])
        else:
            break

if N == 1:
    exit(f"{me}: could not determine number of grid cells, quitting...")

# read, scale, write:
for file in (["data"] if single else fields):
    dbl_fn = f"{file}.{out_nr:04}.dbl"
    print(f"{me}: reading '{dbl_fn}'")
    with open(dbl_fn,"rb") as dbl_in:
        data = np.fromfile(dbl_in,dtype="<f8").reshape((-1,N)) # N doubles for each field

    dbl_fn = file
    if single:
        for f,field_nr in enumerate(field_nrs):
            print(f"{me}: multiplying {N} doubles of {fields[f]}-data by {fact}")
            data[field_nr,:] *= fact
        dbl_fn += "_"+'+'.join(fields)
    else:
        print(f"{me}: multiplying {N} doubles by {fact}")
        data[0,:] *= fact

    dbl_fn += f"-scaled.{out_nr:04}.dbl"
    print(f"{me}: writing result into '{dbl_fn}'")
    with open(dbl_fn,"wb") as dbl_out:
        data.tofile(dbl_out)