Files
LBPM/workflows/Preprocess/preprocess_utils.py
2016-10-10 11:13:39 -04:00

273 lines
9.1 KiB
Python

#!/usr/bin/env python
import os
import numpy as np
import csv
def get_LBM_parameters(csv_file_name,base_name_suffix,image_format,ift=24,Depth=8.8,**kwargs):
# 'ift': dyne/cm
# 'Depth': micron
# Users need to provide the following information
# 1. surface tension in physical unit
# 2. physical depth in physical unit
# 3. experimental file e.g. *.csv
# 4. Other optional information, which is summarised in a dictionary
# 'Para', including:
# Para['D']: characteristic length
# Para['alpha']: LBM parameters, controlling the surface tension
# Para['fitting']: LBM parameters, extracted from the bubble test
# Experimental definitions - units are converted in terms of N, m
micron=1e-6
cm=1e-2
dyne=1e-5
kPa=1e3
Para={'D':30.0} # characteristic length
#length=500*micron
# LBM related parameters
# TODO: for parameters like 'alpha', you should find a way to
# communicate with other functions
# It cannot be hard-coded here
Para['alpha'] = 0.01
Para['fitting'] = 5.796
# Check users' input arguments
for key in kwargs:
if key in Para.keys():
Para[key]=kwargs[key]
else:
print "Error: "+key+" is not a valid input !\n"
print "Error: LBM pressure boundaries are not set successfully !"
return
#end if
#end for
IFT = Para['alpha'] * Para['fitting']
# 'ift' is the surface tension from the experiment in physical unit
ift=ift*dyne/cm # This converts the unit of 'ift' to SI unit
# Process the experimental data
# 'EXP_data' : original experimental data
# It is a recorded numpy array, which means that its component
# can be accessed by 'EXP_data.sw' or 'EXP_data['sw']'
# About 'EXP_data' see more information from the function 'read_csv'
EXP_data = read_csv(csv_file_name)
# A few notes for the experimental data
# 'Jwn': mean curvature in physical unit (e.g. 1/[micron])
# 'pwn': pressure difference in physical (e.g. kPa)
# Overall we need to map the measured physical pressures to get the principle radius of curvature R1
# and associated curvature J1, and similarly R2 and J2 in the model's depth direction
# J1: principal curvature 1
# J2: principal curvature 2 along the model's depth direction
# 'pc' is the dimensionless mean curvature scaled by the length scale 'D32'
# 'pc' is extracted from experimentally measured mean curvature 'Jwn'
pc = Para['D']*micron*EXP_data.Jwn*(1.0/micron)
# Alternatively, the dimensionless mean curvature can also be extracted from the
# experimentally measured pressure difference (i.e. capillary pressure)
# 'pwn' is the dimensionless mean curvature scaled by the length scale 'D32'
# pwn = Para['D']*micron*EXP_data.pwn*kPa/ift
# Curvature is fixed in the micromodel "depth" direction
J2 = Para['D']*micron/(Depth*micron/2.0)
# infer the curvature in the other direction
J1 = pc-J2
# determine the LBM pressure difference
dp=(J1+J2)*IFT/Para['D']
# determine the boundary pressure values for Color.in
din = 1.0+0.5*dp
dout = 1.0-0.5*dp
# Generate names of segmented image data for Segmented.in file
# Need the input 'base_name_suffix' (e.g. '_segmented.raw')
data_name_for_Segmented_in = EXP_data.image_name.copy()
data_name_for_Segmented_in = data_name_for_Segmented_in.replace(image_format,base_name_suffix)
return (data_name_for_Segmented_in,din,dout)
#end def
def write_Domain_in_file(**kwargs):
# For most of the parameters in the Color.in file
# you wouldn't need to worry about them as by default
# they are all hard-coded here
Para={'nprocx':1}
Para['nprocy']=2
Para['nprocz']=2
Para['nx']=1
Para['ny']=2
Para['nz']=2
Para['nspheres']=0 # deprecated
Para['Lx']=10
Para['Ly']=500
Para['Lz']=500
for key in kwargs:
if key in Para.keys():
Para[key]=kwargs[key]
else:
print "Error: "+key+" is not a valid input !\n"
print "Error: Domain.in file is not writen."
return
#end if
#end for
# Check if the dompositoin requirement is satisfied
if (Para['nx']*Para['nprocx']>Para['Lx']) or \
(Para['ny']*Para['nprocy']>Para['Ly']) or \
(Para['nz']*Para['nprocz']>Para['Lz']):
print "Error: The decomposed size does not match the total domain size!"
return
#end if
# write the Domain.in file
ParamFile = open("Domain.in","w")
ParamFile.write("%i " % Para['nprocx'])
ParamFile.write("%i " % Para['nprocy'])
ParamFile.write("%i\n" % Para['nprocz'])
ParamFile.write("%i " % Para['nx'])
ParamFile.write("%i " % Para['ny'])
ParamFile.write("%i\n" % Para['nz'])
ParamFile.write("%i\n" % Para['nspheres'])
ParamFile.write("%.1f " % Para['Lx'])
ParamFile.write("%.1f " % Para['Ly'])
ParamFile.write("%.1f\n" % Para['Lz'])
ParamFile.close()
print "A Domain.in file is created."
#end def
def write_Segment_in_file(**kwargs):
# For most of the parameters in the Color.in file
# you wouldn't need to worry about them as by default
# they are all hard-coded here
Para={'Seg_data_name':'Micromodel_1_segmented.raw'}
Para['Nx']=10
Para['Ny']=500
Para['Nz']=500
Para['xStart']=0
Para['yStart']=0
Para['zStart']=0
for key in kwargs:
if key in Para.keys():
Para[key]=kwargs[key]
else:
print "Error: "+key+" is not a valid input !\n"
print "Error: Segmented.in file is not writen."
return
#end if
#end for
ParamFile = open("Segmented.in","w")
ParamFile.write("%s\n" % Para['Seg_data_name'])
ParamFile.write("%i " % Para['Nx'])
ParamFile.write("%i " % Para['Ny'])
ParamFile.write("%i\n" % Para['Nz'])
ParamFile.write("%i " % Para['xStart'])
ParamFile.write("%i " % Para['yStart'])
ParamFile.write("%i\n" % Para['zStart'])
ParamFile.close()
print "A Segmented.in file is created."
#end def
def write_Color_in_file(**kwargs):
# For most of the parameters in the Color.in file
# you wouldn't need to worry about them as by default
# they are all hard-coded here
Para={'tau':0.7}
Para['alpha']=0.01
Para['beta']=0.95
Para['phi_solid']=-1.0
Para['saturation']=0.0
Para['Fx']=0.0
Para['Fy']=0.0
Para['Fz']=0.0
Para['Restart']=0
Para['pBC']=1
Para['din']=1.001
Para['dout']=0.999
Para['maxtime']=100005
Para['interval']=2000
Para['tolerance']=1e-5
for key in kwargs:
if key in Para.keys():
Para[key]=kwargs[key]
else:
print "Error: "+key+" is not a valid input !\n"
print "Error: Color.in file is not writen."
return
#end if
#end for
# write the color.in file
ParamFile = open("Color.in","w")
ParamFile.write("%f\n" % Para['tau'])
ParamFile.write("%f " % Para['alpha'])
ParamFile.write("%f " % Para['beta'])
ParamFile.write("%f\n" % Para['phi_solid'])
ParamFile.write("%f\n" % Para['saturation'])
ParamFile.write("%f " % Para['Fx'])
ParamFile.write("%f " % Para['Fy'])
ParamFile.write("%f\n" % Para['Fz'])
ParamFile.write("%i " % Para['Restart'])
ParamFile.write("%i " % Para['pBC'])
ParamFile.write("%f " % Para['din'])
ParamFile.write("%f\n" % Para['dout'])
ParamFile.write("%i " % Para['maxtime'])
ParamFile.write("%i " % Para['interval'])
ParamFile.write("%e\n" % Para['tolerance'])
ParamFile.close()
print "A Color.in file is created."
#end def
def read_csv(csv_file_name):
#TODO Haven't thought about a better way of doing this
# Right now I just hard-code the possible variables from the experiment
# which means users are forced to prepare their *.csv file as listed here
image_name = []
sw = []
Jwn = []
pwn = []
with open(csv_file_name,"r") as f:
for line in f:
reader=csv.reader(f,delimiter=' ') #Note the header is skipped by default
for row in reader:
image_name.append(row[0])
sw.append(float(row[1]))
Jwn.append(float(row[2]))
pwn.append(float(row[3]))
#end for
#end for
#end with
# Convter the list to numpy array
image_name_array = np.asarray(image_name,dtype=str)
sw_array = np.asarray(sw,dtype=np.float32)
Jwn_array = np.asarray(Jwn,dtype=np.float32)
pwn_array = np.asarray(pwn,dtype=np.float32)
# Restore the original shape of the experimental data
experiment_data = np.column_stack((image_name_array,sw_array,Jwn_array,pwn_array))
# Unfortunately the column stack will cast all float data to strings
experiment_data = np.core.records.fromrecords(experiment_data,names='image_name,sw,Jwn,pwn')
dt=experiment_data.dtype.descr
dt[1] = (dt[1][0],'float32')
dt[2] = (dt[2][0],'float32')
dt[3] = (dt[3][0],'float32')
experiment_data = experiment_data.astype(dt)
return experiment_data
#end def