https://github.com/SimonUnterstrasser/ColumnModel
Raw File
Tip revision: 8c4e8c105fdfa552938c3dcbe71de99be72243f3 authored by SimonUnterstrasser on 15 September 2020, 15:26:46 UTC
Update README.md
Tip revision: 8c4e8c1
ComputeAgg_dummy.py
# script that controls the computation procedure
# first create the file params_gcc.txt and params.txt, which contain the preprocessor definitions and relevant parameters included in the Python script
# then create pre-processed interpretable source files in the given subdir
# then execute the Python program

import os
import shutil
import sys
import re
import glob
import platform
import time

#set working directory in which Python program is executed
FILEPATH = 'Sims1D/Verification/SediAgg/nz50_inst20_k05_dz10_py/'
iverboseoutput = 1
ilog_linux = 1

def intermediate_format(tmp):
    tmp = re.sub('^.+#GCC', '#GCC', tmp,flags=re.MULTILINE)
        #include flag, then each line is tested. otherwise only the first line of the multiline string matches the pattern;
        #"By default in python, the "^" and "$" special characters (these characters match the start and end of a line, respectively) only apply to the start and end of the entire string."
    tmp = tmp.replace('#','!comment#')
    tmp = tmp.replace('!comment#GCC','#')
    return(tmp)

def py_format(tmp):
    tmp = tmp.replace('!comment#','#')
    return(tmp)

def py_format_file_inplace(fn):
    f = open(fn,'r')
    c = f.read()
    f.close()
    c_pyf = py_format(c)
    f = open(fn,'w')
    f.write(c_pyf)
    f.close()

CurrDir =  os.getcwd()
print(CurrDir)

output_to_file_params_gcc = """
#define COMP  /* don't touch */
#/* the following PPDs (PreProcessor Directives) control how computations are performed.*/
#/*  ----------Kernel-------------   */
#define KERNEL 1  /* =0 Golovin kernel, =1 Long kernel, =2 Hall kernel, =3 product kernel */
#define LongK_Options 1 /* in case of Long kernel: =1 tabulated data, =2 computed data */
#define KERNEL_INTPOL 0 /* relevant for Hall/Long kernel: =1 kernal values are bilinearly interpolated ; =0 no nterpolation (a particular value is taken from the LookUp-Table) , =2 no interpolation, but linear instead of logarithmic mass grid is used */

#/* ---------- Initialization -------*/
#define INITV 1  /* = 1 Exponential distribution, =2 discrete distribution
# /* if computations are based on (small-size) discrete distributions, then no continuous size distributions are deduced. Instead, a discrete mass grid with multiples of the elemental mass is used. */


#/*----------- AON options ----------*/
#define AGG_MC 2 /* 0 no Multiple Collections, = 1 Integer Multiple Collection (conserves integer weights) = 2 Float Multiple Collection */
#define DISCRETE 0 /* = 0 continous use case, = 1 and 2 discrete use case (specify INITV =2 und AGG_MC = 1), Only multiples of a specified elemental mass are possible; = 1 weights are integer valued, = 2 only weights 1 */
#define LINEAR 0 /* =0  check all SIP combinations (quadratic sampling), = 1 linear sampling of SIP combinations */
#define LINEAR_LIMIT 0 /* options when nu_coll>nu_i,nu_j (the options are only active for LINEAR = 1):
#        =0: no special treatment, can lead to negative weights, nu_coll can be larger than max(nu_i,nu_j):
#        =1: limit nu_coll by 0.99*max(nu_i,j),
#        =2: equal partition SIPs with nu_i,j=0.5 min(nu_i,j) (recommended by Shima during GMD,2020 review)
#            in the present setup with nu-values being floats, equality of n_i and nu_j is not tested,
#            as this is an extremely rare event for the current implementation of SIP ensemble generation.
#            Currently, a collection between two equal weights SIPs generates a zero weight SIP which is removed.
#        =3: use an uneven splitting with 0.4 and 0.6 min(nu_i,j)
# NOTE:  for LINEAR = 0, always the limiter 0.99*max(nu_i,j) is used */
#define WELLMIXED 0 /* 0: classical 3D well mixed assumption, 1: 2D well mixed assumption, consider overtakes in each gridbox, 2, 3: 2D wellmixed assumption, consider overtakes in full column, 3: additionally accounts for overtakes across lower boundary, only relevant for period BCs */
#define REVERSE 1 /* =1: Reverse SIP processing start from highest SIP not lowest, benefitial for WM2D-variant */
#define COUNT_COLLS 0 /* track number of collisions and output to log file*/
#define SPEED_ZERO 1 /* = 1 do no test for zero weight SIPs inside AON */
#define SPEED_VECTOR 0 /* = 1 more vector evaluations */
#define WARN 0 /* =1 warnings in AON-algorithmus */

#/* ---------- 1D options ------------*/
#define COLUMN 1  /* = 0 classical box model, = 2 column model with additional sedimentation */
#define INFLUX_TOP 2  /* influx across top boundary: = 0 no influx , = 1 influx with given SD, =2 periodic BC, outfalling SIPs re-enter domain */
#define PROCESS 0 /* sedimentation and collisional growth are both active (=0), switch off sedimentation (=2) or collisional growth (=1) */
#define RANDOMZ 0 /* random placement of SIPs inside column after each time step */
#define TRACKCENTER 0 /* tracks SIPs centers in each grid box */
#define TRACKOUT 0 /* tracks all SIPs that cross lower boundary */

#/* ----------Plot options -----------*/
#define MOM_meanTD 1   /* plot mean moments, average over all instances and full column, TD = TotalDomain  */
#define GV_meanTD  0   /* plot mean size distribution, average over all instances and full column, TD = TotalDomain  */
#define MOM_prof   0   /* plot vertical profiles of mean moments, average over instances */
#define RZ_scatter 0   /* (r,z)-scatter plot */
#define FLUX_time  0   /* plot fluxes over time */

#/* -------- Reference Solution -----*/
#define IREF 1
# /*  = 0 no reference solution,
#     = 1 analytical Golovin solution or Long/Hall reference solution provided by Wang,
#     = 2 Alfonso Hall kernel reference solution
#     = 3 Alfonso product kernel reference solution
#     = 9 read Bott/Wang(?) simulation data, set path fp_ref */
"""

