Visualizing Internal Variables Printed From The User Element Subroutine
This notebook presents the steps to use the czmtestkit package to read and visualize internal variables from the user element subroutine printed to the .msg file while running the simulation. Inorder to use this functionality of the package, print the variable Var of interest to the .msg file using the following command in the fortran code of the subroutine:
WRITE(7,*) 'VarKey = ', Var
Run ADCB_UEL.ipynb to generate sample files. Read the .msg file and find the line numbers in the .msg file corresponding to the stable increments using czmtestkit.py_modules.find_convergedIncrements.
[6]:
from czmtestkit.py_modules import find_convergedIncrements
File= 'ADCB_UEL\point_05\ADCB_UEL.msg'
converged_time, last_unconv_it, converged_it = find_convergedIncrements(File)
print('Last line numbers from converged increments:', '\n',converged_it, '\n')
print('Last line numbers from the last increment before converged increments:', '\n', last_unconv_it, '\n')
print('Step times of converged increments:', '\n',converged_time, '\n')
Last line numbers from converged increments:
[13275, 19849, 25333, 32927, 43743, 75658, 95899, 103400, 122627, 191886, 213140, 224839, 865040, 1506327, 1537206, 1545720, 1547865, 1555295, 1557440]
Last line numbers from the last increment before converged increments:
[12147, 18734, 24207, 31801, 40518, 74557, 94799, 102300, 121527, 188687, 212040, 223739, 862883, 1505226, 1534007, 1544620, 1544620, 1552094, 1552094]
Step times of converged increments:
['0.100', '0.200', '0.300', '0.400', '0.500', '0.600', '0.700', '0.800', '0.900', '0.925', '0.950', '0.975', '0.981', '0.984', '0.987', '0.991', '0.994', '0.999', '1.00']
Initialize an increment class instance for every stable increment and assign the limiting line numbers corresponding to the increment. Line number corresponding to the last line from the increment before a converged increment is the start of the increment and the line number corresponding to the last of converged increment is the end of the increment.
Then, for each stable increment, find the line numbers where the variable Var is printed using the key word VarKey and the find_lineNumbers method.
increment.findlineNumbers('VarKey', p, (m,n))
where p is the number of lines for each entry of the variable Var and m,n are the number of rows and columns. For example, the variable Var is printed to the .msg file as
VarKey = 1.000000 2.000000 3.000000
4.000000 5.000000 6.000000
Since the entry extends to two lines the p is 2. Further, if the variable Var has two rows and three columns with m = 2 and n = 3.
find_lineNumbers method creates an instance of the data class and stores the corresponding line numbers as instance attributes each time the Var is printed within the limits of the stable increment. A list of all the data class instances created is stored as an attribute of the increment class instance.
Further, find_data method fetches the data between the line numbers fetched by find_lineNumbers method and converts it to matrix of the shape m,n for all the data class instances in the list. For example above entry is converted to
The matix is assigned to the value attribute of the corresponding data class instance. Finally, find_data creates data attribute for the increment class instance which is a dictionary with the VarKey as keys and the lists of corresponding data class instances as values.
[2]:
from czmtestkit.py_modules import increment
entries = []
for j in range(len(converged_it)):
ent = increment()
ent.fileName = File
ent.step_time = converged_time[j]
ent.start = last_unconv_it[j]
ent.stop = converged_it[j]
entries.append(ent)
ent.find_lineNumbers('IP',1,(2,1))
ent.find_lineNumbers('GIP',1,(3,1))
ent.find_lineNumbers('TAU',1,(3,1))
ent.find_lineNumbers('DTAU',3,(3,3))
ent.find_lineNumbers('DG',24,(3,24))
ent.find_lineNumbers('DR',24,(3,24))
ent.find_data()
Finally, edit the setup_frame and frame_plot methods of the frame_iterator class to present variables of interest as colormaps and create a movie of frames from all the stable increments. Use the setup_frame method to setup the plot area, titles, and axes, and frame_plot method to plot the increments.
Note: Do not change the input parameters of the setup_frame and frame_plot methods.
[3]:
import numpy as np
from IPython import display
from matplotlib import pyplot as plt
from matplotlib import animation as animation
%matplotlib inline
class frame_iterator:
def __init__(self, array, fileName):
self.mainArray = array
self.itr = len(array)
self.name = fileName
def animate(self): # Animator
self.setup_frame()
Writer = animation.FFMpegWriter
writer = Writer(fps=1, metadata=dict(artist='Nanditha Mudunuru'), bitrate=1800)
anim = animation.FuncAnimation(self.fig, self.frame_plot, frames=self.itr, blit=False, repeat=True)
anim.save(self.name+'.mp4', writer=writer)
def setup_frame(self): # Main frame
fig = plt.figure(figsize=(12,15))
self.fig = fig
# dR color map
ax1 = fig.add_subplot(121)
self.ax1 = ax1
ax1.set_title('dR', fontsize=20)
self.im1 = ax1.imshow(np.zeros([24,3]), cmap='seismic')
self.fig.colorbar(self.im1, ax=self.ax1, orientation='vertical')
# Major ticks and labels
ax1.set_yticks(np.arange(0, 24, 1))
ax1.set_xticks(np.arange(0, 3, 1))
ax1.set_yticklabels(np.arange(1, 25, 1))
ax1.set_xticklabels(np.arange(1, 4, 1))
# Minor ticks and grid
ax1.set_yticks(np.arange(-.5, 24, 1), minor=True)
ax1.set_xticks(np.arange(-.5, 3, 1), minor=True)
ax1.grid(which='minor', color='black', linewidth=2)
# tau color map
ax2 = fig.add_subplot(222)
self.ax2 = ax2
ax2.set_title('\u03C4', fontsize=20)
self.im2 = ax2.imshow(np.zeros([3,1]), cmap='seismic')
self.fig.colorbar(self.im2, ax=self.ax2, orientation='vertical')
# Major ticks and labels
ax2.set_xticks(np.arange(0, 1, 1))
ax2.set_yticks(np.arange(0, 3, 1))
ax2.set_xticklabels(np.arange(1, 2, 1))
ax2.set_yticklabels(np.arange(1, 4, 1))
# Minor ticks and grid
ax2.set_xticks(np.arange(-.5, 1, 1), minor=True)
ax2.set_yticks(np.arange(-.5, 3, 1), minor=True)
ax2.grid(which='minor', color='black', linewidth=2)
# GIP color map
ax3 = fig.add_subplot(224)
self.ax3 = ax3
ax3.set_title(r'$\Delta(e_i)$', fontsize=20)
self.im3 = ax3.imshow(np.zeros([3,1]), cmap='seismic')
self.fig.colorbar(self.im3, ax=self.ax3, orientation='vertical')
# Major ticks and labels
ax3.set_xticks(np.arange(0, 1, 1))
ax3.set_yticks(np.arange(0, 3, 1))
ax3.set_xticklabels(np.arange(1, 2, 1))
ax3.set_yticklabels(np.arange(1, 4, 1))
# Minor ticks and grid
ax3.set_xticks(np.arange(-.5, 1, 1), minor=True)
ax3.set_yticks(np.arange(-.5, 3, 1), minor=True)
ax3.grid(which='minor', color='black', linewidth=2)
return
def frame_plot(self, i): # Frame update at each stable increment
IP_idx = 0
dr = self.mainArray[i].data['DR'][IP_idx].value.T
tau = self.mainArray[i].data['TAU'][IP_idx].value
gip = self.mainArray[i].data['GIP'][IP_idx].value
time = self.mainArray[i].step_time
self.fig.suptitle('Step Time = {}'.format(time), fontsize=26)
self.im1.set_data(dr)
self.im2.set_data(tau)
self.im3.set_data(gip)
return
test = frame_iterator(entries, 'h_u=8')
test.animate()
plt.close()
display.Video("h_u=8.mp4")
[3]:
Or plot individual frames from required increments
[5]:
test.setup_frame()
test.frame_plot(0)
plt.show()