Difference between revisions of "Minimal Serpent Coupling Script"
(→Running) |
|||
Line 2: | Line 2: | ||
== Description == | == Description == | ||
+ | |||
+ | == Files == | ||
+ | |||
+ | === MSCS.py === | ||
+ | |||
+ | <nowiki>############################################################# | ||
+ | # # | ||
+ | # Minimal Serpent Coupling Script v 0.1 # | ||
+ | # # | ||
+ | # Created by: Ville Valtavirta 2016/05/06 # | ||
+ | # Modified by: Ville Valtavirta 2016/05/09 # | ||
+ | # # | ||
+ | ############################################################# | ||
+ | |||
+ | import os | ||
+ | import signal | ||
+ | import time | ||
+ | |||
+ | # Path to Serpent executable | ||
+ | |||
+ | sssexe = '/home/vvvillehe/Serpent2/gittest/sss2' | ||
+ | |||
+ | ####################################################### | ||
+ | # Create the Serpent input-file for this run # | ||
+ | # (process id or communication file must be appended) # | ||
+ | ####################################################### | ||
+ | |||
+ | # Open original input for reading | ||
+ | |||
+ | file_in = open('./input','r') | ||
+ | |||
+ | # Open a new input file for writing | ||
+ | |||
+ | file_out = open('./coupledinput','w') | ||
+ | |||
+ | # Write original input to new file | ||
+ | |||
+ | for line in file_in: | ||
+ | file_out.write(line) | ||
+ | |||
+ | # Close original input file | ||
+ | |||
+ | file_in.close() | ||
+ | |||
+ | # Append signalling mode | ||
+ | |||
+ | file_out.write('\n') | ||
+ | file_out.write('set comfile com.in com.out\n') | ||
+ | |||
+ | # Append interface name | ||
+ | |||
+ | file_out.write('\n') | ||
+ | file_out.write('ifc cool.ifc\n') | ||
+ | |||
+ | # Close new input file | ||
+ | |||
+ | file_out.close() | ||
+ | |||
+ | #################################### | ||
+ | # Write the initial interface file # | ||
+ | #################################### | ||
+ | |||
+ | file_out = open('./cool.ifc','w') | ||
+ | |||
+ | # Write the header line (TYPE MAT OUT) | ||
+ | |||
+ | file_out.write('2 cool 1\n') | ||
+ | |||
+ | # Write the output line (OUTFILE NZ ZMIN ZMAX NR) | ||
+ | |||
+ | file_out.write('coolifc.out 10 -100 100 1\n') | ||
+ | |||
+ | # Write the mesh type | ||
+ | |||
+ | file_out.write('1\n') | ||
+ | |||
+ | # Write the mesh size (NX XMIN XMAX NY YMIN YMAX NZ ZMIN ZMAX) | ||
+ | |||
+ | file_out.write('1 -0.75 0.75 1 -0.75 0.75 10 -100 100\n') | ||
+ | |||
+ | # Write initial fuel temperatures and densities | ||
+ | |||
+ | for i in range(10): | ||
+ | file_out.write('-0.99 520.0\n') | ||
+ | |||
+ | # Close interface file | ||
+ | |||
+ | file_out.close() | ||
+ | |||
+ | ################################ | ||
+ | # Start the Serpent simulation # | ||
+ | ################################ | ||
+ | |||
+ | # Create a command string that will start the Serpent simulation | ||
+ | |||
+ | runcommand = sssexe+' -omp 3 ./coupledinput &' | ||
+ | |||
+ | # Execute the command string | ||
+ | |||
+ | os.system(runcommand) | ||
+ | |||
+ | ######################### | ||
+ | # Picard iteration loop # | ||
+ | ######################### | ||
+ | |||
+ | iterating = 1 | ||
+ | |||
+ | while iterating == 1: | ||
+ | ################### | ||
+ | # Wait for signal # | ||
+ | ################### | ||
+ | |||
+ | sleeping = 1 | ||
+ | |||
+ | while sleeping == 1: | ||
+ | |||
+ | # Sleep for two seconds | ||
+ | |||
+ | time.sleep(2) | ||
+ | |||
+ | # Open file to check if we got a signal | ||
+ | |||
+ | fin = open('./com.out','r') | ||
+ | |||
+ | # Read line | ||
+ | |||
+ | line = fin.readline() | ||
+ | |||
+ | # Close file | ||
+ | |||
+ | fin.close() | ||
+ | |||
+ | # Check signal | ||
+ | |||
+ | if int(line) != -1: | ||
+ | if int(line) == signal.SIGUSR1: | ||
+ | # Got the signal to resume | ||
+ | |||
+ | sleeping = 0 | ||
+ | |||
+ | elif int(line) == signal.SIGUSR2: | ||
+ | # Got the signal to move to next time point | ||
+ | |||
+ | iterating = 0 | ||
+ | sleeping = 0 | ||
+ | elif int(line) == signal.SIGTERM: | ||
+ | # Got the signal to end the calculation | ||
+ | |||
+ | iterating = 0 | ||
+ | sleeping = 0 | ||
+ | else: | ||
+ | # Unknown signal | ||
+ | |||
+ | print "\nUnknown singal read from file, exiting\n" | ||
+ | |||
+ | # Exit | ||
+ | |||
+ | quit() | ||
+ | |||
+ | # Reset the signal in the file | ||
+ | |||
+ | file_out = open('./com.out','w') | ||
+ | |||
+ | file_out.write('-1') | ||
+ | |||
+ | file_out.close() | ||
+ | |||
+ | # Check if iteration has finished | ||
+ | |||
+ | if (iterating == 0): | ||
+ | break | ||
+ | |||
+ | ########################### | ||
+ | # Read power distribution # | ||
+ | ########################### | ||
+ | |||
+ | # Reset power distribution | ||
+ | |||
+ | P = [] | ||
+ | |||
+ | # Open output file | ||
+ | |||
+ | file_in = open('./coolifc.out','r') | ||
+ | |||
+ | # Loop over output file to read power distribution | ||
+ | |||
+ | for line in file_in: | ||
+ | # Split line to values | ||
+ | |||
+ | strtuple = line.split() | ||
+ | |||
+ | # Store power | ||
+ | |||
+ | P.append(float(strtuple[8])) | ||
+ | |||
+ | ########################### | ||
+ | # Calculate TH-solution # | ||
+ | ########################### | ||
+ | |||
+ | # Reset TH-solution | ||
+ | |||
+ | T = [] | ||
+ | rho = [] | ||
+ | |||
+ | # Coolant specific heat capacity | ||
+ | |||
+ | cp = 4900 # J/(kg*K) | ||
+ | |||
+ | # Coolant mass flow rate | ||
+ | |||
+ | w = 0.3 # kg/s | ||
+ | |||
+ | # Put inlet temperature | ||
+ | |||
+ | T.append(520) | ||
+ | |||
+ | # Put inlet density | ||
+ | |||
+ | rho.append(0.813) | ||
+ | |||
+ | # Calculate temperatures at (nz+1) axial nodes | ||
+ | |||
+ | for i in range(10): | ||
+ | |||
+ | # Calculate next temperature | ||
+ | # T(i+1) = T(i) + P(i)/(w*cp) | ||
+ | |||
+ | Tnext = T[i] + P[i]/(w*cp) | ||
+ | |||
+ | # Store new temperature | ||
+ | |||
+ | T.append(Tnext) | ||
+ | |||
+ | # Calculate next density based on temperature | ||
+ | # Linear interpolation between | ||
+ | # T0 = 520, rho0 = 0.813 | ||
+ | # T1 = 600, rho1 = 0.653 | ||
+ | |||
+ | rhonext = 0.813 + (0.653 - 0.813)/(600.0 - 520.0)*(Tnext - 520.0) | ||
+ | |||
+ | # Store new density | ||
+ | |||
+ | rho.append(rhonext) | ||
+ | |||
+ | ########################### | ||
+ | # Update interface # | ||
+ | ########################### | ||
+ | |||
+ | file_out = open('./cool.ifc','w') | ||
+ | |||
+ | # Write the header line (TYPE MAT OUT) | ||
+ | |||
+ | file_out.write('2 cool 1\n') | ||
+ | |||
+ | # Write the output line (OUTFILE NZ ZMIN ZMAX NR) | ||
+ | |||
+ | file_out.write('coolifc.out 10 -100 100 1\n') | ||
+ | |||
+ | # Write the mesh type | ||
+ | |||
+ | file_out.write('1\n') | ||
+ | |||
+ | # Write the mesh size (NX XMIN XMAX NY YMIN YMAX NZ ZMIN ZMAX) | ||
+ | |||
+ | file_out.write('1 -0.75 0.75 1 -0.75 0.75 10 -100 100\n') | ||
+ | |||
+ | # Write updated fuel temperatures and densities | ||
+ | |||
+ | for i in range(10): | ||
+ | # Calculate density and temperature at this layer as an average | ||
+ | # of layer bottom and top values | ||
+ | |||
+ | Tnext = (T[i]+T[i+1])/2.0 | ||
+ | rhonext = (rho[i]+rho[i+1])/2.0 | ||
+ | |||
+ | # Write density and temperature at this layer | ||
+ | |||
+ | file_out.write('{} {}\n'.format(-rhonext, Tnext)) | ||
+ | |||
+ | ############################ | ||
+ | # Signal Serpent (SIGUSR1) # | ||
+ | ############################ | ||
+ | |||
+ | file_out = open('./com.in','w') | ||
+ | |||
+ | file_out.write(str(signal.SIGUSR1)) | ||
+ | |||
+ | file_out.close()</nowiki> | ||
+ | |||
== Setup == | == Setup == |
Revision as of 13:45, 9 May 2016
The Minimal Serpent Coupling Script (MSCS) is a short (< 300 lines with comments) Python program intended to give a minimal working example of a wrapper program that can communicate with Serpent in the coupled calculation mode. MSCS provides a working example of externally coupled multi-physics simulations with Serpent and may be a good starting point for the users that are interested in running such simulations with Serpent.
Description
Files
MSCS.py
############################################################# # # # Minimal Serpent Coupling Script v 0.1 # # # # Created by: Ville Valtavirta 2016/05/06 # # Modified by: Ville Valtavirta 2016/05/09 # # # ############################################################# import os import signal import time # Path to Serpent executable sssexe = '/home/vvvillehe/Serpent2/gittest/sss2' ####################################################### # Create the Serpent input-file for this run # # (process id or communication file must be appended) # ####################################################### # Open original input for reading file_in = open('./input','r') # Open a new input file for writing file_out = open('./coupledinput','w') # Write original input to new file for line in file_in: file_out.write(line) # Close original input file file_in.close() # Append signalling mode file_out.write('\n') file_out.write('set comfile com.in com.out\n') # Append interface name file_out.write('\n') file_out.write('ifc cool.ifc\n') # Close new input file file_out.close() #################################### # Write the initial interface file # #################################### file_out = open('./cool.ifc','w') # Write the header line (TYPE MAT OUT) file_out.write('2 cool 1\n') # Write the output line (OUTFILE NZ ZMIN ZMAX NR) file_out.write('coolifc.out 10 -100 100 1\n') # Write the mesh type file_out.write('1\n') # Write the mesh size (NX XMIN XMAX NY YMIN YMAX NZ ZMIN ZMAX) file_out.write('1 -0.75 0.75 1 -0.75 0.75 10 -100 100\n') # Write initial fuel temperatures and densities for i in range(10): file_out.write('-0.99 520.0\n') # Close interface file file_out.close() ################################ # Start the Serpent simulation # ################################ # Create a command string that will start the Serpent simulation runcommand = sssexe+' -omp 3 ./coupledinput &' # Execute the command string os.system(runcommand) ######################### # Picard iteration loop # ######################### iterating = 1 while iterating == 1: ################### # Wait for signal # ################### sleeping = 1 while sleeping == 1: # Sleep for two seconds time.sleep(2) # Open file to check if we got a signal fin = open('./com.out','r') # Read line line = fin.readline() # Close file fin.close() # Check signal if int(line) != -1: if int(line) == signal.SIGUSR1: # Got the signal to resume sleeping = 0 elif int(line) == signal.SIGUSR2: # Got the signal to move to next time point iterating = 0 sleeping = 0 elif int(line) == signal.SIGTERM: # Got the signal to end the calculation iterating = 0 sleeping = 0 else: # Unknown signal print "\nUnknown singal read from file, exiting\n" # Exit quit() # Reset the signal in the file file_out = open('./com.out','w') file_out.write('-1') file_out.close() # Check if iteration has finished if (iterating == 0): break ########################### # Read power distribution # ########################### # Reset power distribution P = [] # Open output file file_in = open('./coolifc.out','r') # Loop over output file to read power distribution for line in file_in: # Split line to values strtuple = line.split() # Store power P.append(float(strtuple[8])) ########################### # Calculate TH-solution # ########################### # Reset TH-solution T = [] rho = [] # Coolant specific heat capacity cp = 4900 # J/(kg*K) # Coolant mass flow rate w = 0.3 # kg/s # Put inlet temperature T.append(520) # Put inlet density rho.append(0.813) # Calculate temperatures at (nz+1) axial nodes for i in range(10): # Calculate next temperature # T(i+1) = T(i) + P(i)/(w*cp) Tnext = T[i] + P[i]/(w*cp) # Store new temperature T.append(Tnext) # Calculate next density based on temperature # Linear interpolation between # T0 = 520, rho0 = 0.813 # T1 = 600, rho1 = 0.653 rhonext = 0.813 + (0.653 - 0.813)/(600.0 - 520.0)*(Tnext - 520.0) # Store new density rho.append(rhonext) ########################### # Update interface # ########################### file_out = open('./cool.ifc','w') # Write the header line (TYPE MAT OUT) file_out.write('2 cool 1\n') # Write the output line (OUTFILE NZ ZMIN ZMAX NR) file_out.write('coolifc.out 10 -100 100 1\n') # Write the mesh type file_out.write('1\n') # Write the mesh size (NX XMIN XMAX NY YMIN YMAX NZ ZMIN ZMAX) file_out.write('1 -0.75 0.75 1 -0.75 0.75 10 -100 100\n') # Write updated fuel temperatures and densities for i in range(10): # Calculate density and temperature at this layer as an average # of layer bottom and top values Tnext = (T[i]+T[i+1])/2.0 rhonext = (rho[i]+rho[i+1])/2.0 # Write density and temperature at this layer file_out.write('{} {}\n'.format(-rhonext, Tnext)) ############################ # Signal Serpent (SIGUSR1) # ############################ file_out = open('./com.in','w') file_out.write(str(signal.SIGUSR1)) file_out.close()
Setup
MSCS has been tested with Python 2.7.6 and Serpent 2.1.26.
- Extract the MSCS zip to a suitable folder preserving the internal directory structure of the package.
- Replace the absolute path to the Serpent executable on line 16 of MSCS.py.
- The test case is now ready to run.
Running
Note: Before running the MSCS you should familiarize yourself with finding and killing background processes in your operating system. Since MSCS runs Serpent as a background process, killing MSCS will not kill the Serpent process automatically.
Run the simulation from the testcase-folder using the command python ../MSCS.py
The output of the Serpent run will be printed to the terminal.