f = open('params_gcc.txt','w')
f.write(output_to_file_params_gcc)
f.close()

output_to_file_params = """
import math
#----------- parameter definitions--------------------------

    # time step in seconds
dt = 10.

    # simulated time in seconds
Tsim = 3600.  #3600

    #grid box volume
dV = 1. #in m^-3

dV_skal = 1  #increase volume by this factor and call init routine multiple times (increase by factor dV_skal)
dV = dV*dV_skal
dVi = 1./dV

    #number of realisations
nr_inst = 20
nr_ins_start = 0   # each realisation uses a different seed parameter. If a simulation is divided in several subsimulations, then provide a starting index of the current realisations range

    #storage interval of output
        #points in time, at which SIP data is saved and size disitributions can be produced
t_start_GVplot = 0   # in s
t_intervall_GVplot = 200   # in s

        #points in time, at which moment data is saved (usually a finer time grid is used here)
t_start_MOMsave = 0  # in s
t_intervall_MOMsave = 50 # in s

        #units of time axis in Moment and Flux plots
itime_legend = 2  # = 1 in seconds, =2 in minutes

#GCCif (KERNEL == 0)
b_original=1500   # in (cm^3)*(g^(-1))*(s^(-1))
b_golovin=b_original*(1e-6)*(1e3)*dt*dVi #  SI units (m^3*kg^(-1)*(s^(-1))  * s/m^3
#GCCendif /* (KERNEL == 0) */
#GCCif (KERNEL == 3)
C_original=5.49e10   # in (cm^3)*(g^(-2))*(s^(-1)) bzw auch (m^3*kg^(-2)*(s^(-1))
C_prod=C_original*dt *dVi #  SI units kg^(-2)

#GCCendif /* (KERNEL == 3) */


#GCCif (INITV == 1)
    #Density of water in kg/m**3
rho_w=1e3
    # conversion constant mass to radius
const_mass2rad=1./((4./3.)*math.pi*rho_w)

    #Properties of initial size distribution
        #the SingleSIP-method as described in Unterstrasser et al, 2017 is used to generate a SIP ensemble

        #physical parameters
            #Mean Droplet radius in m
r0=9.3e-6   # 9.3e-6  #50.e-6  #9.3e-6
            #mass concentration in kg/m^3
LWC=1e-3  #1e-3

        #numerical parameters
            #number of bins per mass decade (called kappa in the GMD-papers)
n10=5
            #number of mass decades
r10=18
            #starting mass of bin grid (min10=log10(mass in kg))
min10=-18
            #determines smallest mass/radius of SIP at which SIPs are eventually created
            # = 0: min10 is natural lower threshold, = 1: use 1.5625um, = 2: use 0.6um;
imlow=2
            #determines smallest SIP weight relative to the maximum SIP weight of the SIP ensemble Maximalgewicht
eta_nu=1e-9

            #upper bound for SIP number (determines the size of the SIP arrays)
nr_sip_max=15000

    #normalisation constant for SIP droplet masses, usually relevant for the discrete case
skal_m= 1.  # = 1 => no scaling of SIP droplet masses

#GCCendif /* (INITV == 1) */
#GCCif (INITV == 2)
    #Density of water in kg/m**3
rho_w=1e3
    # conversion constant mass to radius
const_mass2rad=1./((4./3.)*math.pi*rho_w)

iSIPinit_discrete = '1b'
if (iSIPinit_discrete == '1a'):
    #Maximum number of SIPs
    nr_sip_max=30
    #normalisation constants for concentration and mass
    skal_rad=17.0e-6 # represents radius of unit particle in m
    skal_m=(skal_rad**3.0)/const_mass2rad  # 1 represents an elemental mass, i.e mass of a 17um particle in SI units
    nplot = 40

if (iSIPinit_discrete == '1b'):
    #Maximum number of SIPs
    nr_sip_max=20*dV_skal

    #normalisation constants for concentration and mass
    skal_rad=17.0e-6 # represents radius of unit particle in m
    skal_m=(skal_rad**3.0)/const_mass2rad  # 1 represents an elemental mass, i.e mass of a 17um particle in SI units
    nplot = 40*dV_skal

if (iSIPinit_discrete == '2'):
    #Maximum number of SIPs
    nr_sip_max  = 100
    #normalisation constants for concentration and mass
    skal_rad    = 14.0e-6 # represents radius of unit particle in m
    skal_m      = (skal_rad**3.0)/const_mass2rad  # 1 represents an elemental mass, i.e mass of a 17um particle in SI units
    nplot       = 100
    skal_m2     = skal_m*skal_m
#GCCendif /* (INITV == 2) */

#GCCif (DISCRETE == 0)
    #definition bin grid for size disitrbution plots (can be chosen independtly of n10)
n10_plot=4
r10_plot=17
nplot=n10_plot*r10_plot
min10_plot=-18
#GCCendif /* (DISCRETE == 0) */

iaddsimREF=0
#GCCif (IREF > 0)
iaddsimREF = 1
#GCCendif /* (IREF > 0) */

#GCCif (COLUMN == 1)
#number of grid boxes in the column
nz = 50  #25

#type of spatial initialisation
i_init_1D = 6
    #  !    1 = empty domain
    #  !    2 = top GB only
    #  !    3 = top half domain
    #  !    4 = linearly decaying over total column from 2*g_init t
    #  !    5 = linearly decaying over top half from 2*g_init to 0
    #  !    6 = total domain
    #  !    7 = linearly decaying over top quarter from 2*g_init to
    #  !    8 = sin()-hill over top half with 2*g_init max peak
    #  !    9 = sin()-hill over top quarter with 2*g_init max peak

    #Mesh size
dz=10. # in m

    #base plane of grid box
dA=dV/dz
dAi=1./dA

    #probabilistic SIP influx, average number of SIP per GB and bin
nr_SIPs_skal = 1

    #dummy z-position for unused SIPs, do not change
zNan=100000

zCol=nz*dz

#### CHANGE fp_Bott
fp_Bott = "/athome/unte_si/_data/Themen/Aggregation/Bott_1D/"
# fp_ref  = fp_Bott + "testcases_onlysedi/quarterdomSIN_zeroinflow_1km_dz10m_FD3/"
fp_ref  = fp_Bott + "testcases_onlysedi/quarterdomSIN_zeroinflow_1km_dz5m_FD3_iscal16_R050/"

#GCCendif /* (COLUMN == 1) */

    #controls the extent of logging output onto screen
iPM = 0


"""
f = open('params.txt','w')
f.write(output_to_file_params)
f.close()
#--------------------------------generation of parameter files finished----------------------------------------


