Skip to content
Snippets Groups Projects
Commit 548011d4 authored by Vitor Silva's avatar Vitor Silva
Browse files

adiosFOAM data extractor script.

parent d5e6bc06
Branches
No related tags found
No related merge requests found
#/usr/bin/python3
import subprocess as subp
import sys
import os
import adios2
import re
import numpy as np
import argparse
def findAll(name, path):
result = []
for root, dirs, files in os.walk(path):
if name in files:
result.append(os.path.join(root))
return result
# HEADER
header = "// Adios2-OpenFOAM visualization data extractor.\n// Forschugszentrum Juelich, 2023\n// Author: Vitor Silva, v.silva@fz-juelich.de\n// ---------------------------------------------\n\n"
# Get subdirectories from the adiosData basedir
ofdir = "../testcavity/"
#ofdir = "/p/project/ccstao/silva2/CoEC/chokedNozzle/"
parser = argparse.ArgumentParser(prog='adiosFOAM-data-extractor',
description='Extracts field data from an OpenFOAM simulation stored in ADIOS2 files by specifying the case directory and the list of timesteps',
epilog='Nothing to comment...')
parser.add_argument('-c','--case', help='OpenFOAM case directory', type=str, required=True)
parser.add_argument('-t','--timestep', action='append', help='Time-steps to be extracted', required=True)
args = parser.parse_args()
# use data read from argparser
case = vars(args)['case']
tstep = vars(args)['timestep']
if case:
ofdir = case
# directories defined after parsing, of course.
# If nothing, it goes to a default directory
datadir = ofdir+"adiosData/"
procrefdir = ofdir+"processor0/"
directories = os.listdir(datadir)
# IMPORTANT: That will not work for directores with timing in integer
# range. To be fixed later.
dirs = [f for f in directories if re.search(r"\d+.\d+",f)]
dirs.sort()
# Use command-line arguments if they are given
if tstep:
# dirs = [tstep[i] for i in tstep]
dirs = tstep[0].split()
# In order to check what are the fields for an OpenFOAM solver,
# the way of doing besides parsing Solver source-code is to
# read the contents of directory 0.
#
# we assume is is there for this script
zerodir = ofdir+"0"
files = os.listdir(zerodir)
# Get rid of any directories if present
fields = [x for x in files if os.path.isfile(os.path.join(zerodir, x))]
### Tip:
# if there are more fields in the adiosFile than those on directory /0
# just touch a file with the name. These files, even empty, will be read
# by the script and the data for them, if present on adios file, will be
# dumped
#
# for example:
#
# touch Q Lambda2 pMean
# the nested loop has the outermost loop adios2.read()
# and the innerloop as processors (blockids in adios2)
# in order to avoid opening and closing big adios2 files
# to only keep stdfiles in the inner loop.
# closing is done by demand.
for adiosts in dirs:
# Access attributes
fh = adios2.open(datadir+adiosts, "r")
adiosatts = fh.available_attributes()
adiosvars = fh.available_variables()
# Get the number of processes. This is the number of blocks in each variable
# The value will be later used to loop through every processor and block
nprocs = fh.read_attribute("/openfoam/nProcs")
# Need to open one case 0 data file to replicate boundaries
# that must be done for every decomposed directory since everyone
# have their own boundaries. Any file works.
# (No boundary data is written, but just listed
# Loop the list and write empty boundaries.
# the keyword 'FoamFile' is the header and need to be fully written
# part of the data needed is obtained from the adiosData
# Get mandatory fields
arc = adiosatts['/openfoam/endian']['Value'] #"LSB;Label=32;scalar=64"
arc = arc.strip('\"')
label = adiosatts['/openfoam/label']['Value']
scalar = adiosatts['/openfoam/scalar']['Value']
# Attributes are queried only once, unless they're are
# different for eveyr variable.
fdict = dict()
# keep track of failing fields to be removed from the list
# after the loop
failing = []
for f in fields:
try:
classe = adiosatts["region0/field/"+f+"/class"]['Value']
classe = classe.strip('\"')
dimen = adiosatts["region0/field/"+f+"/dimensions"]['Value']
dimen = dimen.replace(',', '')
dimen = dimen.replace('{ ', '')
dimen = dimen.replace(' }', '')
fdict[f] = [classe, dimen]
except:
print(' --- ERROR --- : field <{}> cannot be read or not found in adios2 file.'.format(f))
failing.append(f)
# remove all failed elements from the fields list
[fields.remove(elem) for elem in failing]
k=0
while k<nprocs:
# for every decomposed directory:
offile = open(ofdir+"processor"+str(k)+"/0/"+files[0], "r")
basedata = offile.read()
offile.close()
# Find the keywords
res = re.findall("\w+[\s]*{", basedata)
reslistwords = [re.findall("\w+", i) for i in res]
# need a join to have only one list of strings after the 2nd re.findall
reswords = [' '.join(s) for s in reslistwords]
# remove 'FoamFile' from the list that will be iterated
foamfilestr = reswords.pop(0)
bfstr = reswords.pop(0)
# Must loop through all files (in files)
for field in fields:
# make sure directores exist before trying to write the file
if not os.path.isdir(ofdir+"processor"+str(k)+"/"+adiosts):
os.mkdir(ofdir+"processor"+str(k)+"/"+adiosts)
fhl = open(ofdir+"processor"+str(k)+"/"+adiosts+"/"+field, "w")
# FoamFile struct
fhl.write(header)
fhl.write(foamfilestr+"\n{\n")
fhl.write("\tversion\t\t2.0;\n")
fhl.write("\tformat\t\tascii;\n")
fhl.write('\tarch\t\t\"{0};Label={1};scalar={2}";\n'.format(arc, label, scalar))
fhl.write("\tclass\t\t"+fdict[field][0]+";\n")
fhl.write('\tlocation\t"{0}";\n'.format(adiosts)) #iterating over directories on adiosData
fhl.write("\tobject\t\t"+field+";\n")
fhl.write("}\n\n")
# dimensions
fhl.write("dimensions\t["+fdict[field][1]+"];\n\n")
# internalField
# It is written only for the corresponding adios block_id
# processor X get block_id X
if(fdict[field][0] == "volScalarField"):
lstype = "scalar"
else: #volVectorField
lstype = "vector"
# <adios file handler>.read('region0/field/<campo>', int(dimension))
# the k int iteratated matches processor which matches de block on ADISO2 file
fieldk = fh.read("region0/field/"+field, k)
datadim = fieldk.ndim
fieldklist = fieldk.tolist()
fhl.write('internalField\tnonuniform List<{0}> {1}'.format(lstype, fieldk.shape[0]))
## iterate for non-scalar values. For scalar uses the if formats non-iterables
fhl.write(' (')
for variable in fieldklist:
if(datadim == 1):
fhl.write('{} '.format(variable))
else:
fhl.write('({} {} {}) '.format(*variable))
fhl.write(');\n\n')
# dummy boundaryFields
fhl.write(bfstr+"\n{\n")
for word in reswords:
if 'proc' in word:
fhl.write("\t"+word+"\n\t{\n\t\ttype\tprocessor;\n\t}\n")
else:
fhl.write("\t"+word+"\n\t{\n\t\ttype\tempty;\n\t}\n")
fhl.write("}\n\n")
fhl.close()
k+=1
# End
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment