Minimal Serpent Coupling Script

From Serpent Wiki
Jump to: navigation, search

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.

This page is about the really Minimal Serpent Coupling Script for steady state coupled calculations. Other MSCS versions include

NB: Serpent versions up to 2.1.26 have a small bug in the updating of the regular mesh based interface, which should be fixed before running the simulation.

Description

The coupling script communicates with Serpent using the file based communication mode.

Here, the coupling script calculates the TH-solution itself. In many cases that part of the coupling script should be replaced by writing the input for an external solver, running the external solver and reading the results from the external solver output.

The temperature treatment of the interaction physics is done on-the-fly using the TMS temperature treatment technique for the base cross sections and interpolation of thermal scattering data for the thermal scattering libraries.

The problem solved here is a 200 cm long fuel rod in infinite lattice with axially black boundary conditions. Coolant temperature and density solved by MSCS using simple correlations and assuming steady state in heat transfer.

Files

MSCS.py

#############################################################
#                                                           #
#          Minimal Serpent Coupling Script v 0.3            #
#                                                           #
# Created by:  Ville Valtavirta              2016/05/06     #
# Modified by: Ville Valtavirta              2020/10/26     #
#                                                           #
#############################################################

import os
import signal
import time

# Path to Serpent executable

sssexe = '/home/vvvillehe/Serpent2/2.1.31/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 coolant 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.value:
                # Got the signal to resume

                sleeping = 0

            elif int(line) == signal.SIGUSR2.value:
                # Got the signal to move to next time point

                iterating = 0
                sleeping = 0
            elif int(line) == signal.SIGTERM.value:
                # Got the signal to end the calculation

                iterating = 0
                sleeping = 0
            else:
                # Unknown signal

                print("\nUnknown signal 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]))

    file_in.close()

    ###########################
    # 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 coolant 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))

    file_out.close()

    ############################
    # Signal Serpent (SIGUSR1) #
    ############################

    file_out = open('./com.in','w')

    file_out.write("{}".format(int(signal.SIGUSR1.value)))

    file_out.close()

input

% --- Input for MSCS testing

set title "Serpent-MSCS externally coupled calculation"

% --- Fuel Pin definition:

pin 1
fuel   0.4335
gas    0.442000
clad   0.502500
cool

% --- Lattice (type = 1, pin pitch = 1.5):

lat 10  1  0.0 0.0 1 1 1.5
1

% --- Boundary of the geometry (200 cm active length)

surf 2 cuboid -0.75 0.75 -0.75 0.75 -100 100

% --- Cell definitions:

cell  3  0  fill 10  -2     % Pin-cell
cell 99  0  outside   2     % Outside world

% --- Fuel material:

mat fuel    -10.424 tmp 1200.0 rgb 100 160 140
 92235.03c   -0.015867
 92238.03c   -0.86563
  8016.03c   -0.1185

% --- Cladding material:

mat clad     -6.55 rgb 200 200 200
 40090.03c   -0.98135
 24052.03c   -0.00100
 26056.03c   -0.00135
 28058.03c   -0.00055
 50120.03c   -0.01450
  8016.03c   -0.00125

% --- Gas gap:

mat gas -1E-4 rgb 255 255 255  
 2004.06c     1.0

% --- Coolant (majorant density and TMS-limits for temperature):

mat cool     -0.990 tft 520 624 moder lwtr 1001 rgb 150 160 240
 1001.03c     0.66667
 8016.03c     0.33333

% --- Thermal scattering data for light water:
%     On-the-fly treatment for SAB-data between 474 K -- 624 K

therm lwtr 0 lwj3.07t lwj3.09t lwj3.11t lwj3.13t

% --- Reflective boundary conditions in XY

set bc 3 3 1

% --- Neutron population and criticality cycles:

set pop 10000 50 50

% --- Use fission source passing with 20 inactive cycles on 
%     later iterations

set fsp 1 20

% --- Maximum number of coupled calculation iterations set to 2

set ccmaxiter 2

% --- Total power for normalization (600 W/cm, unrealistically high):

set power 120000.00

% --- Disable group constant generation

set gcu -1

Setup

MSCS has been tested with Python 3.8.13 and Serpent 2.2.0.

  1. Save the contents of the MSCS.py file (above) to a file of the same name.
  2. Replace the absolute path to the Serpent executable on line 16 of MSCS.py.
  3. Save the contents of the input file to a file called input in the same directory where the MSCS.py file is located.
  4. Add some cross section libraries to the input-file using the set acelib input option.
  5. 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 folder containing both files using the command python MSCS.py

The output of the Serpent run will be printed to the terminal.

Comments