# ----------------------------------preprocess and run Python code -------------------------------------------------
# the full source files will be saved in subfolder full_source (FILEPATH_SOURCE)
# the preprocessed files will be generated and executed in folder FILEPATH

#list of source code files (separate lists for files with/without preprocessor directives)
list_module_gcc_files = ('CompSim.gcc.py', 'AON_Alg.gcc.py', 'Kernel.gcc.py', 'PlotSim.gcc.py', 'Referenzloesung.gcc.py', 'SIPinit.gcc.py', 'Sedimentation.gcc.py')
list_module_nogcc_files = ('Misc.nogcc.py',) # a 1-element needs a comma

FILEPATH_SOURCE = os.path.join(FILEPATH,'full_source')

print('current working directory:\n', FILEPATH)

    #copy files
if not os.path.isdir(FILEPATH_SOURCE):
    os.makedirs(FILEPATH_SOURCE)

for file2move in ('params.txt','params_gcc.txt'):
    # if dst is given as folder path plus filename, then move overwrites a potentially existing file with the same name in the dst folder
    shutil.move(file2move, os.path.join(FILEPATH_SOURCE, file2move))

name_current_script = sys.argv[0]
shutil.copy(name_current_script, FILEPATH)

filelist2copy = list_module_gcc_files + \
                list_module_nogcc_files
