Difference between revisions of "Minimal Serpent Coupling Script"

From Serpent Wiki
Jump to: navigation, search
(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.

  1. Extract the MSCS zip to a suitable folder preserving the internal directory structure of the package.
  2. Replace the absolute path to the Serpent executable on line 16 of MSCS.py.
  3. 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.

Comments