for file2copy in filelist2copy:
    shutil.copy(file2copy, FILEPATH_SOURCE)

os.chdir(FILEPATH)

#pre-process all Python code that is listed in list_module_gcc_files
#workaround for application of gcc necessary, as both GCC and Python use # to indicate directive and comments respectively
#temporarily use a different character sequence instead of # for Python comments
#additionally, GCC directives in the .gcc.py files use #GCC as marker

tmp = intermediate_format(output_to_file_params)

if (iverboseoutput == 1):
    f = open('params.tmptxt','w') #verbose output
    f.write(tmp) #verbose output
    f.close() #verbose output

f = open('params.fpp','w')
f.write(output_to_file_params_gcc+tmp)
f.close()
os.system('gcc -E -P -C params.fpp > params.txt')

print(os.listdir())
print(os.listdir('full_source'))

for file_gcc_py in list_module_gcc_files:
    print('process file {}'.format(file_gcc_py))
    filebasename = file_gcc_py.replace('.gcc.py','')
    f = open(os.path.join('full_source', file_gcc_py),'r')
    content = f.read()
    f.close()
    content_imf = intermediate_format(content)
        #suffix _imf = intermediate format

    if (iverboseoutput == 1):
        f = open(filebasename+'.tmp.tmptxt','w') #verbose output
        f.write(content_imf) #verbose output
        f.close() #verbose output

    f = open(filebasename+'.fpp','w')
    f.write(output_to_file_params_gcc+content_imf)
    f.close()

    #gcc -E -P -C ${base}.fpp > ${base}.tmptxt
    command_eval = 'gcc -E -P -C {0}.fpp -o {0}.tmptxt'.format(filebasename)
    #command_eval = 'gcc -E -P -C {0}.fpp -o {0}.tmptxt'.format(FILEPATH_OUT+filebasename)
    #print('call preprocessor with command:\n', command_eval)
    os.system(command_eval)

    f = open(filebasename+'.tmptxt','r')
    content = f.read()
    f.close()

    content_pyf = py_format(content)
    f = open(filebasename+'.py','w')
    f.write(content_pyf)
    f.close()

py_format_file_inplace('params.txt')

    #simply copy all Python code that is listed in list_module_gcc_files
for file_nogcc_py in list_module_nogcc_files:
     print('copy file {}'.format(file_nogcc_py))
     filebasename = file_nogcc_py.replace('.nogcc.py','')
     os.rename(os.path.join('full_source',filebasename+'.nogcc.py'), filebasename+'.py')

#preparation of source code finished----------------------------------------

f = open('log.txt','w')
f.write(name_current_script + '\n')
f.write(platform.uname()[1] + '\n')
f.close()

starttime = time.time()

# start program
print('start execution')
#### CHANGE: call python 3 with argument CompSim.py
#use local python anaconda installation
os.system('/net/lx116/export/home/unte_si/anaconda3/bin/python3 CompSim.py')
#with Profiling
#os.system('/net/lx116/export/home/unte_si/anaconda3/bin/python3 -m cProfile -o Profiling.dat -s time CompSim.py')

print("execution start and end time")
endtime = time.time()
print(time.asctime(time.localtime(starttime)),
      time.asctime(time.localtime(endtime  )))
f = open('log.txt','a')
f.write('total computing time in sec: '+ str(int(endtime-starttime)) + '\n')
f.close()

#clean up
print("Clean Up")
filelist_tobedeleted = glob.glob("*.fpp") + glob.glob("*.s") + glob.glob("*.tmptxt")
for file in filelist_tobedeleted:
    os.remove(file)

subdir = os.path.join('CodeCompute','full_source')
if not os.path.isdir(subdir):
    os.makedirs(subdir)

filelist_tobemoved = glob.glob("*.py") + glob.glob("*txt") + glob.glob("full_source/*")

for file2move in filelist_tobemoved:
    # if dst is given as folder path plus filename, then move overwrites a potentially existing file with the same name in the dst folder
    shutil.move(file2move, os.path.join('CodeCompute', file2move))

# filelist_tobemoved =
# for file2move in filelist_tobemoved:
    # # if dst is given as folder path plus filename, then move overwrites a potentially existing file with the same name in the dst folder
    # shutil.move(file2move, os.path.join('CodeCompute',  file2move))

os.rmdir('full_source')
#dest = shutil.move('full_source', 'CodeCompute/', copy_function = shutil.copytree)

os.system('gzip SIP.dat; gzip Moments.dat')
back to top