#!/usr/bin/env python3

#  nbigen_sub.py
#
#  subfunctions of nbigen, handling aspects of code generation for the
#  nbi (nubeam) NTCC module.  dmc 2 Jan 2002
#
#  DMC -- removed xplasma group functionality; simplified nbo_load.f90...
#         15 Apr 2008
#

import os
import nbigen_fortran2C

#
#--------------------------------------------------------------------------
# global items...

from nbigen_global import *

# error handling and i/o

from nbigen_util import *

#--------------------------------------------------------------------
# process array dimensions...
#

def nbigen_array_dimensions(text,section):

    # get array dimensions for nbi modules.  Write the nbi_dimensions module
    # write the "nbi_dimensions" type into nbi_types.f90

    global nbi_initdims    # defined before nbi code control input is given
    global nbi_initlims    # max sizes of the above (where applicable) or 0
    global nbi_dimdflts    # default values of the above
    global nbi_finaldims   # defined after nbi code control input is given
    global nbi_alldims     # union of the above

    global nbi_allnames    # list of all names...

    global nbi_udim_dict   # dictionary of user settable dimensions (initdims)

    nbi_udims = []  # internal data -- user settable dimensions
    nbi_pdims = []  # internal data -- program controlled dimensions
    nbi_qdims = []  # internal data -- deferred program controlled dimensions

    mode = "-"
    for aline in text:

        secns = aline.split('#')
        line = secns[0].strip()

        words = line.split()
        word0 = words[0].upper()

        if word0 == "U":
            if mode != "-" and mode != "U":
                print(" ?nbigen_sub: U dimensions must come before all others")
                raise(nbigen_error)
            mode = "U"
            uline = line[1:]
            expr = uline.split('=')

            if len(expr) != 2:
                nbigen_syntax(section,line)

            lhs = expr[0].strip()  # LHS of name = value[,value]
            lhs = lhs.lower()
            rhs = expr[1].strip()  # RHS
            nbi_check_name(lhs,section,line)

            nbi_udims.append([])
            icur = len(nbi_udims) - 1

            nbi_udims[icur].append(lhs)
            nbi_udim_dict[lhs] = []
            if rhs.find(":") > -1:
                slist = rhs.split(":")
                if len(slist) != 2:
                    nbigen_syntax(section,line)
                dflt = slist[0].strip()
                nbi_check_num(dflt,section,line)
                maxdim = slist[1].strip()
                nbi_check_num(maxdim,section,line)
                maxdim = int(maxdim)

            else:
                dflt = rhs
                nbi_check_num(dflt,section,line)
                maxdim = 0

            nbi_udims[icur].append(dflt)     # default value
            nbi_udims[icur].append(maxdim)   # maximum allowed value, or 0

            nbi_initdims.append(lhs)     # global list of dimensions
            nbi_initlims.append(maxdim)  # global list of size limits
            nbi_dimdflts.append(dflt)

        elif word0 == "P":
            mode = "P"
            uline = line[1:]
            expr = uline.split('=')

            if len(expr) != 2:
                nbigen_syntax(section,line)

            lhs = expr[0].strip()  # LHS of name = <expr>
            lhs = lhs.lower()
            rhs = expr[1].strip() # RHS
            nbi_check_name(lhs,section,line)

            nbi_pdims.append([])
            icur = len(nbi_pdims) - 1

            nbi_pdims[icur].append(lhs)

            if rhs.find(":") > -1:
                slist = rhs.split(":")
                if len(slist) != 2:
                    nbigen_syntax(section,line)
                expr = slist[0].strip()
                maxdim = slist[1].strip()
                nbi_check_num(maxdim,section,line)
                maxdim = int(maxdim)

            else:
                expr = rhs
                maxdim = 0

            nbi_pdims[icur].append(expr)
            nbi_pdims[icur].append(maxdim)

            nbi_initdims.append(lhs)     # global list of dimensions
            nbi_initlims.append(maxdim)  # global list of size limits

        elif word0 == "NBI_FINALDIMS:":
            mode = "C"
            if len(words)<2:
                print("nbigen_array_dimensions: missing words.")
                nbigen_syntax(section,line)

            for word in words[1:]:
                nbi_check_name(word,section,line)

            nbi_qdims = words[1:]
            nbi_finaldims = nbi_qdims    # global list of dimensions

        elif word0 == "!":
            if mode != "U":
                print("nbigen_array_dimensions: ignored: ",line)
            else:
                if len(nbi_udims[icur]) == 3:
                    #  save 1st comment line in this dictionary
                    udimnam = nbi_udims[icur][0]
                    uexpr_pair = line.split('=')
                    if len(uexpr_pair) != 2:
                        print("? first comment for user settable dimension")
                        print(udimnam,uexpr_pair)
                        print("  must contain an expression dependent on one input variable.")
                        nbigen_syntax(section,line)
                    uexpr = uexpr_pair[1].strip()
                    nbi_udim_dict[udimnam].append(uexpr)

                nbi_udims[icur].append(line)  # append comment

        else:
            nbigen_syntax(section,line)

    nbi_alldims = nbi_initdims + nbi_finaldims   # all dimensions: global list
    for aname in nbi_alldims:
        nbi_allnames.append(aname.upper())

    # start "inputs" helpfile appendix

    nbwrite( f_help1, "3 Appendix_B_Initialization_Control_Structure")
    nbwrite( f_help1, " ")
    nbwrite( f_help1, "Declaration:")
    nbwrite( f_help1, " ")
    nbwrite( f_help1, "  use nbi_pstypes")
    nbwrite( f_help1, "  type (nbi_ctrl_init) :: iblk")
    nbwrite( f_help1, "  character*80 filename   ! filename input to I/O routines")
    nbwrite( f_help1, "  integer ierr            ! status return code 0=normal")
    nbwrite( f_help1, " ")
    nbwrite( f_help1, "Calls:")
    nbwrite( f_help1, " ")
    nbwrite( f_help1, "  call nbi_ctrl_init_dflt(iblk) ! set default values")
    nbwrite( f_help1, "  call nbi_ctrl_init_write(filename,iblk,ierr) ! write iblk namelist")
    nbwrite( f_help1, "  call nbi_ctrl_init_cdfwrite(filename,iblk,ierr) ! write iblk NetCDF file")
    nbwrite( f_help1, "  call nbi_ctrl_init_read(filename,iblk,ierr)  ! read iblk namelist")
    nbwrite( f_help1, "  call nbi_ctrl_init_cdfread(filename,iblk,ierr)  ! read iblk NetCDF file")
    nbwrite( f_help1, " ")
    nbwrite( f_help1, "Data element members of nbi_ctrl_init:")

    nbwrite( f_help2, "3 Appendix_C_Step_Control_Structure")
    nbwrite( f_help2, " ")
    nbwrite( f_help2, "Declaration:")
    nbwrite( f_help2, " ")
    nbwrite( f_help2, "  use nbi_pstypes")
    nbwrite( f_help2, "  type (nbi_ctrl_update) :: sblk")
    nbwrite( f_help2, "  character*80 filename   ! filename input to I/O routines")
    nbwrite( f_help2, "  integer ierr            ! status return code 0=normal")
    nbwrite( f_help2, " ")
    nbwrite( f_help2, "Calls:")
    nbwrite( f_help2, " ")
    nbwrite( f_help2, "  call nbi_ctrl_update_dflt(sblk) ! set default values")
    nbwrite( f_help2, "  call nbi_ctrl_update_write(filename,sblk,ierr) ! write sblk namelist")
    nbwrite( f_help2, "  call nbi_ctrl_update_cdfwrite(filename,sblk,ierr) ! write sblk NetCDF file")
    nbwrite( f_help2, "  call nbi_ctrl_update_read(filename,sblk,ierr)  ! read sblk namelist")
    nbwrite( f_help2, "  call nbi_ctrl_update_cdfread(filename,sblk,ierr)  ! read sblk NetCDF file")
    nbwrite( f_help2, " ")
    nbwrite( f_help2, "Data element members of nbi_ctrl_update:")

    nbwrite( f_help4, "3 Appendix_E_Legacy_Input_Structures_&_Methods")
    nbwrite( f_help4, " ")
    nbwrite( f_help4, " Array dimensions must be set before any other")
    nbwrite( f_help4, " input structure.")
    nbwrite( f_help4, " ")
    nbwrite( f_help4, " Methods and structure contents are shown, with")
    nbwrite( f_help4, " comments copied from nubeam/nbspec.dat ...")
    nbwrite( f_help4, " ")
    nbwrite( f_help4, " To define the referenced fortran-90 structures,")
    nbwrite( f_help4, " user code should include the statement: ")
    nbwrite( f_help4, " ")
    nbwrite( f_help4, "     use nbi_types")
    nbwrite( f_help4, " ")

    jset = "TRUE"
    jmod = "FALSE"
    ihelp_start( f_help4, "dims", jset, jmod)

    # write dimensions module

    nbwrite( f_nbidim, "  ! user settable dimensions:")
    nbwrite( f_nbidim, " ")

    for item in nbi_udims:
        s = "  integer :: " + item[0] + " = " + item[1]
        nbwrite( f_nbidim, s)

        nbwrite( f_help4, "    integer :: " + item[0])
        nbwrite( f_help4, "    ! -> default value: " + item[1])
        if item[2] > 0:
            nbwrite( f_nbidim, "  ! -> maximum user value allowed: " + repr(item[2]))
            nbwrite( f_help4, "    ! -> maximum user value allowed: " + repr(item[2]))
        if len(item) > 3:
            for cmt in item[3:]:
                nbwrite( f_nbidim, "          " + cmt)
                nbwrite( f_help4,   "          " + cmt)
            nbwrite( f_nbidim, " ")
            nbwrite( f_help4, " ")

    nbwrite( f_nbidim, " ")
    nbwrite( f_nbidim, "  ! program controlled dimensions:")
    for item in nbi_pdims:
        s = "  integer :: " + item[0] + " = -1"
        nbwrite( f_nbidim, s)

    nbwrite( f_nbidim, " ")
    nbwrite( f_nbidim, "  ! program controlled dimensions:")
    nbwrite( f_nbidim, "  ! (not set until after input is read):")

    for idim in nbi_qdims:
        s = "  integer :: " + idim + " = -1"
        nbwrite( f_nbidim, s)

    # create a data type for the user settable dimensions

    nbwrite( f_nbityp, "  ! user settable dimensions:")
    nbwrite( f_nbityp, "  ! see nbi_dimensions.f90 for description.")
    nbwrite( f_nbityp, " ")
    nbwrite( f_nbityp, "  type nbitype_dims")
    nbwrite( f_nbityp, " ")

    for item in nbi_udims:
        s = "    integer :: " + item[0]
        nbwrite( f_nbityp, s)

    nbwrite( f_nbityp, " ")
    nbwrite( f_nbityp, "  end type nbitype_dims")
    nbwrite( f_nbityp, " ")

    # create routine to initialize instance of data type (default values)

    nbwrite( f_nbinit, "subroutine nbi_init_dims(zdims)")
    nbwrite( f_nbinit, " ")
    nbwrite( f_nbinit, "  ! default values for user settable dimensions.")
    nbwrite( f_nbinit, " ")
    nbwrite( f_nbinit, "  use nbi_dimensions")
    nbwrite( f_nbinit, "  use nbi_types")
    nbwrite( f_nbinit, "  implicit NONE")
    nbwrite( f_nbinit, " ")
    nbwrite( f_nbinit, "  type (nbitype_dims), intent(out) :: zdims")
    nbwrite( f_nbinit, " ")

    for item in nbi_udims:
        s = "  zdims%" + item[0] + " = " + item[1]
        nbwrite( f_nbinit, s)

    nbwrite( f_nbinit, " ")
    nbwrite( f_nbinit, "end subroutine nbi_init_dims")
    nbwrite( f_nbinit, " ")

    # create routine to get current values of user settable dimensions

    nbwrite( f_nbiget, "subroutine nbi_get_dims(zdims,ierr)")
    nbwrite( f_nbiget, " ")
    nbwrite( f_nbiget, "  ! retrieve user settable dimensions.")
    nbwrite( f_nbiget, " ")
    nbwrite( f_nbiget, "  use nbi_com")
    nbwrite( f_nbiget, "  use nbi_types")
    nbwrite( f_nbiget, "  implicit NONE")
    nbwrite( f_nbiget, " ")
    nbwrite( f_nbiget, "  type (nbitype_dims), intent(out) :: zdims")
    nbwrite( f_nbiget, "  integer, intent(out) :: ierr")
    nbwrite( f_nbiget, " ")

    nbwrite( f_nbiget, "  ierr=0")
    nbwrite( f_nbiget, "  if(.not.nbidim_init) then")
    nbwrite( f_nbiget, "    write(nonlin,*) '?nbi_get_dims: dimensions not yet set.'")
    nbwrite( f_nbiget, "    ierr=1")
    nbwrite( f_nbiget, "    return")
    nbwrite( f_nbiget, "  endif")
    nbwrite( f_nbiget, " ")

    for item in nbi_udims:
        s = "  zdims%" + item[0] + " = " + item[0]
        nbwrite( f_nbiget, s)

    nbwrite( f_nbiget, " ")
    nbwrite( f_nbiget, "end subroutine nbi_get_dims")
    nbwrite( f_nbiget, " ")

    # create routine to set current values of user settable dimensions

    nbwrite( f_nbiset, "subroutine nbi_set_dims(zdims,ierr)")
    nbwrite( f_nbiset, " ")
    nbwrite( f_nbiset, "  ! retrieve user settable dimensions.")
    nbwrite( f_nbiset, " ")
    nbwrite( f_nbiset, "  use nbi_com")
    nbwrite( f_nbiset, "  use nbi_types")
    nbwrite( f_nbiset, "  implicit NONE")
    nbwrite( f_nbiset, " ")
    nbwrite( f_nbiset, "  type (nbitype_dims), intent(in) :: zdims")
    nbwrite( f_nbiset, "  integer, intent(out) :: ierr")
    nbwrite( f_nbiset, " ")

    nbwrite( f_nbiset, "  ierr=0")
    nbwrite( f_nbiset, "  if(nbidim_init) then")
    nbwrite( f_nbiset, "    write(nonlin,*) '?nbi_set_dims: dimensions already set.'")
    nbwrite( f_nbiset, "    ierr=1")
    nbwrite( f_nbiset, "    return")
    nbwrite( f_nbiset, "  else")
    nbwrite( f_nbiset, "    nbidim_init = .TRUE.")
    nbwrite( f_nbiset, "  endif")
    nbwrite( f_nbiset, " ")

    for item in nbi_udims:
        s = "  " + item[0] + " = max(2, zdims%" + item[0] + " )"
        if item[0] == "mgyro":
            s = "  " + item[0] + " = max(1, zdims%" + item[0] + " )"
        elif item[0] == "mnkaep":
            s = "  if(zdims%" + item[0] + ".gt.0)"+ item[0] + " = min("+ item[0] + ", zdims%" + item[0] + " )"
#            s = "  " + item[0] + " = max(0, zdims%" + item[0] + " )"

        nbwrite( f_nbiset, s)
        if item[2] > 0:
            nbwrite( f_nbiset,"  if(" + item[0] + ".gt." + repr(item[2]) + ") then")
            nbwrite( f_nbiset,"    write(nonlin,*) \"?nbi_set_dims: " +
                     item[0] + " max allowed value is " + repr(item[2]) + ".\"")
            nbwrite( f_nbiset,"    ierr = ierr + 1")
            nbwrite( f_nbiset,"  endif")

    nbwrite( f_nbiset, " ")
    nbwrite( f_nbiset, "  ! program dimensions derived from user dimensions:")
    nbwrite( f_nbiset, " ")
    for item in nbi_pdims:
        s = "  " + item[0] + " = " + item[1]
        nbwrite( f_nbiset, s)
        if item[2] > 0:
            nbwrite( f_nbiset,"  if(" + item[0] + ".gt." + repr(item[2]) + ") then")
            nbwrite( f_nbiset,"    write(nonlin,*) \"?nbi_set_dims: " +
                     item[0] + " max allowed value is " + repr(item[2]) + ".\"")
            nbwrite( f_nbiset,"    ierr = ierr + 1")
            nbwrite( f_nbiset,"  endif")

    nbwrite( f_nbiset, " ")
    nbwrite( f_nbiset, "end subroutine nbi_set_dims")
    nbwrite( f_nbiset, " ")

    # open file to contain mpi_bcast (field state) data

    nbwrite(f_bcast_st,"subroutine nbi_dim_fld_bufput")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  use nbi_com")
    nbwrite(f_bcast_st,"  use nbi_bcastbuf")
    nbwrite(f_bcast_st,"  implicit NONE")
    nbwrite(f_bcast_st,"  integer :: inumi")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  inumi=0")
    nbwrite(f_bcast_st," ")
    for idim in nbi_initdims:
        s = "  call putdat(" + idim + ",inumi)"
        nbwrite(f_bcast_st,s)
    for idim in nbi_finaldims:
        dimname = idim.strip().lower()
        if dimname != "mlost_data":
            s = "  call putdat(" + idim + ",inumi)"
            nbwrite(f_bcast_st,s)
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"end subroutine nbi_dim_fld_bufput")
    nbwrite(f_bcast_st," ")


    nbwrite(f_bcast_st,"subroutine nbi_dim_fld_bufget")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  use nbi_com")
    nbwrite(f_bcast_st,"  use nbi_bcastbuf")
    nbwrite(f_bcast_st,"  implicit NONE")
    nbwrite(f_bcast_st,"  integer :: inumi")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  inumi=0")
    nbwrite(f_bcast_st," ")
    for idim in nbi_initdims:
        s = "  call getdat(" + idim + ",inumi)"
        nbwrite(f_bcast_st,s)
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  call nbi_alloc_init")
    nbwrite(f_bcast_st," ")
    for idim in nbi_finaldims:
        dimname = idim.strip().lower()
        if dimname != "mlost_data":
            s = "  call getdat(" + idim + ",inumi)"
            nbwrite(f_bcast_st,s)
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"end subroutine nbi_dim_fld_bufget")
    nbwrite(f_bcast_st," ")
    # put dimensions in state file...

    nbstate_hdr(f_statio, "nbi_state_define0")

    nbwrite(f_statio,"  idm = (/ 0, 0, 0/)")
    nbwrite(f_statio," ")

    for idim in nbi_alldims:
        if(idim != 'minb' and idim != 'mlost_data' ):
            nbwrite(f_statio,
                    "  call cdfDefVar(icdf, '" + idim + "', idm, 'INT')")

    nbstate_trlr0(f_statio, "nbi_state_define0")

    nbstate_hdr(f_statio, "nbi_state_output0")

    for idim in nbi_alldims:
        if(idim != 'minb' and idim != 'mlost_data'):
            nbwrite(f_statio,
                    "  call cdfPutVar(icdf, '" + idim + "', " + idim + ")")

    nbstate_trlr0(f_statio, "nbi_state_output0")

    nbstate_hdr(f_statio, "nbi_state_read0")

    for idim in nbi_initdims:
        nbwrite(f_statio,"  idm = (/ -1, -1, -1 /)")
        nbwrite(f_statio,
                "  call cdfInqVar(icdf, '" + idim + "', idm, zvartype)")
        nbwrite(f_statio,"  if(idm(1).ne.-1) then")
        nbwrite(f_statio,
                "     call cdfGetVar(icdf, '" + idim + "', " + idim + ")")
        nbwrite(f_statio,"  else")
        strw = "     write(nonlin,*) ' ** DIMENSION (init) not in state file: "
        indxd = nbi_initdims.index(idim)
        if indxd < len(nbi_dimdflts):
            dvald = nbi_dimdflts[indxd]
            strw = strw + idim.upper() + "; default value set.'"
        else:
            dvald = "0"
            strw = strw + idim.upper() + "; cleared to ZERO.'"
        nbwrite(f_statio,strw)
        nbwrite(f_statio,"     " + idim + " = " + dvald)
        nbwrite(f_statio,"  endif")

    nbwrite(f_statio," ")
    nbwrite(f_statio,"  call nbi_alloc_init")
    nbwrite(f_statio," ")

    for idim in nbi_finaldims:
        if(idim != 'minb' and idim != 'mlost_data'):
            nbwrite(f_statio,"  idm = (/ -1, -1, -1 /)")
            nbwrite(f_statio,
                    "  call cdfInqVar(icdf, '" + idim + "', idm, zvartype)")
            nbwrite(f_statio,"  if(idm(1).ne.-1) then")
            nbwrite(f_statio,
                    "     call cdfGetVar(icdf, '" + idim + "', " + idim + ")")
            nbwrite(f_statio,"  else")
            strw = "     write(nonlin,*) ' ** DIMENSION (fin) not in state file: "
            strw = strw + idim.upper() + "; cleared to ZERO'"
            nbwrite(f_statio,strw)
            nbwrite(f_statio,"     " + idim + " = 0")
            nbwrite(f_statio,"  endif")

    nbwrite(f_statio," ")

    nbstate_trlr0(f_statio, "nbi_state_read0")



    #  start ascii i/o routine -- for debugging purposes

    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"  subroutine nbi_ascii")
    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"  use nbi_com")
    nbwrite(f_asciio," ")

    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio,
            "  write(nonlin,*) ' *** array dimensions (initial set) *** '")
    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio," ")
    nbwrite(f_asciio," 1001 format(6x,a,t20,i7)")

    for idim in nbi_initdims:
        s = "  write(nonlin,1001) '" + idim + "', " + idim
        nbwrite(f_asciio,s)
    nbwrite(f_asciio," ")

    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio,
            "  write(nonlin,*) ' *** array dimensions (final set) *** '")
    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio," ")

    for idim in nbi_finaldims:
        s = "  write(nonlin,1001) '" + idim + "', " + idim
        nbwrite(f_asciio,s)
    nbwrite(f_asciio," ")

    nbwrite(f_inp_io,"subroutine nbi_in_dim_def(icdf)")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  use nbi_com")
    nbwrite(f_inp_io,"  use ezcdf")
    nbwrite(f_inp_io,"  implicit NONE")
    nbwrite(f_inp_io,"  integer,intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_inp_io," ")
    for idim in nbi_initdims:
        s = "  call cdf_define(icdf,'" + idim + "'," + idim + ")"
        nbwrite(f_inp_io,s)
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"end subroutine nbi_in_dim_def")
    nbwrite(f_inp_io," ")

    nbwrite(f_inp_io,"subroutine nbi_in_dim_wr(icdf)")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  use nbi_com")
    nbwrite(f_inp_io,"  use ezcdf")
    nbwrite(f_inp_io,"  implicit NONE")
    nbwrite(f_inp_io,"  integer,intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_inp_io," ")
    for idim in nbi_initdims:
        s = "  call cdf_write(icdf,'" + idim + "'," + idim + ")"
        nbwrite(f_inp_io,s)
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"end subroutine nbi_in_dim_wr")
    nbwrite(f_inp_io," ")

    nbwrite(f_inp_io,"subroutine nbi_in_dim_rd(icdf,ierr)")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  use nbi_com")
    nbwrite(f_inp_io,"  use ezcdf")
    nbwrite(f_inp_io,"  implicit NONE")
    nbwrite(f_inp_io,"  integer,intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_inp_io,"  integer,intent(out) :: ierr ! Completion code 0=OK")
    nbwrite(f_inp_io," ")
    for idim in nbi_initdims:
        s = "  call cdf_read(icdf,'" + idim + "'," + idim + ",ierr)"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io,"  if(ierr.ne.0) return")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  if(.not.nbi_init_flag) call nbi_alloc_init")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"end subroutine nbi_in_dim_rd")
    nbwrite(f_inp_io," ")

    nbwrite(f_bcast,"subroutine nbi_initdim_bufput")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  use nbi_com")
    nbwrite(f_bcast,"  use nbi_bcastbuf")
    nbwrite(f_bcast,"  implicit NONE")
    nbwrite(f_bcast,"  integer :: inumi")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  inumi=0")
    nbwrite(f_bcast," ")
    for idim in nbi_initdims:
        s = "  call putdat(" + idim + ",inumi)"
        nbwrite(f_bcast,s)
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"end subroutine nbi_initdim_bufput")
    nbwrite(f_bcast," ")


    nbwrite(f_bcast,"subroutine nbi_initdim_bufget")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  use nbi_com")
    nbwrite(f_bcast,"  use nbi_bcastbuf")
    nbwrite(f_bcast,"  implicit NONE")
    nbwrite(f_bcast,"  integer :: inumi")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  inumi=0")
    nbwrite(f_bcast," ")
    for idim in nbi_initdims:
        s = "  call getdat(" + idim + ",inumi)"
        nbwrite(f_bcast,s)
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  if(.not.nbi_init_flag) call nbi_alloc_init")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"end subroutine nbi_initdim_bufget")
    nbwrite(f_bcast," ")

    return 0

#--------------------------------------------------------------------
# process constants (defined as input parameters...)
#

def nbigen_constants(text,section):

    # this section contains a list of parameter constants, not split
    # into sublocks.  Each is a scalar of type REAL INTEGER LOGICAL
    # REAL*8 or CHARACTER*n ... no arrays allowed.  The specification
    # lines are of the form "<type>  <name> = <expression>"... the
    # validity of expressions is not checked.

    global nbi_initdims    # defined before nbi code control input is given
    global nbi_finaldims   # defined after nbi code control input is given
    global nbi_alldims     # union of the above

    global nbi_allnames    # list of all names...

    nbi_items = []  # individual internal items
    item = []       # single item description

    for line in text:
        if line[0] == "!":
            if item == []:
                print("nbigen_constants: comment not associated with item.")
                nbigen_syntax(section,line)
            else:
                item.append(line)
        else:
            if item != []: nbi_items.append(item)
            item = []

            #---------------------------
            # parse an item
            # <decl>  <name>[(dims)]=<default-value>

            [pllinfo,decl,name,dims,rhs] = nbparse_item(section,line)
            if pllinfo != []:
                print("nbigen_sub: constants: should not be attached to pll dataset")
                nbigen_syntax(section,line)

            if rhs == "":
                print("nbigen_sub: constants: value must be supplied.")
                nbigen_syntax(section,line)

            item.append(name)        # item[0]: the name

            # parse decl: R|I|L|D|C*n[A][S] ...

            [dtype,atype,zmode] = nbparse_decl(section,line,decl,dims)

            if zmode == " ":
                mode = "standard"
            else:
                print("nbigen_sub: invalid character in declaration: ",zmode)
                nbigen_syntax(section,line)

            if atype == "array":
                print("nbigen_sub: arrays of constants not supported:")
                nbigen_syntax(section,line)

            item.append(dtype)  # item[1]: data type (e.g. REAL)
            item.append(rhs)    # item[2]: the definining expression

    # end of loop -- tack last item onto list.

    if item != []:nbi_items.append(item)

    nbwrite(f_nbicom,"  !==============================================")
    nbwrite(f_nbicom,"  ! CONSTANTS...")
    nbwrite(f_nbicom," ")

    for item in nbi_items:

        name = item[0]
        dtype = item[1]  # data type e.g. "INTEGER"
        rhs = item[2]  # scalar or array
        cmts = item[3:]

        # write nbi_com

        s = "  " + dtype.lower() + ", PARAMETER :: " + name + " = " + rhs
        nbwrite(f_nbicom,s)

        for cmt in cmts:
            s = "        " + cmt
            nbwrite(f_nbicom,s)

    #------------------------------------
    #  list of names...

    for item in nbi_items:
        dname = item[0]
        nbi_allnames.append(dname.upper())

    return 0

#--------------------------------------------------------------------
# process input blocks
#

def nbigen_input(text,section):

    # define blocks of input quantities for nubeam module.

    global nbi_initdims    # defined before nbi code control input is given
    global nbi_dimdflts    # default values of the above
    global nbi_finaldims   # defined after nbi code control input is given
    global nbi_alldims     # union of the above

    global nbi_allnames    # list of all names...

    global ialloc_start    # detect 1st allocatable array in alloc routine
    global ialloc2_start   # detect 1st allocatable array in alloc2 routine
    global ialloctr_start   # detect 1st allocatable array in alloc2 routine
    global ialloctrz_start   # detect 1st allocatable array in alloc_track_zone routine
    global ialloctre_start   # detect 1st allocatable array in alloc_track_zone routine
    global iallocm_start   # detect 1st allocatable array in alloc2 routine
    global dval_nltest_output

    nbi_blocks = [] # separate blocks of input
    nbi_items = []  # individual input items
    item = []       # single item description with "!" comments

    curblock = []   # block label with "!" comments

    ps_status = "FALSE"
    pslist = []

    for line in text:
        test = line[:6].upper()
        test2 = line[:9].upper()
        test3 = line[:19].upper()
        if test == "BLOCK:":
            if curblock != []:
                if item != []:
                    nbi_items.append(item)
                item = []
                if nbi_items != []:
                    nbi_blocks.append([curblock,nbi_items])
                nbi_items = []
                curblock = []
            bname = line[6:].strip()
            curblock.append(bname)
            iprev = -2
            if ps_status == "TRUE":
                print('%nbigen_sub: input section: new block: "' + bname + '"; Plasma_State_Input flag is cleared.')
                ps_status = "FALSE"
        elif test3 == "PLASMA_STATE_INPUT:":
            ttmp = line.split(":")
            if len(ttmp) != 2:
                print("expected syntax: <keyword>: <value>")
                nbigen_syntax(section,line)
            else:
                val = ttmp[1].strip().upper()
                if val != "FALSE" and val != "TRUE":
                    print('expected value field "TRUE" or "FALSE".')
                    nbigen_syntax(section,line)
                else:
                    ps_status = val
        else:
            if curblock == []:
                print("nbigen_sub: INPUT section must start with BLOCK: stmt")
                nbigen_syntax(section,line)
            if line[0] == "!":
                if item == []:
                    curblock.append(line)
                else:
                    item.append(line)
            else:
                if item != []: nbi_items.append(item)
                itemp = item
                item = []

                #---------------------------
                # parse an item
                # <decl>  <name>[(dims)]=<default-value>

                [pllinfo,decl,name,dims,rhs] = nbparse_item(section,line)
                if pllinfo != []:
                    print("nbigen_sub: inputs: should not be attached to pll dataset")
                    nbigen_syntax(section,line)

                if rhs == "":
                    print("nbigen_sub: <name>=<default-value> expected.")
                    nbigen_syntax(section,line)

                item.append(name)        # item[0]: the name
                iprev = iprev + 1

                if ps_status == "TRUE":
                    pslist.append(name)
                else:
                    if decl[0:2] == "C*":
                        f_nbipst.write("  public :: nubeam_set_" + name + "\n")

                # parse decl: R|I|L|D|C*n[A][X|M] ...

                [dtype,atype,zmode] = nbparse_decl(section,line,decl,dims)

                if zmode == "X":
                    mode = "extensible"
                    if iprev > -1:
                        if itemp[3] != "extensible":
                            print("nbigen_sub:  all items in block must")
                            print(" be extensible, or none.")
                            nbigen_syntax(section,line)
                    if atype == "scalar":
                        if dtype != "INTEGER":
                            print("nbigen_sub:  only integers scalars allowed")
                            print("  in extensible blocks.")
                            nbigen_syntax(section,line)
                        else:
                            lenvar = name
                elif zmode == "M":
                    mode = "updatable"
                elif zmode == " ":
                    mode = "init_once"
                else:
                    print("nbigen_sub: invalid char. in declaration: ",zmode)
                    nbigen_syntax(section,line)

                item.append(dtype)  # item[1]: data type
                item.append(atype)  # item[2]: "scalar" or "array"
                item.append(mode)   # item[3]: "extensible", "updatable",
                                    #   or "init_once".

                if atype == "array":
                    if dims[0] != "(": nbigen_syntax(section,line)
                    if dims[-1:] != ")": nbigen_syntax(section,line)
                    inside = dims[1:len(dims)-1]
                    parts = inside.split(",")
                    if mode == "extensible":
                        if len(parts) != 1:
                            print("nbigen_sub: extensible items must be 1d lists.")
                            nbigen_syntax(section,line)
                    if dtype.upper() == "LOGICAL":
                        if len(parts) != 1:
                            print("nbigen_sub: LOGICAL input arrays  must be 1d.")
                            nbigen_syntax(section,line)
                    comdim = "("
                    typdim = "("
                    typuse = "("
                    for zpart in parts:
                        part = zpart.strip()
                        indsemi = part.find(";")
                        if indsemi == -1:
                            dimname = part
                            symname = part
                        else:
                            dimname = part[:indsemi].strip()
                            symname = part[indsemi+1:].strip()

                        if mode == "extensible":
                            if symname != lenvar:
                                print("nbigen_sub: list length symbol mismatch:")
                                print("  found: " + synmame + " expected: " + lenvar)
                                nbigen_syntax(section,line)
                        dimname = dimname.lower()
                        nbi_check_dim(dimname,nbi_initdims,section,line)
                        if dimname in nbi_initdims:
                            indx=nbi_initdims.index(dimname)
                            if nbi_initlims[indx] == 0:
                                print("nbigen_sub: dimension invalid: ",dimname)
                                print("nbigen_sub: (no size limit).")
                                nbigen_syntax(section,line)
                            else:
                                dimtype = repr(nbi_initlims[indx])

                            comdim = comdim + dimname + ","
                            typdim = typdim + dimtype + ","
                            typuse = typuse + "1:" + symname + ","
                        else:
                            comdim = comdim + dimname + ","
                            typdim = typdim + dimname + ","
                            typuse = typuse + "1:" + symname + ","

                    # replace trailing comma with closing parenthesis
                    comdim = comdim[:len(comdim)-1]+")"
                    typdim = typdim[:len(typdim)-1]+")"
                    typuse = typuse[:len(typuse)-1]+")"
                else:
                    comdim = " "
                    typdim = " "
                    typuse = " "

                item.append(comdim)  # item[4]: dimensions in nbi_com module
                item.append(typdim)  # item[5]: dimensions in type-element
                item.append(typuse)  # item[6]: dimensions in type, as used.

                item.append(rhs)     # initialization string

    if item != []: nbi_items.append(item)
    if nbi_items != []: nbi_blocks.append([curblock,nbi_items])

    # add to list of all names...

    for triple in nbi_blocks:
        nbi_items = triple[1]
        for item in nbi_items:
            dname = item[0].upper()
            if dname in nbi_allnames:
                print("nbigen_sub: duplicate name: " + dname)
                raise dupname_error
            nbi_allnames.append(dname)

    # parse nbi_udim_dict expressions (now that input variable names are known)
    # expressions used to generate dimensioning information in nbi_pstypes.f90.

    udim_keys = list(nbi_udim_dict.keys())
    for ukey in udim_keys:
        uexpr = nbi_udim_dict[ukey][0]
        uupr = uexpr.upper()
        if uupr[0:9] == "VERBATIM:":
            uinvar = "verbatim:"
            ublock = "verbatim:"
            ubefore = uexpr[9:]
            uafter = ""
            # print uexpr
        elif uupr in nbi_allnames:
            # expression is just the name itself
            uinvar = uupr.lower()
            ublock = find_var_block(uinvar,nbi_blocks,uexpr,ukey)
            ubefore = ""
            uafter = ""
            # print " singleton: ",uexpr,' in ',ublock
        else:
            uinvar = "?error"
            ict = 0
            for delim in ["**","+","-","*","/","("]:
                uelis = uexpr.split(delim)
                if len(uelis) != 2:
                    ict = ict + 1
                elif delim != "(":
                    uupr = uelis[0].strip().upper()
                    if uupr in nbi_allnames:
                        uinvar = uupr.lower()
                        ublock = find_var_block(uinvar,nbi_blocks,uexpr,ukey)
                        ubefore = ""
                        uafter = delim + " " + uelis[1].strip()
                        # print "var 1st in dyadic expr: ",uexpr,' in ',ublock
                    else:
                        uupr = uelis[1].strip().upper()
                        if uupr in nbi_allnames:
                            uinvar = uupr.lower()
                            ublock = find_var_block(uinvar,nbi_blocks,uexpr,ukey)
                            ubefore = uelis[0].strip() + " " + delim
                            uafter = ""
                            # print "var 2nd in dyadic expr: ",uexpr,' in ',ublock
                        else:
                            print("nbigen_sub: detected invalid expression for user settable array dimension:")
                            print("  (one operand must be an input variable).")
                            print("  for dimension " + ukey.upper() + ": expression is:" + uexpr)
                            raise expression_error
                else:
                    uoperator = uelis[0].strip()
                    uoperanda = uelis[1].strip()
                    utrailer = uoperanda[-1:]
                    if utrailer != ")":
                        print("nbigen_sub: detected invalid expression for user settable array dimension:")
                        print("  (trailing close-parenthesis missing).")
                        print("  for dimension " + ukey.upper() + ": expression is:" + uexpr)
                        raise expression_error
                    uupr = uoperanda[:-1].upper()
                    if uupr not in nbi_allnames:
                        print("nbigen_sub: detected invalid expression for user settable array dimension:")
                        print("  (operand must be an input variable).")
                        print("  for dimension " + ukey.upper() + ": expression is:" + uexpr)
                        raise expression_error
                    else:
                        uinvar = uupr.lower()
                        ublock = find_var_block(uinvar,nbi_blocks,uexpr,ukey)
                        ubefore = uoperator + "("
                        uafter = ")"
                        # print " operator(operand-var): ",uexpr,' in ',ublock
            if uinvar == "?error":
                print("nbigen_sub: could not parse user-settable dimension expression:")
                print("  for dimension " + ukey.upper() + ": expression is:" + uexpr)
                raise expression_error

        nbi_udim_dict[ukey].append(uinvar)
        nbi_udim_dict[ukey].append(ublock)
        nbi_udim_dict[ukey].append(ubefore)
        nbi_udim_dict[ukey].append(uafter)

#    for triple in nbi_blocks:
#        curblock = triple[0]
#        nbi_items = triple[1]
#        print "block: " + curblock[0]
#        for item in nbi_items:
#            print "item: ",item[0]
#            print "dtype: ",item[1]
#            print "class: ",item[2]
#            print "access: ",item[3]
#            if item[2] == "array":
#                print "nbi_com dim: ",item[4]
#                print "nbi_typ dim: ",item[5]
#                print "nbi_typ use: ",item[6]
#            print "default setting: ",item[7]

    # in nbi_pstypes, declare local copies of input block structures

    f_nbipst.write(" \n")
    f_nbipst.write("  ! module local copies of input blocks:\n")
    f_nbipst.write(" \n")
    f_nbipst.write("  type(nbitype_dims) :: zdims\n")
    f_nbipst.write(" \n")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        s = "  type(nbitype_" + blockname + ") :: z" + blockname
        f_nbipst.write(s + "\n")

    # start lists, to gather lines for nbi_pstypes declarations

    nbi_ctrl_init_char = []
    nbi_ctrl_init_r8 = []
    nbi_ctrl_init_ii = []

    nbi_ctrl_update_r8 = []
    nbi_ctrl_update_ii = []

    nbi_ps_init = []
    nbi_ps_update = []

    # start allocation subroutine & deallocation subroutine

    nbwrite(f_alloc,"subroutine nbi_alloc_init")
    nbwrite(f_alloc," ")
    nbwrite(f_alloc,"  use nbi_com")
    nbwrite(f_alloc,"  implicit NONE")
    nbwrite(f_alloc," ")
    nbwrite(f_alloc,"  !==============================================")
    nbwrite(f_alloc,"  ! input arrays")
    nbwrite(f_alloc," ")

    nbwrite(f_dalloc,"subroutine nbi_dalloc")
    nbwrite(f_dalloc," ")
    nbwrite(f_dalloc,"  use nbi_com")
    nbwrite(f_dalloc,"  implicit NONE")
    nbwrite(f_dalloc," ")
    nbwrite(f_dalloc,"  !==============================================")
    nbwrite(f_dalloc,"  ! input arrays")
    nbwrite(f_dalloc," ")

    nbwrite(f_allocsplt,"subroutine nbi_alloc_splt")
    nbwrite(f_allocsplt," ")
    nbwrite(f_allocsplt,"  use nbi_com")
    nbwrite(f_allocsplt,"  implicit NONE")
    nbwrite(f_allocsplt," ")
    nbwrite(f_allocsplt,"  !==============================================")
    nbwrite(f_allocsplt,"  ! allocate arrays")
    nbwrite(f_allocsplt," ")

    nbwrite(f_dallocsplt,"subroutine nbi_dalloc_splt")
    nbwrite(f_dallocsplt," ")
    nbwrite(f_dallocsplt,"  use nbi_com")
    nbwrite(f_dallocsplt,"  implicit NONE")
    nbwrite(f_dallocsplt," ")
    nbwrite(f_dallocsplt,"  !==============================================")
    nbwrite(f_dallocsplt,"  ! allocate arrays")
    nbwrite(f_dallocsplt," ")

    nbwrite(f_spltexpnd,"subroutine nbi_spltexpnd(ierror)")
    nbwrite(f_spltexpnd," ")
    nbwrite(f_spltexpnd,"  use nbi_com")
    nbwrite(f_spltexpnd,"  implicit NONE")
    nbwrite(f_spltexpnd,"  integer :: ierror")
    nbwrite(f_spltexpnd,"  integer :: minbs_save")
    nbwrite(f_spltexpnd,"  integer,save :: i_spltexpnd = 2")
    nbwrite(f_spltexpnd,"  integer,allocatable :: itmp(:)")
    nbwrite(f_spltexpnd,"  real(fp),allocatable :: tmp(:)")
    nbwrite(f_spltexpnd," ")
    nbwrite(f_spltexpnd,"  ierror = 0")
    nbwrite(f_spltexpnd,"  minbs_save = minbs_expnd   ! old value")
    nbwrite(f_spltexpnd,"  minbs_expnd = minbs * i_spltexpnd")
    nbwrite(f_spltexpnd,"  minbs_expnd = min(minbs_expnd, ntotptp(lsbeam)-nuse(lsbeam))")
    nbwrite(f_spltexpnd,"  if(minbs_expnd.le.0) then ")
    nbwrite(f_spltexpnd,"     ierror = 1")
    nbwrite(f_spltexpnd,"     return")
    nbwrite(f_spltexpnd,"  endif")
    nbwrite(f_spltexpnd,"  if(allocated(tmp)) deallocate(tmp)")
    nbwrite(f_spltexpnd,"  allocate(tmp(1:minbs_save)); tmp = zero")
    nbwrite(f_spltexpnd,"  if(allocated(itmp)) deallocate(itmp)")
    nbwrite(f_spltexpnd,"  allocate(itmp(1:minbs_save)); itmp = zero")
    nbwrite(f_spltexpnd," ")
    nbwrite(f_spltexpnd,"  !==============================================")
    nbwrite(f_spltexpnd,"  ! expand arrays")
    nbwrite(f_spltexpnd," ")

    nbwrite(f_nbicom,"  !==============================================")
    nbwrite(f_nbicom,"  ! INPUT items...")

    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio,"  write(nonlin,*) ' *** INPUT items *** '")

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]

        if nbi_items[0][3] == "extensible":
            block_mode = "extensible"
            jset = "FALSE"
        else:
            block_mode = "normal"
            jset = "TRUE"

        update_flag = 0
        jmod = "FALSE"
        for item in nbi_items:
            if item[3] == "updatable":
                update_flag = 1
                jmod = "TRUE"

        # help file
        ihelp_start(f_help4, blockname, jset, jmod)

        # module

        nbwrite(f_nbicom,"  ! block: " + blockname)
        for cmt in curblock[1:]:
            nbwrite(f_nbicom,"    "+cmt)
            nbwrite(f_help4,  "    "+cmt)
        nbwrite(f_nbicom," ")

        initflag = "init_" + blockname
        nbwrite(f_nbicom,"  LOGICAL :: " + initflag + " = .FALSE.")
        nbwrite(f_nbicom," ")

        # ascii output

        nbwrite(f_asciio," ")
        nbwrite(f_asciio,"  write(nonlin,*) ' '")
        nbwrite(f_asciio,"  write(nonlin,*) ' *** block: " + blockname +
                " *** '")
        nbwrite(f_asciio,"  write(nonlin,*) ' '")
        nbwrite(f_asciio," ")

        # data type for information transfers

        ztype = "nbitype_" + blockname
        nbwrite(f_nbityp,"  type " + ztype)
        nbwrite(f_nbityp," ")

        # set defaults

        nbwrite(f_nbinit,"subroutine nbi_init_" + blockname + "(zblock)")
        nbwrite(f_nbinit," ")
        nbwrite(f_nbinit,"  ! default values for input block: " + blockname)
        nbwrite(f_nbinit," ")
        nbwrite(f_nbinit,"  use nbi_com")
        nbwrite(f_nbinit,"  use nbi_types")
        nbwrite(f_nbinit,"  implicit NONE")
        nbwrite(f_nbinit," ")
        s = "  type (nbitype_" + blockname + "), intent(out) :: zblock"
        nbwrite(f_nbinit,s)
        nbwrite(f_nbinit," ")

        inaml_count = 0

        # set values

        subname = "nbi_set_" + blockname
        if block_mode == "extensible":  subname = "nbi_add_" + blockname

        nbwrite(f_nbiset,"subroutine " + subname + "(zblock,ierr)")
        nbwrite(f_nbiset," ")
        nbwrite(f_nbiset,"  ! set values for input block: " + blockname)
        nbwrite(f_nbiset," ")
        nbwrite(f_nbiset,"  use nbi_com")
        nbwrite(f_nbiset,"  use nbi_types")
        nbwrite(f_nbiset,"  implicit NONE")
        nbwrite(f_nbiset," ")
        s = "  type (nbitype_" + blockname + "), intent(in) :: zblock"
        nbwrite(f_nbiset,s)
        nbwrite(f_nbiset,"  integer, intent(out) :: ierr")
        nbwrite(f_nbiset," ")
        if block_mode == "extensible":
            nbwrite(f_nbiset,"  integer :: iprev,inc")
            nbwrite(f_nbiset," ")
            nbwrite(f_nbiset,"  ierr=0")
            nbwrite(f_nbiset,"  init_" + blockname + " = .TRUE.")
        else:
            nbwrite(f_nbiset,"  ierr=0")
            nbwrite(f_nbiset,"  if(init_" + blockname + ") then")
            s = "    write(nonlin,*) '"
            s = s + "?" + subname + ": block was already initialized.'"
            nbwrite(f_nbiset, s)
            nbwrite(f_nbiset,"    ierr=1; return")
            nbwrite(f_nbiset,"  else")
            nbwrite(f_nbiset,"    init_" + blockname + " = .TRUE.")
            nbwrite(f_nbiset,"  endif")
            nbwrite(f_nbiset," ")

        # get values

        nbwrite(f_nbiget,"subroutine nbi_get_" + blockname + "(zblock)")
        nbwrite(f_nbiget," ")
        nbwrite(f_nbiget,"  ! fetch values for input block: " + blockname)
        nbwrite(f_nbiget," ")
        nbwrite(f_nbiget,"  use nbi_com")
        nbwrite(f_nbiget,"  use nbi_types")
        nbwrite(f_nbiget,"  implicit NONE")
        nbwrite(f_nbiget," ")
        s = "  type (nbitype_" + blockname + "), intent(out) :: zblock"
        nbwrite(f_nbiget,s)
        nbwrite(f_nbiget," ")
        nbwrite(f_nbiget,"  if(.not.init_" + blockname + ") then")
        s = "     write(nonlin,*) 'nbi_get_" + blockname + " warning:"
        s = s + " block was never initialized.'"
        nbwrite(f_nbiget,s)
        nbwrite(f_nbiget,"  endif")

        if update_flag == 1:

            # update values

            nbwrite(f_update,"subroutine nbi_update_" + blockname + "(zblock)")
            nbwrite(f_update," ")
            nbwrite(f_update,"  ! update values for input block: " + blockname)
            nbwrite(f_update," ")
            nbwrite(f_update,"  use nbi_com")
            nbwrite(f_update,"  use nbi_types")
            nbwrite(f_update,"  implicit NONE")
            nbwrite(f_update," ")
            s = "  type (nbitype_" + blockname + "), intent(in) :: zblock"
            nbwrite(f_update,s)
            nbwrite(f_update," ")

        iflag = 0
        for item in nbi_items:
            sdflt0 = item[0] + " = " + item[7]
            if item[7] in nbi_initdims:
                print(" ?nbspec.dat no longer supports using an array ")
                print("  dimension symbol as the default value of an input ")
                print("  variable, for technical reasons.")
                print("     cf: ",sdflt0)
                raise default_setting_error
            else:
                sdflt1 = sdflt0

            nbwrite(f_nbinit,"  zblock%" + sdflt0)

            if item[1] == "REAL":
                type_abbrev = "R"
            elif item[1] == "REAL(fp)":
                type_abbrev = "D"
            elif item[1] == "INTEGER":
                type_abbrev = "I"
            elif item[1].upper() == "LOGICAL":
                type_abbrev = "L"
            elif item[1][0:4] == "CHAR":
                type_abbrev = "C"

            if item[2] == "array":

                # in nbi_com_mod.f90:

                s = "  " + item[1].lower() + ", dimension("
                dlist = item[4].split(",")
                for d in dlist:
                    s = s + ":,"
                s = s[:len(s)-1]+"), allocatable :: " + item[0]
                nbwrite(f_nbicom,s)

                # in nbi_alloc.f90 & nbi_dalloc.f90:

                s = "  if(allocated("+item[0]+")) deallocate("+item[0]+")"
                nbwrite(f_dalloc,s)

                ialloc_start = wr_alloc_check(f_alloc,
                                              "nbi_alloc",item[0],ialloc_start)
                s = "  allocate(" + item[0] + item[4] + ")"
                nbwrite(f_alloc,s)
                s = "  " + item[0] + " = " + item[7]
                nbwrite(f_alloc,s)

                # in nbi_ascii.f90:

                udlist = item[6][1:-1].split(",")
                udimn = len(udlist)
                sname = "nbi_ascii_" + type_abbrev + "_wr" + repr(udimn)
                s = "  call " + sname
                s = s + "(nonlin, '" + item[0] + "', " + item[0] + item[6]
                for udp in udlist:
                    udima = udp[2:]
                    s = s + "," + udima
                s = s + ")"

                nbwrite(f_asciio,s)

                # in nbi_types.f90:

                s = "    " + item[1].lower() + " :: " + item[0] + item[5]
                s = s + "  ! " + item[6]
                str2 = s
                strb=item[0]
                dtpe=item[1]
                if item[1] == "REAL":
                    str2 = "    REAL(FP) :: " + item[0] + item[5]
                    str2 = str2 + "  ! " + item[6]
                    print(item[1])

                iiname = item[0]
                iilims = item[6].strip()
                iilims = iilims[1:-1]
                iilims = iilims.split(':')

                str3 = "  DO II = " + iilims[0] + "," + iilims[1]
                str4 = "    write(lunnbx,*) ' " + iiname + "(',ii,')=',"
                str4 = str4 + iiname + "(ii)"
                str5 = "  ENDDO"

                nbwrite(f_nbityp,s)

                sstr = s.strip()
                if iiname in pslist:
                    if sstr[0:7].upper() == "LOGICAL":
                        tstr = "INTEGER" + sstr[7:]
                    else:
                        tstr = sstr
                    # quantity to be set from plasma state
                    nbi_ps_init.append([tstr,blockname,item])
                    if item[3] == "updatable":
                        nbi_ps_update.append([tstr,blockname,item])

                else:
                    # quantity to be set from user accessible control structure
                    # REAL*8 and INTEGER only; LOGICALs are converted.
                    if item[1][0:4].upper() == "CHAR":
                        tsplit = sstr.split("::")
                        tstr = tsplit[0] + ":: saved_" + tsplit[1].strip()
                        nbi_ctrl_init_char.append([tstr,blockname,item])
                    else:
                        if item[1][0:4].upper() == "REAL":
                            nbi_ctrl_init_r8.append([sstr,blockname,item])
                            if item[3] == "updatable":
                                nbi_ctrl_update_r8.append([sstr,blockname,item])

                        else:
                            if sstr[0:7].upper() == "LOGICAL":
                                tstr = "INTEGER" + sstr[7:]
                            else:
                                tstr = sstr

                            nbi_ctrl_init_ii.append([tstr,blockname,item])
                            if item[3] == "updatable":
                                nbi_ctrl_update_ii.append([tstr,blockname,item])

                nbwrite(f_help4," ")
                if item[3] == "extensible":
                    nbwrite(f_help4,s + "  *extensible list*")
                elif item[3] == "updatable":
                    nbwrite(f_help4,s + "  *updatable*")
                else:
                    nbwrite(f_help4,s)
                nbwrite(f_help4,"    !  --> default value: " + item[7])

                # in nbi_set.f90

                if block_mode == "extensible":
                    if iflag == 1:
                        nbwrite(f_nbiset,"  if (iprev+inc.gt." + item[4] + ") then")
                        s = "    write(nonlin,*) '?" + subname + ": maximum"
                        s = s + " length of " + item[0] + " exceeded.'"
                        nbwrite(f_nbiset, s)
                        s = "    write(nonlin,*) ' needed: ',iprev+inc"
                        nbwrite(f_nbiset, s)
                        s = "    write(nonlin,*) ' available: " + item[4] + " = "
                        s = s + "', " + item[4]
                        nbwrite(f_nbiset, s)
                        nbwrite(f_nbiset, "    ierr=1; return")
                        nbwrite(f_nbiset,"  endif")
                        nbwrite(f_nbiset," ")
                        iflag = 0

                    nbwrite(f_nbiset,"  if (inc.gt.0) then")
                    s = "    " + item[0] + "(iprev+1:iprev+inc) = "
                    s = s + "zblock%" + item[0] + "(1:inc)"
                    nbwrite(f_nbiset,s)
                    nbwrite(f_nbiset,"  endif")
                    nbwrite(f_nbiset," ")

                else:
                    s = "  " + item[0] + item[6] + " = "
                    s = s + "zblock%" + item[0] + item[6]
                    nbwrite(f_nbiset,s)

                s = "  z" + blockname + "%" + item[0] + item[6]
                s = s + " = " + item[0] + item[6]

                # in nbi_get.f90

                [dvalt,dvt_abbrev] = nbtype_dval(item[1])
                nbwrite(f_nbiget,"  zblock%" + item[0] + " = " + dvalt)

                s = "  " + "zblock%" + item[0] + item[6] + " = "
                s = s + item[0] + item[6]
                nbwrite(f_nbiget,s)

                # in nbi_update.f90

                if item[3] == "updatable":
                    s = "  " + item[0] + item[6] + " = "
                    s = s + "zblock%" + item[0] + item[6]
                    nbwrite(f_update,s)

            else:
                # in nbi_com_mod.f90:
                if item[7] in nbi_alldims:
                    s = "  " + item[1].lower() + " :: " + item[0] + " = 0"
                else:
                    s = "  " + item[1].lower() + " :: " + item[0] + " = " + item[7]
                    if item[0].lower() ==  "nltest_output":
                        dval_nltest_output = item[7]




                nbwrite(f_nbicom,s)

                # in nbi_ascii.f90:

                sname = "nbi_ascii_" + type_abbrev + "_wr0"
                s = "  call " + sname
                s = s + "(nonlin, '" + item[0] + "', " + item[0] + ")"
                nbwrite(f_asciio,s)

                # in nbi_types.f90:

                iiname = item[0]

                s = "    " + item[1] + " :: " + iiname
                nbwrite(f_nbityp,s)

                sstr = s.strip()
                if iiname in pslist:
                    if sstr[0:7].upper() == "LOGICAL":
                        tstr = "INTEGER" + sstr[7:]
                    else:
                        tstr = sstr
                    # quantity to be set from plasma state
                    nbi_ps_init.append([tstr,blockname,item])
                    if item[3] == "updatable":
                        nbi_ps_update.append([tstr,blockname,item])

                else:
                    # quantity to be set from user accessible control structure
                    # REAL*8 and INTEGER only; LOGICALs are converted.
                    if item[1][0:4].upper() == "CHAR":
                        tsplit = sstr.split("::")
                        tstr = tsplit[0] + ":: saved_" + tsplit[1].strip()
                        nbi_ctrl_init_char.append([tstr,blockname,item])
                    else:

                        if item[1][0:4].upper() == "REAL":
                            nbi_ctrl_init_r8.append([sstr,blockname,item])
                            if item[3] == "updatable":
                                nbi_ctrl_update_r8.append([sstr,blockname,item])

                        else:
                            if sstr[0:7].upper() == "LOGICAL":
                                tstr = "INTEGER" + sstr[7:]
                            else:
                                tstr = sstr

                            nbi_ctrl_init_ii.append([tstr,blockname,item])
                            if item[3] == "updatable":
                                nbi_ctrl_update_ii.append([tstr,blockname,item])

                nbwrite(f_help4," ")
                if item[3] == "extensible":
                    nbwrite(f_help4,s + " !  *extensible list*")
                elif item[3] == "updatable":
                    nbwrite(f_help4,s + " !  *updatable*")
                else:
                    nbwrite(f_help4,s)
                nbwrite(f_help4,"    !  --> default value: " + item[7])

                strb=item[0]
                dtpe=item[1]

                str2 = s
                if item[1].upper() == "REAL":
                    str2 = "    real(fp) :: " + item[0]
                    print(item[1])

                str3 = "  write(lunnbx,*) ' " + item[0] + "='," + item[0]

                # in nbi_set.f90

                if block_mode == "extensible":
                    nbwrite(f_nbiset,"  inc = zblock%" + item[0])
                    nbwrite(f_nbiset,"  iprev = " + item[0])
                    nbwrite(f_nbiset,"  " + item[0] + " = iprev + inc")
                    nbwrite(f_nbiset," ")
                    iflag = 1
                else:
                    s = "  " + item[0] + " = zblock%" + item[0]
                    nbwrite(f_nbiset,s)
                    if item[0].lower() ==  "nltest_output":
                        s = "#ifdef __MPI"
                        nbwrite(f_nbiset,s)
                        nbwrite(f_nbiset,"    debug_mpi = nltest_output")
                        s = "#else"
                        nbwrite(f_nbiset,s)
                        nbwrite(f_nbiset,"    debug_mpi = .FALSE.")
                        s = "#endif"
                        nbwrite(f_nbiset,s)

                s = "  z" + blockname + "%" + item[0] + " = " + item[0]

                # in nbi_get.f90

                s = "  zblock%" + item[0] + " = " + item[0]
                nbwrite(f_nbiget,s)

                if item[3] == "updatable":
                    s = "  " + item[0] + " = zblock%" + item[0]
                    nbwrite(f_update,s)
                    if item[0].lower() ==  "nltest_output":
                        s = "#ifdef __MPI"
                        nbwrite(f_update,s)
                        nbwrite(f_update,"    debug_mpi = nltest_output")
                        s = "#else"
                        nbwrite(f_update,s)
                        nbwrite(f_update,"    debug_mpi = .FALSE.")
                        s = "#endif"
                        nbwrite(f_update,s)


            for cmt in item[8:]:
                nbwrite(f_nbicom,"        " + cmt)
                nbwrite(f_help4,  "        " + cmt)

        #  finish up after loop through all items...

        nbwrite(f_nbicom," ")

        nbwrite(f_nbityp," ")
        nbwrite(f_nbityp,"  end type " + ztype)
        nbwrite(f_nbityp," ")

        nbwrite(f_nbinit," ")
        nbwrite(f_nbinit,"end subroutine nbi_init_" + blockname)
        nbwrite(f_nbinit," ")

        nbwrite(f_nbiset," ")
        nbwrite(f_nbiset,"end subroutine " + subname)
        nbwrite(f_nbiset," ")

        nbwrite(f_nbiget," ")
        nbwrite(f_nbiget,"end subroutine nbi_get_" + blockname)
        nbwrite(f_nbiget," ")

        if update_flag == 1:
            nbwrite(f_update," ")
            nbwrite(f_update,"end subroutine nbi_update_" + blockname)
            nbwrite(f_update," ")

    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"end subroutine nbi_ascii")

    # OK now generate code for state file i/o
    # the state file code will be continued for internal variables

    # the state file contains all input scalars and arrays

    # cdfDefVar calls...

    nbstate_hdr(f_statio, "nbi_state_define1")

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbwrite(f_statio,"  ! --------------> block: " + blockname)
        nbi_items = triple[1]

        nbwrite_defvar("init_" + blockname, "INT", [])

        for item in nbi_items:

            dname = item[0]

            if dname[0:3] != "id_":
                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                nbwrite_defvar(dname,dabbrev,dims)

    nbstate_trlr0(f_statio, "nbi_state_define1")

    # cdfPutVar calls...

    nbstate_hdr(f_statio, "nbi_state_output1")

    sublist = []
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbwrite(f_statio,"  ! --------------> block: " + blockname)
        nbi_items = triple[1]

        nbwrite_putvar("init_" + blockname, "LOGICAL", 0, [], "")

        for item in nbi_items:

            dname = item[0]
            dtype = item[1]

            if dname[0:3] != "id_":
                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                zlist = nbwrite_putvar(dname,dtype,ndims,dims,dimstring)
                sublist = sublist + zlist

    nbwrite(f_statio," ")
    nbstate_trlr(f_statio, "nbi_state_output1", sublist)

    # Open file to put data for MPI broadcast (state field)
    nbwrite(f_bcast_st,"subroutine nbi_fld_bufput")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  use nbi_com")
    nbwrite(f_bcast_st,"  use nbi_bcastbuf")
    nbwrite(f_bcast_st,"  use nbi_random")
    nbwrite(f_bcast_st,"  use rngdef")
    nbwrite(f_bcast_st,"  use nbi_idhdr")
    nbwrite(f_bcast_st,"  implicit NONE")
    nbwrite(f_bcast_st,"  integer :: inumi,inumr,inumc,inuml")
    nbwrite(f_bcast_st,"  integer :: NBI_STATE_INDX")
    nbwrite(f_bcast_st,"  real(double), dimension(0:rng_k-1) :: NBI_STATE_ARR")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  NBI_STATE_INDX=RNG_CURSTATE%INDEX")
    nbwrite(f_bcast_st,"  NBI_STATE_ARR(0:RNG_K-1)=RNG_CURSTATE%ARRAY(0:RNG_K-1)")
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st,"  inumi=0")
    nbwrite(f_bcast_st,"  inumr=0")
    nbwrite(f_bcast_st,"  inumc=0")
    nbwrite(f_bcast_st,"  inuml=0")
    nbwrite(f_bcast_st," ")

    # Open file to get data from broadcast buffer  (state field)
    nbwrite(f_bcast_st_get,"subroutine nbi_fld_bufget")
    nbwrite(f_bcast_st_get," ")
    nbwrite(f_bcast_st_get,"  use nbi_com")
    nbwrite(f_bcast_st_get,"  use nbi_bcastbuf")
    nbwrite(f_bcast_st_get,"  use nbi_random")
    nbwrite(f_bcast_st_get,"  use rngdef")
    nbwrite(f_bcast_st_get,"  use nbi_idhdr")
    nbwrite(f_bcast_st_get,"  implicit NONE")
    nbwrite(f_bcast_st_get,"  integer :: inumi,inumr,inumc,inuml")
    nbwrite(f_bcast_st_get,"  integer :: NBI_STATE_INDX")
    nbwrite(f_bcast_st_get,"  real(double), dimension(0:rng_k-1) :: NBI_STATE_ARR")
    nbwrite(f_bcast_st_get," ")
    nbwrite(f_bcast_st_get,"  inumi=0")
    nbwrite(f_bcast_st_get,"  inumr=0")
    nbwrite(f_bcast_st_get,"  inumc=0")
    nbwrite(f_bcast_st_get,"  inuml=0")
    nbwrite(f_bcast_st_get," ")

    # cdfInqVar/cdfGetVar calls...

    nbstate_hdr(f_statio, "nbi_state_read1")

    sublist = []
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbwrite(f_statio,"  ! --------------> block: " + blockname)
        nbi_items = triple[1]

        zzlist = nbwrite_getvar("init_" + blockname, "LOGICAL", ".FALSE.", 0, [], "")

        for item in nbi_items:

            dname = item[0]
            dtype = item[1]
            dval = item[7]

            if dname[0:3] != "id_":
                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                zlist = nbwrite_getvar(dname,dtype,dval,ndims,dims,dimstring)
                sublist = sublist + zlist

    nbwrite(f_statio," ")
    nbwrite(f_statio,"  call nbi_alloc2_init")
    nbstate_trlr(f_statio, "nbi_state_read1", sublist)

    # Put data (read1) into broadcast buffer

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]

        s = "  call putdat(init_" + blockname + ",inuml)"
        nbwrite(f_bcast_st,s)
        s = "  call getdat(init_" + blockname + ",inuml)"
        nbwrite(f_bcast_st_get,s)

        for item in nbi_items:
            dname = item[0]
            dtype = item[1]
            if dtype[0]=='R':
             s = "  call putdat(" + dname + ",inumr)"
             nbwrite(f_bcast_st,s)
             s = "  call getdat(" + dname + ",inumr)"
             nbwrite(f_bcast_st_get,s)
            if dtype[0]=='I':
             s = "  call putdat(" + dname + ",inumi)"
             nbwrite(f_bcast_st,s)
             s = "  call getdat(" + dname + ",inumi)"
             nbwrite(f_bcast_st_get,s)

            if dtype[0]=='C':
             s = "  call putdat(" + dname + ",inumc)"
             nbwrite(f_bcast_st,s)
             s = "  call getdat(" + dname + ",inumc)"
             nbwrite(f_bcast_st_get,s)
            if dtype[0]=='L':
             s = "  call putdat(" + dname + ",inuml)"
             nbwrite(f_bcast_st,s)
             s = "  call getdat(" + dname + ",inuml)"
             nbwrite(f_bcast_st_get,s)
             if dname=='nlfbmflr':
                 nbwrite(f_bcast_st_get,"  call nbi_alloc2_init")

    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st_get," ")

    # xplasma id save/restore operations

    for oper in ["save", "restore"]:
        nbwrite(f_statio, " ")
        nbwrite(f_statio, "!=======================")
        nbwrite(f_statio, "subroutine nbi_id_" + oper )
        nbwrite(f_statio, "  use nbi_com")
        nbwrite(f_statio, "  implicit NONE")
        nbwrite(f_statio, " ")

        for triple in nbi_blocks:
            curblock = triple[0]
            blockname = curblock[0]
            icount = 0
            nbi_items = triple[1]
            for item in nbi_items:

                dname = item[0]
                dtype = item[1]

                if dname[0:3] == "id_" and dname != "id_mcgrid":
                    icount = icount +1
                    if icount == 1:
                        nbwrite(f_statio,
                                "  ! --------------> block: " + blockname)
                    [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,1)

                    if ndims == 0:
                        s = "  call nbi_" + oper + "_id0('"
                        s = s + dname + "'," + dname + ")"
                    elif ndims == 1:
                        s = "  call nbi_" + oper + "_id1('"
                        s = s + dname + "'," + dname + "," + dims[0] + ")"
                    elif ndims == 2:
                        s = "  call nbi_" + oper + "_id2('"
                        s = s + dname + "'," + dname
                        s = s + "," + dims[0] + "," + dims[1] + ")"
                    else:
                        s = "  call nbi_" + oper + "_id('"
                        s = s + dname + "'," + dname

                        for dim in dims:
                            s = s + "," + dim

                        s = s + ")"

                    nbwrite(f_statio,s)

        nbwrite(f_statio, " ")
        nbwrite(f_statio, "end subroutine nbi_id_" + oper)

    # inputs read/write via NetCDF file...

    nbwrite(f_inp_io,"subroutine nbi_inputs_write(icdf)")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  ! write file of NUBEAM inputs.")
    nbwrite(f_inp_io,"  implicit NONE")
    nbwrite(f_inp_io,"  integer,intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  call nbi_in_dim_def(icdf)")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        s = "  call nbi_in_" + blockname + "_def(icdf)"
        nbwrite(f_inp_io,s)
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  call nbi_in_dim_wr(icdf)")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        s = "  call nbi_in_" + blockname + "_wr(icdf)"
        nbwrite(f_inp_io,s)
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"end subroutine nbi_inputs_write")
    nbwrite(f_inp_io," ")

    nbwrite(f_inp_io,"subroutine nbi_inputs_read(icdf,ierr)")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  ! read file of NUBEAM inputs.")
    nbwrite(f_inp_io,"  implicit NONE")
    nbwrite(f_inp_io,"  integer,intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_inp_io,"  integer,intent(out) :: ierr ! completion code, 0=OK")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"  call nbi_in_dim_rd(icdf,ierr)")
    nbwrite(f_inp_io,"  if(ierr.ne.0) return")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        s = "  call nbi_in_" + blockname + "_rd(icdf,ierr)"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io,"  if(ierr.ne.0) return")
    nbwrite(f_inp_io," ")
    nbwrite(f_inp_io,"end subroutine nbi_inputs_read")
    nbwrite(f_inp_io," ")

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        s = "subroutine nbi_in_" + blockname + "_def(icdf)"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        nbwrite(f_inp_io,"  use nbi_com")
        nbwrite(f_inp_io,"  use ezcdf")
        nbwrite(f_inp_io,"  implicit NONE")
        nbwrite(f_inp_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_inp_io," ")
        for item in nbi_items:
            dname = item[0]
            s = "  call cdf_define(icdf,'" + dname + "'," + dname + ")"
            nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        s = "end subroutine nbi_in_" + blockname + "_def"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        s = "subroutine nbi_in_" + blockname + "_wr(icdf)"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        nbwrite(f_inp_io,"  use nbi_com")
        nbwrite(f_inp_io,"  use ezcdf")
        nbwrite(f_inp_io,"  implicit NONE")
        nbwrite(f_inp_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_inp_io," ")
        for item in nbi_items:
            dname = item[0]
            s = "  call cdf_write(icdf,'" + dname + "'," + dname + ")"
            nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        s = "end subroutine nbi_in_" + blockname + "_wr"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")

    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        s = "subroutine nbi_in_" + blockname + "_rd(icdf,ierr)"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        nbwrite(f_inp_io,"  use nbi_com")
        nbwrite(f_inp_io,"  use ezcdf")
        nbwrite(f_inp_io,"  implicit NONE")
        nbwrite(f_inp_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_inp_io,"  integer, intent(out) :: ierr ! completion code, 0=OK")
        nbwrite(f_inp_io," ")
        for item in nbi_items:
            dname = item[0]
            s = "  call cdf_read(icdf,'" + dname + "'," + dname + ",ierr)"
            nbwrite(f_inp_io,s)
            nbwrite(f_inp_io,"  if(ierr.ne.0) return")
        nbwrite(f_inp_io," ")
        s = "  init_" + blockname + " = .TRUE."
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")
        s = "end subroutine nbi_in_" + blockname + "_rd"
        nbwrite(f_inp_io,s)
        nbwrite(f_inp_io," ")

    nbwrite(f_bcast,"subroutine nbi_bufput_data")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  use nbi_com")
    nbwrite(f_bcast,"  use nbi_bcastbuf")
    nbwrite(f_bcast,"  implicit NONE")
    nbwrite(f_bcast,"  integer :: inumi,inumr,inumc,inuml")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  inumi=0")
    nbwrite(f_bcast,"  inumr=0")
    nbwrite(f_bcast,"  inumc=0")
    nbwrite(f_bcast,"  inuml=0")
    nbwrite(f_bcast," ")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        for item in nbi_items:
            dname = item[0]
            dtype = item[1]
            if dtype[0]=='R':
             s = "  call putdat(" + dname + ",inumr)"
             nbwrite(f_bcast,s)
            if dtype[0]=='I':
             s = "  call putdat(" + dname + ",inumi)"
             nbwrite(f_bcast,s)
            if dtype[0]=='C':
             s = "  call putdat(" + dname + ",inumc)"
             nbwrite(f_bcast,s)
            if dtype[0]=='L':
             s = "  call putdat(" + dname + ",inuml)"
             nbwrite(f_bcast,s)
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"end subroutine nbi_bufput_data")
    nbwrite(f_bcast," ")

    nbwrite(f_bcast,"subroutine nbi_bufget_data")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  use nbi_com")
    nbwrite(f_bcast,"  use nbi_bcastbuf")
    nbwrite(f_bcast,"  implicit NONE")
    nbwrite(f_bcast,"  integer :: inumr,inumi,inumc,inuml")
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"  inumi=0")
    nbwrite(f_bcast,"  inumr=0")
    nbwrite(f_bcast,"  inumc=0")
    nbwrite(f_bcast,"  inuml=0")
    nbwrite(f_bcast," ")
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        for item in nbi_items:
            dname = item[0]
            dtype = item[1]
            if dtype[0]=='R':
             s = "  call getdat(" + dname + ",inumr)"
             nbwrite(f_bcast,s)
            if dtype[0]=='I':
             s = "  call getdat(" + dname + ",inumi)"
             nbwrite(f_bcast,s)
            if dtype[0]=='C':
             s = "  call getdat(" + dname + ",inumc)"
             nbwrite(f_bcast,s)
            if dtype[0]=='L':
             s = "  call getdat(" + dname + ",inuml)"
             nbwrite(f_bcast,s)
    nbwrite(f_bcast," ")
    nbwrite(f_bcast,"end subroutine nbi_bufget_data")
    nbwrite(f_bcast," ")

    #-------------------------------------------------
    # write saved copies of character variables...

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  ! saved copies of character control variables")
    for elem in nbi_ctrl_init_char:
        nbwrite(f_nbipst,"  " + elem[0])

    #-------------------------------------------------
    # write type definitions in nbi_pstypes

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  type nbi_ps_init")
    nbwrite(f_nbipst," ")

    for elem in nbi_ps_init:
        nbwrite(f_nbipst,"    " + elem[0])

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end type nbi_ps_init")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  type nbi_ps_update")
    nbwrite(f_nbipst," ")

    for elem in nbi_ps_update:
        nbwrite(f_nbipst,"    " + elem[0])

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end type nbi_ps_update")

    cNbiTypes = open("nbiTypes.h", "w")
    print("""
/**
 * written by nbigen.py
 * !!! do not edit !!! (use nbigen.py instead)
 */
 """, file=cNbiTypes)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  type nbi_ctrl_init")
    nbwrite(f_nbipst,"    SEQUENCE")
    nbwrite(f_nbipst," ")
    print("""
struct nbiCtrlInit {
""", file=cNbiTypes)

    for elem in nbi_ctrl_init_r8:
###        print '===> elem=', elem
        nbwrite(f_nbipst,"    " + elem[0])
        print(nbigen_fortran2C.translate(elem[0]), file=cNbiTypes)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        nbwrite(f_nbipst,"    " + elem[0])
        print(nbigen_fortran2C.translate(elem[0]), file=cNbiTypes)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end type nbi_ctrl_init")
    print("""
};  /* nbiCtrlInit */

""", file=cNbiTypes)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  type nbi_ctrl_update")
    nbwrite(f_nbipst,"    SEQUENCE")
    nbwrite(f_nbipst," ")
    print("""
struct nbiCtrlUpdate {
""", file=cNbiTypes)

    for elem in nbi_ctrl_update_r8:
        nbwrite(f_nbipst,"    " + elem[0])
        print(nbigen_fortran2C.translate(elem[0]), file=cNbiTypes)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        nbwrite(f_nbipst,"    " + elem[0])
        print(nbigen_fortran2C.translate(elem[0]), file=cNbiTypes)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end type nbi_ctrl_update")
    print("""
};  /* nbiCtrlUpdate */

""", file=cNbiTypes)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"CONTAINS")
    nbwrite(f_nbipst," ")

    cnbiMeth = open("cnbi_methods.f90", "w")
#
# dmc -- deleted  dollar Id colon construct in following print >> stmt:
#        leads to spurious version differences.
#
    print("""
! written by nbigen.py
! *** do not edit *** (use nbigen.py instead)

subroutine cnubeam_set_mission(cstr,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: cstr
    integer :: ierr
    ierr = 0
    call nubeam_set_mission(cstr,ierr)
end subroutine cnubeam_set_mission

subroutine cnubeam_set_workpath(cstr,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: cstr
    integer :: ierr
    ierr = 0
    call nubeam_set_workpath(cstr,ierr)
end subroutine cnubeam_set_workpath

subroutine cnubeam_ctrl_init(ssh,nbi_ctrl,ierr)
    use plasma_state_mod
    use nbi_pstypes
    implicit none
    integer :: ssh(12) ! opaque handle to plasma_state
    type (nbi_ctrl_init) :: nbi_ctrl
    integer, intent(out) :: ierr
    ! local
    type plasma_state_ptr
         type(plasma_state), pointer :: ptr
    end type
    type(plasma_state_ptr) :: ss_ptr
    ! unpack
    ss_ptr = transfer(ssh, ss_ptr)
    ! invoke
    call nubeam_ctrl_init(ss_ptr%ptr,nbi_ctrl,ierr)
end subroutine cnubeam_ctrl_init

subroutine cnubeam_ctrl_step(ss_inh,ss_outh,nbi_ctrl,ierr)
    use plasma_state_mod
    use nbi_pstypes
    implicit none
    integer :: ss_inh(12) ! opaque handle to plasma_state
    integer :: ss_outh(12) ! opaque handle to plasma_state
    type (nbi_ctrl_update) :: nbi_ctrl
    integer, intent(out) :: ierr
    ! local
    type plasma_state_ptr
         type(plasma_state), pointer :: ptr
    end type
    type(plasma_state_ptr) :: ss_in_ptr, ss_out_ptr
    ! unpack
    ss_in_ptr = transfer(ss_inh, ss_in_ptr)
    ss_out_ptr = transfer(ss_outh, ss_out_ptr)
    ! invoke
    call nubeam_ctrl_step(ss_in_ptr%ptr,ss_out_ptr%ptr,nbi_ctrl,ierr)
end subroutine cnubeam_ctrl_step

subroutine cnubeam_ctrl_step_child(ierr)
    use plasma_state_mod
    use nbi_pstypes
    implicit none
    integer, intent(out) :: ierr
    ! invoke
    call nubeam_ctrl_step_child(ierr)
end subroutine cnubeam_ctrl_step_child

subroutine cnubeam_ctrl_nostep(ss_inh,ierr)
    use plasma_state_mod
    use nbi_pstypes
    implicit none
    integer :: ss_inh(12) ! opaque handle to plasma_state
    integer, intent(out) :: ierr
    ! local
    type plasma_state_ptr
         type(plasma_state), pointer :: ptr
    end type
    type(plasma_state_ptr) :: ss_in_ptr
    ! unpack
    ss_in_ptr = transfer(ss_inh, ss_in_ptr)
    ! invoke
    call nubeam_ctrl_nostep(ss_in_ptr%ptr,ierr)
end subroutine cnubeam_ctrl_nostep
""", file=cnbiMeth)
    #-------------------------------------------------
    # write default setting routines

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  subroutine nbi_ps_init_dflt(blk)")
    nbwrite(f_nbipst,"    type (nbi_ps_init) :: blk")
    nbwrite(f_nbipst," ")

    for elem in nbi_ps_init:
        declar = elem[0].upper()
        item = elem[2]
        name = item[0]
        if declar[0:3] == "INT":
            nbwrite(f_nbipst,"    blk%" + name + " = idflt_nbips")
        elif declar[0:4] == "REAL":
            nbwrite(f_nbipst,"    blk%" + name + " = r8dflt_nbips")
        else:
            nbwrite(f_nbipst,"    blk%" + name + " = ' '")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end subroutine nbi_ps_init_dflt")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  subroutine nbi_ps_update_dflt(blk)")
    nbwrite(f_nbipst,"    type (nbi_ps_update) :: blk")
    nbwrite(f_nbipst," ")

    for elem in nbi_ps_update:
        declar = elem[0].upper()
        item = elem[2]
        name = item[0]
        if declar[0:3] == "INT":
            nbwrite(f_nbipst,"    blk%" + name + " = idflt_nbips")
        elif declar[0:4] == "REAL":
            nbwrite(f_nbipst,"    blk%" + name + " = r8dflt_nbips")
        else:
           nbwrite(f_nbipst,"    blk%" + name + " = ' '")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end subroutine nbi_ps_update_dflt")

    print("""
subroutine cnbi_ctrl_init_dflt(blk)
    use nbi_pstypes
    implicit none
    type (nbi_ctrl_init) :: blk
    call nbi_ctrl_init_dflt(blk)
end subroutine cnbi_ctrl_init_dflt
    """, file=cnbiMeth)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  subroutine nbi_ctrl_init_dflt(blk)")
    nbwrite(f_nbipst,"    type (nbi_ctrl_init) :: blk")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_init_r8:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = r8dflt_nbips")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = idflt_nbips")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end subroutine nbi_ctrl_init_dflt")

    print("""
subroutine cnbi_ctrl_update_dflt(blk)
    use nbi_pstypes
    implicit none
    type (nbi_ctrl_update) :: blk
    call nbi_ctrl_update_dflt(blk)
end subroutine cnbi_ctrl_update_dflt
    """, file=cnbiMeth)
    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  subroutine nbi_ctrl_update_dflt(blk)")
    nbwrite(f_nbipst,"    type (nbi_ctrl_update) :: blk")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_update_r8:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = r8dflt_nbips")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = idflt_nbips")

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  end subroutine nbi_ctrl_update_dflt")

    # i/o routines
    print("""
subroutine cnbi_ctrl_init_cdfread(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! input file
    type (nbi_ctrl_init) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_init_cdfread(ofile,blk,ierr)
end subroutine cnbi_ctrl_init_cdfread
    """, file=cnbiMeth)

    f_nbipst.write("""

  subroutine nbi_ctrl_init_cdfread(ofile,blk,ierr)
    ! read nbi_ctrl_init block in ezcdf file

    character*(*) :: ofile            ! input file
    type (nbi_ctrl_init) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: icdf
    !---------------------------

    call ezcdf_open(icdf,ofile,'r',ierr)
    if(ierr.ne.0) then
       call nbi_warning( &
            ' ?nbi_ctrl_init_cdfread: ezcdf open failure, file: '// &
            trim(ofile))
       return
    endif

""")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_read(icdf,'" + name +
                "',saved_" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_read(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_read(icdf,'" + name +
                "',blk%" + name + ")")

    print("""
subroutine cnbi_ctrl_update_cdfread(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! input file
    type (nbi_ctrl_update) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_update_cdfread(ofile,blk,ierr)
end subroutine cnbi_ctrl_update_cdfread
    """, file=cnbiMeth)

    f_nbipst.write("""

    call ezcdf_close(icdf)

  end subroutine nbi_ctrl_init_cdfread

  subroutine nbi_ctrl_update_cdfread(ofile,blk,ierr)
    ! read nbi_ctrl_update block in ezcdf file

    character*(*) :: ofile            ! input file
    type (nbi_ctrl_update) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: icdf
    !---------------------------

    call ezcdf_open(icdf,ofile,'r',ierr)
    if(ierr.ne.0) then
       call nbi_warning( &
            ' ?nbi_ctrl_update_cdfread: ezcdf open failure, file: '// &
            trim(ofile))
       return
    endif

""")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_read(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_read(icdf,'" + name +
                "',blk%" + name + ")")

    f_nbipst.write("""

    call ezcdf_close(icdf)

  end subroutine nbi_ctrl_update_cdfread
""")

    print("""
subroutine cnbi_ctrl_init_read(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! input file
    type (nbi_ctrl_init) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_init_read(ofile,blk,ierr)
end subroutine cnbi_ctrl_init_read
    """, file=cnbiMeth)

    f_nbipst.write("""

  subroutine nbi_ctrl_init_read(ifile,blk,ierr)

    character*(*) :: ifile            ! input file
    type (nbi_ctrl_init) :: blk    ! read from file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    character*40 :: tmpfilnam
    integer :: ilun_dbg = 0
    integer :: ilun_tmp,ilnb,istat
    !---------------------------
    ! namelist:
""")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_init_char:
        item = elem[2]
        nbwrite(f_nbipst,"    " + item[1] + " :: " + item[0])

        dflt = item[7]
        nbwrite(f_help1," ")
        nbwrite(f_help1,"  " + item[1] + " :: " + item[0])
        nbwrite(f_help1,"    default value: " + dflt)
        for cmt in item[8:]:
            nbwrite(f_help1,"      !" + cmt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        nbwrite(f_nbipst,"    " + elem[0])

        item = elem[2]
        dflt = item[7]
        nbwrite(f_help1," ")
        nbwrite(f_help1,"  " + elem[0])
        nbwrite(f_help1,"    default value: " + dflt)
        for cmt in item[8:]:
            nbwrite(f_help1,"      !" + cmt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        nbwrite(f_nbipst,"    " + elem[0])

        item = elem[2]
        dflt = item[7]
        nbwrite(f_help1," ")
        nbwrite(f_help1,"  " + elem[0])
        nbwrite(f_help1,"    default value: " + dflt)
        for cmt in item[8:]:
            nbwrite(f_help1,"      !" + cmt)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"    namelist/NBI_INIT/ &")

    ict = 0
    s = "        "
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        s = s + name + ", "
        ict = ict + 1
        if ict == 4:
            nbwrite(f_nbipst,s + " &")
            s = "        "
            ict = 0

    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        s = s + name + ", "
        ict = ict + 1
        if ict == 4:
            nbwrite(f_nbipst,s + " &")
            s = "        "
            ict = 0

    ilenii = len(nbi_ctrl_init_ii)
    ictii = 0
    suffix = " &"

    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        ictii = ictii + 1
        if ictii < ilenii:
            s = s + name + ", "
        else:
            # last one...
            s = s + name
            ict = 3
            suffix = " "
        ict = ict + 1
        if ict == 4:
            nbwrite(f_nbipst,s + suffix)
            s = "        "
            ict = 0

    f_nbipst.write("""
    !---------------------------
    ! error check

    if(init_called) then
       write(ilun_dbg,*) "?nbi_ctrl_init_read: NUBEAM initialization already performed; cannot be repeated."
       ierr=1
       return
    else
       ierr=0
    endif

    ! set default values:

""")

    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    " + name + " = r8dflt_nbips")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    " + name + " = idflt_nbips")

    f_nbipst.write("""

    call find_io_unit(ilun_tmp)
    open(UNIT=ilun_tmp,file=ifile,status='old',iostat=istat)
    if(istat.eq.0) then
       read(UNIT=ilun_tmp,NML=NBI_INIT,iostat=istat)
       close(UNIT=ilun_tmp)
    endif
    if(istat.ne.0) then
       write(ilun_dbg,*) "?nbi_ctrl_init_read: error reading: "//trim(ifile)
       ierr=1
       return
    endif

""")

    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call nubeam_set_" + name + "(" + name + ",ierr)")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = " + name)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = " + name)

    print("""
subroutine cnbi_ctrl_update_read(ifile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ifile            ! input file
    type (nbi_ctrl_update) :: blk    ! loaded from file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_update_read(ifile,blk,ierr)
end subroutine cnbi_ctrl_update_read
    """, file=cnbiMeth)

    f_nbipst.write("""

  end subroutine nbi_ctrl_init_read

  subroutine nbi_ctrl_update_read(ifile,blk,ierr)
    character*(*) :: ifile            ! input file
    type (nbi_ctrl_update) :: blk  ! read from file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    character*40 :: tmpfilnam
    integer :: ilun_dbg = 0
    integer :: ilun_tmp,ilnb,istat
    !---------------------------
    ! namelist:
""")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_update_r8:
        nbwrite(f_nbipst,"    " + elem[0])

        item = elem[2]
        nbwrite(f_help2," ")
        nbwrite(f_help2,"  " + elem[0])
        nbwrite(f_help2,"    default: value not changed")
        for cmt in item[8:]:
            nbwrite(f_help2,"      !" + cmt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        nbwrite(f_nbipst,"    " + elem[0])

        item = elem[2]
        nbwrite(f_help2," ")
        nbwrite(f_help2,"  " + elem[0])
        nbwrite(f_help2,"    default: value not changed")
        for cmt in item[8:]:
            nbwrite(f_help2,"      !" + cmt)

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"    namelist/NBI_UPDATE/ &")

    ict = 0
    s = "        "
    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        s = s + name + ", "
        ict = ict + 1
        if ict == 4:
            nbwrite(f_nbipst,s + " &")
            s = "        "
            ict = 0

    ilenii = len(nbi_ctrl_update_ii)
    ictii = 0
    suffix = " &"

    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        ictii = ictii + 1
        if ictii < ilenii:
            s = s + name + ", "
        else:
            # last one...
            s = s + name
            ict = 3
            suffix = " "
        ict = ict + 1
        if ict == 4:
            nbwrite(f_nbipst,s + suffix)
            s = "        "
            ict = 0

    f_nbipst.write("""

    !---------------------------
    ierr = 0

    !---------------------------
    ! set default values:

""")

    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    " + name + " = r8dflt_nbips")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    " + name + " = idflt_nbips")

    f_nbipst.write("""

    call find_io_unit(ilun_tmp)
    open(UNIT=ilun_tmp,file=ifile,status='old',iostat=istat)
    if(istat.eq.0) then
       read(UNIT=ilun_tmp,NML=NBI_UPDATE,iostat=istat)
       close(UNIT=ilun_tmp)
    endif
    if(istat.ne.0) then
       write(ilun_dbg,*) "?nbi_ctrl_update_read: error reading: "//trim(ifile)
       ierr=1
       return
    endif

""")

    for elem in nbi_ctrl_update_r8:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = " + name)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        declar = elem[0]
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    blk%" + name + " = " + name)

    print("""
subroutine cnbi_ctrl_init_cdfwrite(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! output file
    type (nbi_ctrl_init) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_init_cdfwrite(ofile,blk,ierr)
end subroutine cnbi_ctrl_init_cdfwrite
    """, file=cnbiMeth)

    f_nbipst.write("""

  end subroutine nbi_ctrl_update_read

  subroutine nbi_ctrl_init_cdfwrite(ofile,blk,ierr)
    ! write nbi_ctrl_init block in ezcdf file

    character*(*) :: ofile            ! output file
    type (nbi_ctrl_init) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: icdf
    !---------------------------

    call ezcdf_open(icdf,ofile,'w',ierr)
    if(ierr.ne.0) then
       call nbi_warning( &
            ' ?nbi_ctrl_init_cdfwrite: ezcdf open failure, file: '// &
            trim(ofile))
       return
    endif

""")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_define(icdf,'" + name +
                "',saved_" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_define(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_define(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_write(icdf,'" + name +
                "',saved_" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_write(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_write(icdf,'" + name +
                "',blk%" + name + ")")

    print("""
subroutine cnbi_ctrl_update_cdfwrite(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! output file
    type (nbi_ctrl_update) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_update_cdfwrite(ofile,blk,ierr)
end subroutine cnbi_ctrl_update_cdfwrite
    """, file=cnbiMeth)

    f_nbipst.write("""

    call ezcdf_close(icdf)

  end subroutine nbi_ctrl_init_cdfwrite

  subroutine nbi_ctrl_update_cdfwrite(ofile,blk,ierr)
    ! write nbi_ctrl_update block in ezcdf file

    character*(*) :: ofile            ! output file
    type (nbi_ctrl_update) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: icdf
    !---------------------------

    call ezcdf_open(icdf,ofile,'w',ierr)
    if(ierr.ne.0) then
       call nbi_warning( &
            ' ?nbi_ctrl_update_cdfwrite: ezcdf open failure, file: '// &
            trim(ofile))
       return
    endif

""")
    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_define(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_define(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_write(icdf,'" + name +
                "',blk%" + name + ")")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call cdf_write(icdf,'" + name +
                "',blk%" + name + ")")

    print("""
subroutine cnbi_ctrl_init_write(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! output file
    type (nbi_ctrl_init) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_init_write(ofile,blk,ierr)
end subroutine cnbi_ctrl_init_write
    """, file=cnbiMeth)

    f_nbipst.write("""

    call ezcdf_close(icdf)

  end subroutine nbi_ctrl_update_cdfwrite

  subroutine nbi_ctrl_init_write(ofile,blk,ierr)

    ! write NON-DEFAULT values in the nbi_ctrl_init block
    ! to a commented namelist file

    character*(*) :: ofile            ! output file
    type (nbi_ctrl_init) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: ilun_dbg = 0
    integer :: ilun_tmp,istat,idiff
    !---------------------------
    ! local copies of elements for default values:
""")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_init_char:
        item = elem[2]
        nbwrite(f_nbipst,"    " + item[1] + " :: " + item[0])

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        nbwrite(f_nbipst,"    " + elem[0])

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        nbwrite(f_nbipst,"    " + elem[0])

    f_nbipst.write("""
    !---------------------------
    ierr = 0

    call find_io_unit(ilun_tmp)
    open(unit=ilun_tmp,file=trim(ofile),status='unknown')

    write(ilun_tmp,*) ' !! nbi_ctrl_init_write -- this file contains'
    write(ilun_tmp,*) ' !!   non-default values of initialization inputs'
    write(ilun_tmp,*) ' !!   to NUBEAM, in namelist format.'
    write(ilun_tmp,*) ' !!      LOGICAL variables mapped to INTEGER: 1=TRUE; 0=FALSE'
    write(ilun_tmp,*) ' '
    write(ilun_tmp,*) '&NBI_INIT'
    write(ilun_tmp,*) ' '

    ! set default values...

""")

    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        if item[1].upper() == "LOGICAL":
            nbwrite(f_nbipst,"    " + name + " = inbi_logical(" + dflt + ")")
        else:
            nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        nbwrite(f_nbipst,"    call dwrite(ilun_tmp,'" + name +
                "'," + dflt + ",saved_" + name + ",idiff)")
        nbw_cmts(f_nbipst,item[8:])

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call dwrite(ilun_tmp,'" + name +
                "'," + name + ",blk%" + name + ",idiff)")
        nbw_cmts(f_nbipst,item[8:])

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_init_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call dwrite(ilun_tmp,'" + name +
                "'," + name + ",blk%" + name + ",idiff)")
        nbw_cmts(f_nbipst,item[8:])

    print("""
subroutine cnbi_ctrl_update_write(ofile,blk,ierr)
    use nbi_pstypes
    implicit none
    character*(*) :: ofile            ! output file
    type (nbi_ctrl_update) :: blk    ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK
    ierr = 0
    call nbi_ctrl_update_write(ofile,blk,ierr)
end subroutine cnbi_ctrl_update_write
    """, file=cnbiMeth)

    f_nbipst.write("""
    write(ilun_tmp,*) '/'
    close(unit=ilun_tmp)

  end subroutine nbi_ctrl_init_write

  subroutine nbi_ctrl_update_write(ofile,blk,ierr)

    ! write NON-DEFAULT values in the nbi_ctrl_update block
    ! to a commented namelist file

    character*(*) :: ofile            ! output file
    type (nbi_ctrl_update) :: blk  ! written to file
    integer, intent(out) :: ierr      ! status, 0=OK

    !---------------------------
    ! local:
    integer :: ilun_dbg = 0
    integer :: ilun_tmp,istat,idiff
    !---------------------------
    ! local copies of elements for default values:
""")
    nbwrite(f_nbipst," ")

    for elem in nbi_ctrl_update_r8:
        nbwrite(f_nbipst,"    " + elem[0])

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        nbwrite(f_nbipst,"    " + elem[0])

    f_nbipst.write("""
    !---------------------------
    ierr = 0

    call find_io_unit(ilun_tmp)
    open(unit=ilun_tmp,file=trim(ofile),status='unknown')

    write(ilun_tmp,*) ' !! nbi_ctrl_update_write -- this file contains'
    write(ilun_tmp,*) ' !!   non-default values of time step update inputs'
    write(ilun_tmp,*) ' !!   to NUBEAM, in namelist format.'
    write(ilun_tmp,*) ' !!      LOGICAL variables mapped to INTEGER: 1=TRUE; 0=FALSE'
    write(ilun_tmp,*) ' '
    write(ilun_tmp,*) '&NBI_UPDATE'
    write(ilun_tmp,*) ' '

    ! set default values...

""")

    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        dflt = item[7]
        if item[1].upper() == "LOGICAL":
            nbwrite(f_nbipst,"    " + name + " = inbi_logical(" + dflt + ")")
        else:
            nbwrite(f_nbipst,"    " + name + " = " + dflt)

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_r8:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call dwrite(ilun_tmp,'" + name +
                "'," + name + ",blk%" + name + ",idiff)")

    nbwrite(f_nbipst," ")
    for elem in nbi_ctrl_update_ii:
        item = elem[2]
        name = item[0]
        nbwrite(f_nbipst,"    call dwrite(ilun_tmp,'" + name +
                "'," + name + ",blk%" + name + ",idiff)")

    f_nbipst.write("""
    write(ilun_tmp,*) '/'
    close(unit=ilun_tmp)

  end subroutine nbi_ctrl_update_write

""")

    # write the subroutines to actually transfer the data

    pstype_twrite(f_nbipst,"init",nbi_blocks,
                  nbi_ctrl_init_ii + nbi_ctrl_init_r8,
                  nbi_ps_init,
                  nbi_ctrl_init_char)

    pstype_twrite(f_nbipst,"update",nbi_blocks,
                  nbi_ctrl_update_ii +  nbi_ctrl_update_r8,
                  nbi_ps_update,
                  [])

    nbwrite(f_nbipst," ")
    nbwrite(f_nbipst,"  ! PUBLIC routines to set CHARACTER control variables")
    for elem in nbi_ctrl_init_char:
        item = elem[2]
        name = item[0]

        nbwrite(f_nbipst," ")
        nbwrite(f_nbipst,"  subroutine nubeam_set_" + name + "(cstr,ierr)")
        nbwrite(f_nbipst,"    character*(*) :: cstr")
        nbwrite(f_nbipst,"    integer :: ierr")
        nbwrite(f_nbipst," ")
        nbwrite(f_nbipst,"    if(init_called) then")
        nbwrite(f_nbipst,"      ierr = 1")
        nbwrite(f_nbipst,"      return")
        nbwrite(f_nbipst,"    else")
        nbwrite(f_nbipst,"      ierr = 0")
        nbwrite(f_nbipst,"    endif")
        nbwrite(f_nbipst," ")
        nbwrite(f_nbipst,"    saved_" + name + " = cstr")
        nbwrite(f_nbipst," ")
        nbwrite(f_nbipst,"  end subroutine nubeam_set_" + name)

    return 0

#--------------------------------------------
def nbw_cmts(f,cmts):

    nbwrite(f,"    if(idiff.gt.0) then")
    for cmt in cmts:
        css = cmt.split("'")
        s = css[0]
        for csect in css[1:]:
            s = s + '"' + csect

        fstr = "       write(ilun_tmp,*) '     !'// &"
        nbwrite(f,fstr)
        fstr = "            '" + s + "'"
        nbwrite(f,fstr)

    nbwrite(f,"       write(ilun_tmp,*) ' '")
    nbwrite(f,"    endif")
    return

#--------------------------------------------
def find_var_block(uinvar,nbi_blocks,uexpr,ukey):

    # find block that contains input variable (uinvar)
    # raise error if search fails

    block = "?error"

    for triple in nbi_blocks:
        curblock = triple[0][0]
        nbi_items = triple[1]
        for item in nbi_items:
            varname = item[0].lower()
            if varname == uinvar:
                block = curblock

    if block == "?error":
        print("nbigen_sub: failed to find input block containing variable: ",uinvar)
        print("  error while attempting parse of user settable dimension expression.")
        print("  for dimension " + ukey.upper() + ": expression is:" + uexpr)
        raise expression_error

    return block

#--------------------------------------------
def pstype_twrite(f,stype,nbi_blocks,list1,list2,listchar):

    # write subroutine to transfer input data items

    nbwrite(f," ")
    nbwrite(f,"  subroutine nbi_ctrl_" + stype + "_apply(blk1,blk2,ierr)")
    nbwrite(f,"    type (nbi_ctrl_" + stype + ") :: blk1")
    nbwrite(f,"    type (nbi_ps_" + stype + ") :: blk2")
    nbwrite(f,"    integer, intent(out) :: ierr")
    nbwrite(f," ")
    nbwrite(f,"    ierr = 0")
    nbwrite(f," ")

    # list of "extensible" blocks (set with "add" routine):

    addlist = []
    for triple in nbi_blocks:
        curblock = triple[0]
        blockname = curblock[0]
        nbi_items = triple[1]
        if nbi_items[0][3] == "extensible":
            addlist.append(blockname)

    # list of nbi_types blocks affected

    blist = []

    for elem in list1 + list2 + listchar:
        tblk = elem[1]
        if tblk not in blist:
            blist.append(tblk)

    blist.sort()

    # retrieve default or current values...

    if stype == "init":
        # deal with array dimensions
        nbwrite(f,"    call nbi_init_dims(zdims)")
        nbwrite(f," ")

    for tblk in blist:
        if stype == "init":
            s = "call nbi_init_" + tblk + "(z" + tblk + ")"
        else:
            s = "call nbi_get_" + tblk + "(z" + tblk + ")"
        nbwrite(f,"    " + s)

    # set new values in the blocks

    tblk=" "
    for elem in list1:
        tblkp = tblk
        tblk = elem[1]
        item = elem[2]
        name = item[0]

        if tblk != tblkp:
            nbwrite(f," ")

        nbwrite(f,"    call trans(blk1%" + name + ",z" + tblk + "%" + name + ")")

    tblk=" "
    for elem in list2:
        tblkp = tblk
        tblk = elem[1]
        item = elem[2]
        name = item[0]

        if tblk != tblkp:
            nbwrite(f," ")

        nbwrite(f,"    call trans(blk2%" + name + ",z" + tblk + "%" + name + ")")
    tblk=" "

    for elem in listchar:
        tblkp = tblk
        tblk = elem[1]
        item = elem[2]
        name = item[0]

        if tblk != tblkp:
            nbwrite(f," ")

        nbwrite(f,"    z" + tblk + "%" + name + " = saved_" + name)


    if stype == "init":
        # deal with array dimensions

        nbwrite(f," ")
        nbwrite(f,"    call nbi_init_dims(zdims)")

        udim_list = list(nbi_udim_dict.keys())
        udim_list.sort()

        nbwrite(f," ")
        for ukey in udim_list:
            s = "    zdims%" + ukey + " = "
            uinfo = nbi_udim_dict[ukey]
            varnam = uinfo[1]
            ubefore = uinfo[3]
            uafter = uinfo[4]
            if varnam == "verbatim:":
                s = s + ubefore + uafter
            else:
                blknam = uinfo[2]
                s = s + ubefore + "z" + blknam + "%" + varnam + uafter
            nbwrite(f,s)

        nbwrite(f," ")
        nbwrite(f,"    call nbi_set_dims(zdims,ierr)")
        nbwrite(f,"    if(ierr.ne.0) return")

        nbwrite(f," ")
        nbwrite(f,"    call nbi_alloc_init")

    # apply new values

    nbwrite(f," ")
    for tblk in blist:
        if stype == "init":
            if tblk in addlist:
                s = "call nbi_add_" + tblk + "(z" + tblk + ",ierr)"
            else:
                s = "call nbi_set_" + tblk + "(z" + tblk + ",ierr)"
        else:
            s = "call nbi_update_" + tblk + "(z" + tblk + ")"
        nbwrite(f,"    " + s)
        if stype == "init":
            nbwrite(f,"    if(ierr.ne.0) return")

    # end of subroutine
    nbwrite(f," ")

    if stype == "init":
        nbwrite(f,"    init_called = .TRUE.")
        nbwrite(f," ")

    nbwrite(f,"  end subroutine nbi_ctrl_" + stype + "_apply")

#--------------------------------------------------------------------
# process nbi_com internal variables and arrays
#

def nbigen_internal(text,section):

    # this section contains a list of variables and arrays, not split
    # into sublocks.  Only the "S" mode (state-file) is supported; comments
    # must be associated with individual variables.

    global nbi_initdims    # defined before nbi code control input is given
    global nbi_finaldims   # defined after nbi code control input is given
    global nbi_alldims     # union of the above

    global nbi_allnames    # list of all names...
    global nbi_pllinfo     # mpi_reduce pll buffer code generator info

    global ialloc_start    # detect 1st allocatable array in alloc routine
    global ialloc2_start   # detect 1st allocatable array in alloc2 routine
    global ialloctr_start   # detect 1st allocatable array in alloc2 routine
    global ialloctrz_start   # detect 1st allocatable array in alloc_track_zone routine
    global ialloctre_start   # detect 1st allocatable array in alloc_track_zone routine
    global iallocm_start   # detect 1st allocatable array in alloc2 routine
    global dval_nltest_output

    nbi_items = []  # individual internal items
    item = []       # single item description

    for line in text:
        if line[0] == "!":
            if item == []:
                print("nbigen_internal: comment not associated with item.")
                nbigen_syntax(section,line)
            else:
                item.append(line)
        else:
            if item != []: nbi_items.append(item)
            item = []

            #---------------------------
            # parse an item
            # <decl>  <name>[(dims)]=<default-value>

            [pllinfo,decl,name,dims,rhs] = nbparse_item(section,line)
            for pitem in pllinfo:
                nbi_pllinfo.append([name,dims,pitem])

            if rhs != "":
                print("nbigen_sub: internal item: value assignment not expected.")
                nbigen_syntax(section,line)

            item.append(name)        # item[0]: the name

            # parse decl: R|I|L|D|C*n[A][S] ...

            [dtype,atype,zmode] = nbparse_decl(section,line,decl,dims)

            if zmode == " ":
                mode = "standard"
            elif zmode == "S":
                mode = "stateful"
            elif zmode == "SN":
                mode = "ptclstate"
            else:
                print("nbigen_sub: invalid character in declaration: ",zmode)
                nbigen_syntax(section,line)

            item.append(dtype)  # item[1]: data type (e.g. REAL)
            item.append(atype)  # item[2]: "scalar" or "array"
            item.append(mode)   # item[3]: "standard" or "stateful", or"ptclstate"
            item.append(dims)   # item[4]: (array dimensions)

            has_minb = "FALSE"

            defer_alloc = "NA"
            if atype == "array":
                if dims[0] != "(": nbigen_syntax(section,line)
                if dims[-1:] != ")": nbigen_syntax(section,line)
                inside = dims[1:len(dims)-1]
                parts = inside.split(",")

                if dims[0:2] != "(:":
                    defer_alloc = "FALSE"
                    for part in parts:
                        dimname = part.strip()
                        nbi_check_dim(dimname,nbi_alldims,section,line)
                        if dimname in nbi_finaldims:
                            defer_alloc = "TRUE"

                        dimnamu = dimname.upper()
                        if dimnamu == "MINB":
                            has_minb = "TRUE"

            if has_minb == "TRUE" and mode != "stateful" and mode != "ptclstate":
                print(" ? nbigen_sub: particle arrays (with MINB dimension)")
                print("   should have the statefile save (S) attribute or")
                print("   should have the ptclstate save (s) attribute or")
                nbigen_syntax(section,line)

            item.append(defer_alloc)  # item[5]: TRUE for deferred array alloc.
            item.append(has_minb)    #  item[6]: TRUE if minb is a dimension
                                     #           (check for particle variable)

    # end of loop -- tack last item onto list.

    if item != []: nbi_items.append(item)

    nbwrite(f_nbicom,"  !==============================================")
    nbwrite(f_nbicom,"  ! INTERNAL items...")
    nbwrite(f_nbicom," ")

    nbwrite(f_alloc,"  !==============================================")
    nbwrite(f_alloc,"  ! internal arrays")
    nbwrite(f_alloc," ")

    nbwrite(f_alloc2,"subroutine nbi_alloc2_init")
    nbwrite(f_alloc2," ")
    nbwrite(f_alloc2,"  use nbi_com")
    nbwrite(f_alloc2,"  implicit NONE")
    nbwrite(f_alloc2," ")
    nbwrite(f_alloc2,"  !==============================================")
    nbwrite(f_alloc2,"  ! internal arrays")
    nbwrite(f_alloc2," ")

    nbwrite(f_alloctr,"subroutine nbi_alloc_track")
    nbwrite(f_alloctr," ")
    nbwrite(f_alloctr,"  use nbi_com")
    nbwrite(f_alloctr,"  use logmod")
    nbwrite(f_alloctr,"  implicit NONE")
    nbwrite(f_alloctr," ")
    nbwrite(f_alloctr,"  logical :: ia")
    nbwrite(f_alloctr," ")
    nbwrite(f_alloctr,"  !==============================================")
    nbwrite(f_alloctr,"  ! internal arrays")
    nbwrite(f_alloctr," ")

    nbwrite(f_alloctrz,"subroutine nbi_alloc_track_zone(jsize)")
    nbwrite(f_alloctrz," ")
    nbwrite(f_alloctrz,"  use nbi_com")
    nbwrite(f_alloctrz,"  use logmod")
    nbwrite(f_alloctrz,"  implicit NONE")
    nbwrite(f_alloctrz," ")
    nbwrite(f_alloctrz,"  integer, intent(in) :: jsize")
    nbwrite(f_alloctrz," ")
    nbwrite(f_alloctrz,"  logical :: ia")
    nbwrite(f_alloctrz," ")
    nbwrite(f_alloctrz,"  !==============================================")
    nbwrite(f_alloctrz,"  ! internal arrays")
    nbwrite(f_alloctrz," ")


    nbwrite(f_dalloctr,"subroutine nbi_dalloc_track")
    nbwrite(f_dalloctr," ")
    nbwrite(f_dalloctr,"  use nbi_com")
    nbwrite(f_dalloctr,"  implicit NONE")
    nbwrite(f_dalloctr," ")
    nbwrite(f_dalloctr,"  !==============================================")
    nbwrite(f_dalloctr,"  ! internal arrays")
    nbwrite(f_dalloctr," ")

    nbwrite(f_dalloctrz,"subroutine nbi_dalloc_track_zone")
    nbwrite(f_dalloctrz," ")
    nbwrite(f_dalloctrz,"  use nbi_com")
    nbwrite(f_dalloctrz,"  implicit NONE")
    nbwrite(f_dalloctrz," ")
    nbwrite(f_dalloctrz,"  !==============================================")
    nbwrite(f_dalloctrz,"  ! internal arrays")
    nbwrite(f_dalloctrz," ")

    nbwrite(f_nbilst,"module nbi_lost_ptcl ")
    nbwrite(f_nbilst,"  use nbi_com")
    nbwrite(f_nbilst,"  implicit NONE")
    nbwrite(f_nbilst,"  integer, dimension(:), allocatable :: mlost_all  !arrays containing the number of elements")
    nbwrite(f_nbilst,"                                                   !that are received from each process")
    nbwrite(f_nbilst,"  real(fp) :: gtime,yyion,yze   !time, Z, energy lost ptcl.")
    nbwrite(f_nbilst,"  real(fp) :: ynbsce, ynbien   !source and energy fraction index of lost ptcl.")
    nbwrite(f_nbilst," ")
    nbwrite(f_nbilst," ")

    nbwrite(f_cxnrm,"subroutine cxnrm ")
    nbwrite(f_cxnrm,"  use nbi_com")
    nbwrite(f_cxnrm,"  use nbi_mpi_com")
    nbwrite(f_cxnrm,"  implicit NONE")
    nbwrite(f_cxnrm,"  integer :: ib")
    nbwrite(f_cxnrm,"  real(fp) :: zcxnorm")
    nbwrite(f_cxnrm,"  ")
    nbwrite(f_cxnrm,"  zcxnorm = xncx0_orb(lsbeam)/real(ncx0_use,fp)")
    nbwrite(f_cxnrm," ")


    nbwrite(f_nbizone,"subroutine nbi_expand_track_zone")
    nbwrite(f_nbizone," ")
    nbwrite(f_nbizone,"  use nbi_com")
    nbwrite(f_nbizone,"  use dep_track_counter")
    nbwrite(f_nbizone,"  use logmod")
    nbwrite(f_nbizone,"  implicit NONE")
    nbwrite(f_nbizone," ")
    nbwrite(f_nbizone,"  real(fp), dimension(:), allocatable :: tmp")
    nbwrite(f_nbizone,"  integer, PARAMETER :: mtrk0_blksize = 20000")
    nbwrite(f_nbizone,"  integer, SAVE :: mtrk0_maxsize = mtrk0_blksize")
    nbwrite(f_nbizone,"  integer, SAVE :: mtrk0_prev = 0")
    nbwrite(f_nbizone,"  integer :: iblks")
    nbwrite(f_nbizone," ")

    nbwrite(f_alloclst,"subroutine nbi_alloc_lost")
    nbwrite(f_alloclst," ")
    nbwrite(f_alloclst,"  use nbi_com")
    nbwrite(f_alloclst,"  implicit NONE")
    nbwrite(f_alloclst," ")
    nbwrite(f_alloclst,"  !==============================================")
    nbwrite(f_alloclst,"  ! internal arrays")
    nbwrite(f_alloclst," ")
    nbwrite(f_alloclst,"  call nbi_dalloc_lost")
    nbwrite(f_alloclst,"  if(mlost_data.eq.0) return")

    nbwrite(f_dalloclst,"subroutine nbi_dalloc_lost")
    nbwrite(f_dalloclst," ")
    nbwrite(f_dalloclst,"  use nbi_com")
    nbwrite(f_dalloclst,"  implicit NONE")
    nbwrite(f_dalloclst," ")
    nbwrite(f_dalloclst,"  !==============================================")
    nbwrite(f_dalloclst,"  ! internal arrays")
    nbwrite(f_dalloclst," ")


    nbwrite(f_reallocm,"subroutine nbi_realloc_minb(minb_new)")
    nbwrite(f_reallocm," ")
    nbwrite(f_reallocm,"  use nbi_com")
    nbwrite(f_reallocm,"  implicit NONE")
    nbwrite(f_reallocm,"  integer, intent(in) :: minb_new")
    nbwrite(f_reallocm,"  integer :: j")
    nbwrite(f_reallocm,"  integer,dimension(:,:),allocatable :: tmp_minb_int")
    nbwrite(f_reallocm,"  real(fp), dimension(:,:),allocatable :: tmp_minb_r8")
    nbwrite(f_reallocm," ")
    nbwrite(f_reallocm," ")
    nbwrite(f_reallocm,"  !==============================================")
    nbwrite(f_reallocm,"  ! internal arrays")
    nbwrite(f_reallocm," ")

    nbwrite(f_allocm,"subroutine nbi_alloc_minb")
    nbwrite(f_allocm," ")
    nbwrite(f_allocm,"  use nbi_com")
    nbwrite(f_allocm,"  implicit NONE")
    nbwrite(f_allocm,"  integer :: j")
    nbwrite(f_allocm," ")
    nbwrite(f_allocm,"  !==============================================")
    nbwrite(f_allocm,"  ! internal arrays")
    nbwrite(f_allocm," ")

    nbwrite(f_dalloc,"  !==============================================")
    nbwrite(f_dalloc,"  ! internal arrays")
    nbwrite(f_dalloc," ")

#strat for
    klst = 0
    for pitem in nbi_pllinfo:
        pll_section = pitem[2][0]
        pll_name=pitem[0].lower().strip()
        if pll_section.lower() == "lst":
            klst = klst + 1
    ss = repr(klst)
    nbwrite(f_nbilst,"  integer, parameter ::  num_lst_arrays = "+ss+" !number of arrays to gather lost ptcl")
    nbwrite(f_nbilst," ")
    nbwrite(f_nbilst,"contains")
    for item in nbi_items:

        name = item[0]
        dtype = item[1]  # data type e.g. "INTEGER"
        atype = item[2]  # scalar or array
        mode = item[3]
        dims = item[4]
        ndims = len(dims.split(","))
        defer_alloc = "NA"  # (for scalars)
        if atype == "array":
            defer_alloc = item[5]  # TRUE or FALSE (for arrays) or NA
        cmts = item[7:]

        # initial values...

        [dval,type_abbrev] = nbtype_dval(item[1])

        # write nbi_com

        if atype == "scalar":
            s = "  " + dtype.lower() + " :: " + name + " = " + dval
            if item[0].lower() ==  "debug_mpi":
                dval=dval_nltest_output
                s = "#ifdef __MPI"
                nbwrite(f_nbicom,s)
                nbwrite(f_nbicom,"  " + dtype.lower() + " :: " + name + " = " + dval)
                s = "#else"
                nbwrite(f_nbicom,s)
                nbwrite(f_nbicom,"  " + dtype.lower() + " :: " + name + " = .FALSE.")
                s = "#endif"


        else:
                # the array itself

            s = "  " + dtype.lower() + ", dimension("
            ctr = 0
            while ctr < ndims:
                ctr = ctr + 1
                s = s + ":"
                if ctr < ndims:
                    s = s + ","
                else:
                    s = s + ")"
            s = s + ", allocatable :: " + name

        nbwrite(f_nbicom,s)

        for cmt in cmts:
            s = "        " + cmt
            nbwrite(f_nbicom,s)

        # write allocator

        has_minb=item[6]
        if has_minb == "FALSE":
            if atype == "array":
                iend="\n  endif"
                if name.lower() == "fbm_cx":
                    s = "  if(ncx0.gt.0) then\n  allocate(" + name + dims + ")\n  "
                elif name.lower() == "fbm_ptcl":
                    s = "  if(nlfbmflr) then\n  allocate(" + name + dims + ")\n  "
                elif name[0:5].lower() == "svn3v":
                    s = "  if(levmod_halo.eq.2) then\n  allocate(" + name + dims + ")\n  "
                else:
                    iend=""
                    if dims[1:-1].lower() == "mtrk0":
                        s = "  allocate(" + name + "(jsize)); "
                    else:
                        s = "  allocate(" + name + dims + "); "
                s = s + name + " = " + dval + iend
                if defer_alloc == "TRUE":
                    kl_write=0
                    for pitem in nbi_pllinfo:
                        pll_section = pitem[2][0]
                        pll_name=pitem[0].lower().strip()
                        if name.lower() == pll_name:
                            if pll_section.lower() == "dpt":
                                if dims[1:-1].lower() == "mtrk0":
                                    ialloctrz_start = wr_alloc_check_track_zone(f_alloctrz,
                                                                          "nbi_alloc_track_zone",name,ialloctrz_start)
                                    s ="  if(ia)" + s[1:]
                                    nbwrite(f_alloctrz,s)

                                    s = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                                    nbwrite(f_dalloctrz,s)

                                    ialloctre_start = wr_expand_track_zone(f_nbizone,
                                                                          "nbi_expand_track_zone",name,ialloctre_start)

                                    s = "  if(allocated(" + name + ")) then"
                                    nbwrite(f_nbizone,s)
                                    s = "     tmp = " + name + "(1:mtrk0_prev)"
                                    nbwrite(f_nbizone,s)
                                    s = "     deallocate(" + name + ")"
                                    nbwrite(f_nbizone,s)
                                    nbwrite(f_nbizone,"  else")
                                    nbwrite(f_nbizone,"     tmp = zero")
                                    nbwrite(f_nbizone,"  endif")
                                    s = "  allocate(" + name + "(mtrk0_maxsize)); " + name + "(mtrk0_prev+1:mtrk0_maxsize) = zero"
                                    nbwrite(f_nbizone,s)
                                    s = "  " + name + "(1:mtrk0_prev) = tmp"
                                    nbwrite(f_nbizone,s)
                                    nbwrite(f_nbizone,"  ")
                                    kl_write=1
                                else:
                                    ialloctr_start = wr_alloc_check_track(f_alloctr,
                                                                          "nbi_alloc_track",name,ialloctr_start)
                                    s = "  if(ia)" + s[1:]
                                    nbwrite(f_alloctr,s)

                                    s = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                                    nbwrite(f_dalloctr,s)
                                    kl_write=1
                            elif pll_section.lower() == "lst":
                                nbwrite(f_alloclst,s)
                                s = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                                nbwrite(f_dalloclst,s)
                                kl_write=1

                    if kl_write ==0:
                        ialloc2_start = wr_alloc_check(f_alloc2,
                                                       "nbi_alloc2",name,ialloc2_start)
                        nbwrite(f_alloc2,s)
                        s = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                        nbwrite(f_dalloc,s)


                elif defer_alloc == "FALSE":
                    ialloc_start = wr_alloc_check(f_alloc,
                                                  "nbi_alloc", name,ialloc_start)
                    str1 = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                    if dims[1:-1].lower() == "minbs":
                        nbwrite(f_allocsplt,s)
                        wr_spltexpnd(f_spltexpnd, name,dtype[0])
                        nbwrite(f_dallocsplt,str1)
                    else:
                        nbwrite(f_alloc,s)
                        nbwrite(f_dalloc,str1)



        # write allocator minb
        has_minb=item[6]
        if has_minb == "TRUE":
            if dtype == "INTEGER":
                tmp_name ="tmp_minb_int"
                initval ="0"
            elif dtype == "REAL(fp)":
                tmp_name="tmp_minb_r8"
                initval ="zero"

            if defer_alloc == "TRUE":
                iallocm_start = wr_alloc_check(f_allocm,
                                                  "nbi_alloc_minb",name,iallocm_start)
                s = "  allocate(" + name + dims + "); "
                s = s + name + " = " + initval
                nbwrite(f_allocm,s)
                if name == "nbndex":
                    s = "  do j=1,minb"
                    nbwrite(f_allocm,s)
                    s = "     "+name+"(j,1:mibs)=j"
                    nbwrite(f_allocm,s)
                    s ="  enddo"
                    nbwrite(f_allocm,s)

            elif defer_alloc == "FALSE":
                #---------------------- allocate scalar if any
                s = "   allocate(" + name + "(minb))"
                s = s + ";"+ name +"="+ initval
                nbwrite(f_allocm,s)

        # write reallocator minb

        has_minb=item[6]
        if has_minb == "TRUE":
            if dtype == "INTEGER":
                tmp_name ="tmp_minb_int"
                initval ="0"
            elif dtype == "REAL(fp)":
                tmp_name="tmp_minb_r8"
                initval ="zero"

            if defer_alloc == "TRUE":
                s = "   allocate(" + tmp_name + "(minb"+dims[5:len(dims)]+")"
                s = s + ";"+ tmp_name +"="+ initval
                nbwrite(f_reallocm,s)
                s = "   "+tmp_name +"="+name
                nbwrite(f_reallocm,s)
                s = "   deallocate(" + name +")"
                nbwrite(f_reallocm,s)
                dims_new = "(minb_new" + dims[5:len(dims)]
                s = "   allocate(" + name + dims_new + "); "
                s = s + name + "  = " + initval
                nbwrite(f_reallocm,s)
                if name == "nbndex":
                    s = "   do j=minb+1,minb_new"
                    nbwrite(f_reallocm,s)
                    s = "      "+name+"(j,1:mibs)=j"
                    nbwrite(f_reallocm,s)
                    s ="   enddo"
                    nbwrite(f_reallocm,s)
                s = "   "+name + "(1:minb,1:mibs)  = " + tmp_name+ "(1:minb,1:mibs)"
                nbwrite(f_reallocm,s)
                s = "   deallocate(" +tmp_name +")"
                nbwrite(f_reallocm,s)
                s = "  "
                nbwrite(f_reallocm,s)
            elif defer_alloc == "FALSE":
                #---------------------- allocate scalar if any
                s = "   allocate(" + tmp_name + "(minb))"
                s = s + ";"+ tmp_name +"="+ initval
                nbwrite(f_reallocm,s)
                s = tmp_name +"="+name
                nbwrite(f_reallocm,s)
                s = "   deallocate(" + name +")"
                nbwrite(f_reallocm,s)
                dims_new = "(minb_new)"
                s = "   allocate(" + name + dims_new + "); "
                s = s + name + "  = " + initval
                nbwrite(f_reallocm,s)
                s = "   "+ name + "  = " + tmp_name
                nbwrite(f_reallocm,s)
                s = "   deallocate(" +tmp_name +")"
                nbwrite(f_reallocm,s)
 #end for
    #------------------------------------
    #  state-file i/o (particle quantities)

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_define2_ptcl")

    nbwrite(f_statio,"  idm = (/ 0, 0, 0/)")
    for idim in nbi_alldims:
        if(idim == 'minb'):
            nbwrite(f_statio,
                    "  call cdfDefVar(icdf, '" + idim + "', idm, 'INT')")

    for item in nbi_items:
        if item[3] == "ptclstate":
            #and item[6] == "TRUE":
            dname = item[0]

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)
            
            nbwrite_defvar(dname,dabbrev,dims)

    nbstate_trlr0(f_statio, "nbi_state_define2_ptcl")

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_output2_ptcl")
    for idim in nbi_alldims:
        if(idim == 'minb'):
            nbwrite(f_statio,
                    "  call cdfPutVar(icdf, '" + idim + "', " + idim + ")")

    sublist = []
    for item in nbi_items:

        if item[3] == "ptclstate":
            #and item[6] == "TRUE":
            dname = item[0]
            dtype = item[1]

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

            zlist = nbwrite_putvar(dname,dtype,ndims,dims,dimstring)
            sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_output2_ptcl", sublist)

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_read2_ptcl")

    for idim in nbi_finaldims:
        if(idim == 'minb' ):
            nbwrite(f_statio,"  idm = (/ -1, -1, -1 /)")
            nbwrite(f_statio,
                    "  call cdfInqVar(icdf, '" + idim + "', idm, zvartype)")
            nbwrite(f_statio,"  if(idm(1).ne.-1) then")
            nbwrite(f_statio,
                    "     call cdfGetVar(icdf, '" + idim + "', " + idim + ")")
            nbwrite(f_statio,"  else")
            strw = "     write(nonlin,*) ' ** DIMENSION (fin) not in state file: "
            strw = strw + idim.upper() + "; cleared to ZERO'"
            nbwrite(f_statio,strw)
            nbwrite(f_statio,"     " + idim + " = 0")
            nbwrite(f_statio,"  endif")

            nbwrite(f_statio," ")
            nbwrite(f_statio,"  call nbi_alloc_minb")
            nbwrite(f_statio," ")

    sublist = []
    for item in nbi_items:

        if item[3] == "ptclstate" :
            #and item[6] == "TRUE":
            dname = item[0]
            dtype = item[1]
            [dval,type_abbrev] = nbtype_dval(dtype)

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

            zlist = nbwrite_getvar(dname,dtype,dval,ndims,dims,dimstring)
            sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_read2_ptcl", sublist)

    #------------------------------------
    #  state-file i/o (field quantities)

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_define2")

    for item in nbi_items:

        if item[3] == "stateful" and item[6] != "TRUE":
            dname = item[0]

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)
            nbwrite_defvar(dname,dabbrev,dims)

    nbstate_trlr0(f_statio, "nbi_state_define2")

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_output2")

    sublist = []
    for item in nbi_items:

        if item[3] == "stateful" and item[6] != "TRUE":
            dname = item[0]
            dtype = item[1]

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

            zlist = nbwrite_putvar(dname,dtype,ndims,dims,dimstring)
            sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_output2", sublist)

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_read2")

    sublist = []
    for item in nbi_items:

        if item[3] == "stateful" and item[6] != "TRUE":
            dname = item[0]
            dtype = item[1]
            [dval,type_abbrev] = nbtype_dval(dtype)

            [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)
            zlist = nbwrite_getvar(dname,dtype,dval,ndims,dims,dimstring)
            sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_read2", sublist)


    # Put more field data (read2) into broadcast buffer

    for item in nbi_items:

        if item[3] == "stateful" and item[6] != "TRUE":
            dname = item[0]
            dtype = item[1]
            if dtype[0]=='R':
                str1 = ""
                if dname[0:5] == "svn3v":
                    nbwrite(f_bcast_st,"  if(levmod_halo.eq.2) then")
                    str1 = "   "

                s = str1 + "  call putdat(" + dname + ",inumr)"
                nbwrite(f_bcast_st,s)
                if dname[0:5] == "svn3v":
                    nbwrite(f_bcast_st,"  endif")

                str1 = ""
                if dname[0:5] == "svn3v":
                    nbwrite(f_bcast_st_get,"  if(levmod_halo.eq.2) then")
                    str1 = "   "
                s = str1 + "  call getdat(" + dname + ",inumr)"
                nbwrite(f_bcast_st_get,s)
                if dname[0:5] == "svn3v":
                    nbwrite(f_bcast_st_get,"  endif")

            if dtype[0]=='I':
                s = "  call putdat(" + dname + ",inumi)"
                nbwrite(f_bcast_st,s)
                s = "  call getdat(" + dname + ",inumi)"
                nbwrite(f_bcast_st_get,s)
            if dtype[0]=='C':
                s = "  call putdat(" + dname + ",inumc)"
                nbwrite(f_bcast_st,s)
                s = "  call getdat(" + dname + ",inumc)"
                nbwrite(f_bcast_st_get,s)
            if dtype[0]=='L':
                s = "  call putdat(" + dname + ",inuml)"
                nbwrite(f_bcast_st,s)
                s = "  call getdat(" + dname + ",inuml)"
                nbwrite(f_bcast_st_get,s)
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st_get," ")

    #------------------------------------
    #  list of names...

    for item in nbi_items:
        dname = item[0]
        nbi_allnames.append(dname.upper())

#  lost ptcl.
    nbwrite(f_nbilst,"  subroutine store_lost_ptcl")
    nbwrite(f_nbilst,"    real(fp), dimension(:), allocatable :: tmp_lost")
    nbwrite(f_nbilst,"  ")
    nbwrite(f_nbilst,"    if(mlost_data.ge.minb) return   !do not gather lost orbit, too many data")
    nbwrite(f_nbilst,"  ")
    nbwrite(f_nbilst,"    if(mlost_data.gt.0) then")
    nbwrite(f_nbilst,"       if(allocated(tmp_lost)) deallocate(tmp_lost)")
    nbwrite(f_nbilst,"       allocate(tmp_lost(mlost_data))")
    for pitem in nbi_pllinfo:
        pll_section = pitem[2][0]
        pll_name=pitem[0].lower().strip()
        if pll_section.lower() == "lst":
            nbwrite(f_nbilst," ")
            nbwrite(f_nbilst,"       tmp_lost = "+ pll_name)
            nbwrite(f_nbilst,"       if(allocated(" + pll_name + ")) deallocate("+pll_name+") ")
            nbwrite(f_nbilst,"       allocate(" + pll_name + "(mlost_data+1))")
            nbwrite(f_nbilst,"       "+pll_name+"(1:mlost_data)=tmp_lost")
            if pll_name == "species_lost":
                nbwrite(f_nbilst,"       "+pll_name+"(mlost_data+1)= lsbeam")
            else:
                nbwrite(f_nbilst,"       "+pll_name+"(mlost_data+1)="+ pll_name[0:-5])
            nbwrite(f_nbilst," ")

    nbwrite(f_nbilst,"    else")
    nbwrite(f_nbilst," ")
    klst = 0
    for pitem in nbi_pllinfo:
        pll_section = pitem[2][0]
        pll_name=pitem[0].lower().strip()
        if pll_section.lower() == "lst":
            klst = klst + 1
            nbwrite(f_nbilst,"       if(allocated(" + pll_name + ")) deallocate("+pll_name+") ")
            nbwrite(f_nbilst,"       allocate(" + pll_name + "(mlost_data+1))")
            if pll_name == "species_lost":
                nbwrite(f_nbilst,"       "+pll_name+"(mlost_data+1)= lsbeam")
            else:
                nbwrite(f_nbilst,"       "+pll_name+"(mlost_data+1)="+ pll_name[0:-5])
            nbwrite(f_nbilst," ")
    nbwrite(f_nbilst,"    endif")
    nbwrite(f_nbilst,"    mlost_data=mlost_data+1")
    nbwrite(f_nbilst,"  end subroutine store_lost_ptcl")
    nbwrite(f_nbilst,"  ")
    nbwrite(f_nbilst,"  subroutine write_lost_ptcl")
    nbwrite(f_nbilst,"    integer ii")
    nbwrite(f_nbilst," ")
    nbwrite(f_nbilst,"    do ii=1,mlost_data")
    ss = repr(klst)
    str1 = "       write(lunnbx,'(" + ss +"(1x,1pe12.5))')& "
    nbwrite(f_nbilst,str1)
    klst1=0
    for pitem in nbi_pllinfo:
        pll_section = pitem[2][0]
        pll_name=pitem[0].lower().strip()
        if pll_section.lower() == "lst":
            klst1=klst1+1
            if klst1 == klst :
                s = "            &"+ pll_name+"(ii)"
            else:
                s = "            &"+ pll_name+"(ii),&"

            nbwrite(f_nbilst,s)
    nbwrite(f_nbilst,"    enddo")
    nbwrite(f_nbilst,"  end subroutine write_lost_ptcl")



    nbwrite(f_nbilst,"end module nbi_lost_ptcl")
#                nbwrite(f_nbilst," " + name)
#    for idim in nbi_finaldims:
#       if( idim == 'mlost_data'):

    return 0
#--------------------------------------------------------------------
# process nbi_com output variables and arrays
#

def nbigen_output(text,section):

    # this section contains a list of variables and arrays, split
    # into sublocks.  There are comments associated with the blocks
    # and comments associated with individual scalars and arrays.
    # some items need to be in the state file ("S" mode).  Items
    # containing "mj" in the dimension are "profiles", for which
    # there are output modes " ","~", and "|" meaning standard (a
    # particle, source, torque or power density profile), "~" for
    # a parameter such as rotation velocity or average energy, "|"
    # for cross-zone-boundary flux profiles.  "^" means a parameter
    # that is not smoothed and for which a piecewise linear fit is
    # used.

    global nbi_initdims    # defined before nbi code control input is given
    global nbi_finaldims   # defined after nbi code control input is given
    global nbi_alldims     # union of the above

    global nbi_allnames    # list of all names...
    global nbi_pllinfo     # mpi_reduce pll buffer code generator info

    global ialloc_start    # detect 1st allocatable array in alloc routine
    global ialloc2_start   # detect 1st allocatable array in alloc2 routine
    global ialloctr_start   # detect 1st allocatable array in alloc2 routine
    global ialloctrz_start   # detect 1st allocatable array in alloc_track_zone routine
    global ialloctre_start   # detect 1st allocatable array in alloc_track_zone routine
    global ialloclst_start   # detect 1st allocatable array in alloc2 routine
    global ireallocm_start   # detect 1st allocatable array in reallocm routine
    global iallocm_start      # detect 1st allocatable array in reallocm routine

    oblocks = []    # collection of all output blocks
    nbi_items = []  # list of individual items within blocks
    nbi_grps = []   # list of item groups within blocks
    item = []       # single item description
    grp = []        # single group description
    gnames = []     # list of group names
    curblock = []   # current block [blk_info,nbi_items]
    blk_info = []   # blockname, block level comments

    bname = ""

    for line in text:
        test = line.upper().strip()
        if test[0:6] == "BLOCK:":
            ### start new block
            if item != []: nbi_items.append(item)
            if grp != []: nbi_grps.append(grp)
            item = []
            grp = []
            if nbi_items != []:
                curblock.append(blk_info)
                curblock.append(nbi_items)
                curblock.append(nbi_grps)
                blk_info = []
                nbi_items = []
                nbi_grps = []
            if curblock != []:
                oblocks.append(curblock)
                curblock = []
            words = line.split()
            bname = words[1]
            blk_info.append(bname)

        elif line[0] == "!":
            if bname == "":
                print("nbigen_sub: 1st statement in Outputs section")
                print(" should be a 'Block:' statement.")
                nbigen_syntax(section,line)
            if item == []:
                blk_info.append(line)  # block comment
            else:
                item.append(line)      # item comment
        elif test[0:6] == "GROUP ":
            if grp != []: nbi_grps.append(grp)
            grp = []
            gwk = line.split('"')
            if len(gwk) != 3:
                print("nbigen_sub: group label missing or label syntax error:")
                nbigen_syntax(section,line)
            glabel = gwk[1].strip()
            gwk = gwk[0].split('/')
            if len(gwk) != 3:
                print("nbigen_sub: group contents specification not found:")
                nbigen_syntax(section,line)
            gmemb0 = gwk[1].split(',')
            if len(gmemb0) > 1:
                gmembs = []
                for gmemb in gmemb0:
                    gmembs.append(gmemb.strip())

                gwords = gwk[0].split()
                gname = gwords[1]
                gnames.append(gname)

                grp.append(gname)
                grp.append(gmembs)
                grp.append(glabel)
            else:
                print("nbigen_sub: warning, group ignored (too few members):")
                print("  " + line)
        else:
            if grp != []: nbi_grps.append(grp)
            grp = []
            if item != []: nbi_items.append(item)
            item = []

            #---------------------------
            # parse an item
            # <decl>  <name>[(dims)][*<scale-factor>] "output_label"

            qsplit = line.split('"')
            if len(qsplit) != 3:
                print("nbigen_sub: output item label missing.")
                nbigen_syntax(section,line)

            olabel = qsplit[1].strip() # output item label(e.g. for plot)
            dline = qsplit[0].strip()  # output item declaration

            scale_fac = ""
            ifind = dline.find("*")
            if ifind > 0:
                scale_fac = dline[ifind+1:].strip()
                zline = dline[:ifind].strip()
            else:
                zline = dline
            [pllinfo,decl,name,dims,rhs] = nbparse_item(section,zline)
            for pitem in pllinfo:
                nbi_pllinfo.append([name,dims,pitem])

            if rhs != "":
                print("nbigen_sub: output item: value assignment not expected.")
                nbigen_syntax(section,line)

            item.append(name)        # item[0]: the name
            grp.append(name)
            gnames.append(name)
            gmembs = []
            gmembs.append(name)
            grp.append(gmembs)

            # parse decl: R|I|L|D|C*n[A][S]["|"|"~"] ...

            [dtype,atype,zmode] = nbparse_decl(section,zline,decl,dims)

            # check array dimensions

            if atype == "array":
                nbi_check_odims(dims,nbi_initdims,nbi_initlims,section,zline)

            # check for "mj": output 1d profiles...

            if atype == "array":
                [ioname,iodims] = nbcheck_prof(dtype,name,dims)
                if ioname == "ERROR":
                    nbigen_syntax(section,line)
            else:
                ioname = ""
                iodims = ""

            # check profile type...

            iflag = 0
            if zmode[-1] == "~":
                if ioname == "":
                    print("nbigen_sub: profile type symbol '~' but no profile.")
                    nbigen_syntax(section,line)
                proftype = "parameter"
                iflag = 1
            elif zmode[-1] == "|":
                if ioname == "":
                    print("nbigen_sub: profile type symbol '|' but no profile.")
                    nbigen_syntax(section,line)
                proftype = "flow"
                iflag = 1
            elif zmode[-1] == "^":
                if ioname == "":
                    print("nbigen_sub: profile type symbol '^' but no profile.")
                    nbigen_syntax(section,line)
                proftype = "linparam"
                iflag = 1
            elif zmode[-1] == "@":
                if ioname == "":
                    print("nbigen_sub: profile type symbol '@' but no profile.")
                    nbigen_syntax(section,line)
                proftype = "curdens"
                iflag = 1
            else:
                if ioname != "":
                    proftype = "density"
                else:
                    proftype = "NONE"

            if iflag == 1:
                if len(zmode) > 1:
                    zmode = zmode[:-1]  # strip off proftype char
                else:
                    zmode = " "

            if zmode == " ":
                mode = "standard"
            elif zmode == "S":
                mode = "stateful"
            elif zmode == "SN":
                mode = "ptclstate"
            else:
                print("nbigen_sub: invalid character in declaration: ",zmode)
                nbigen_syntax(section,line)

            item.append(dtype)  # item[1]: data type (e.g. REAL)
            item.append(atype)  # item[2]: "scalar" or "array"
            item.append(mode)   # item[3]: "standard" or "stateful"
            item.append(dims)   # item[4]: (array dimensions)

            defer_alloc = "NA"
            if atype == "array":
                if dims[0] != "(": nbigen_syntax(section,line)
                if dims[-1:] != ")": nbigen_syntax(section,line)
                inside = dims[1:len(dims)-1]
                parts = inside.split(",")

                if dims[0:2] != "(:":
                    defer_alloc = "FALSE"
                    for part in parts:
                        dimname = part.strip()
                        nbi_check_dim(dimname,nbi_alldims,section,zline)
                        if dimname in nbi_finaldims:
                            defer_alloc = "TRUE"
                else:
                    print(' ?nbigen_sub: ":" dimension unavailable for output item.')
                    nbigen_syntax(section,line)

            item.append(defer_alloc)  # item[5]: TRUE for deferred array alloc.

            item.append(proftype)     # item[6]: profile type (see above)
            item.append(ioname)       # item[7]: xplasma id variable, if any
            item.append(iodims)       # item[8]: xplasma id var. dims, if any
            item.append(scale_fac)    # item[9]: scale factor if any
            item.append(olabel)       # item[10]: output label
            item.append([])           # item[11]: list of groups containing item
            # item[12...] -- comments appended...

            grp.append(olabel)

    # end of loop -- tack last item onto list.
    # pick up trailing item...




    if grp != []: nbi_grps.append(grp)
    grp = []
    if item != []: nbi_items.append(item)
    item = []
    if nbi_items != []:
        curblock.append(blk_info)
        curblock.append(nbi_items)
        curblock.append(nbi_grps)
        blk_info = []
        nbi_items = []
        nbi_grps = []
    if curblock != []:
        oblocks.append(curblock)
        curblock = []

    # check groups...

    gnames.sort()
    gprev = "???"
    ierct = 0
    for gname in gnames:
        if gname == gprev:
            print("?nbigen_sub: duplicate output group name: " + gname)
            ierct = ierct + 1
        gprev = gname

    if ierct > 0:
        print("?nbigen_sub: EXIT due to duplicate group names.")
        raise nbigen_error

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        nbi_items = curblock[1]
        nbi_grps = curblock[2]
        #  print " block name: " + bname
        for grp in nbi_grps:
            idimn = "NONE"
            gname = grp[0]
            #  print " ...group name: " + gname
            gmembs= grp[1]
            glabel= grp[2]
            gunits= glabel.split(';')
            gunits = gunits[0].strip().upper()

            for gmemb in gmembs:
                ifound = 0
                for item in nbi_items:
                    iname = item[0]
                    dims = item[4]
                    olabel = item[10]
                    ounits= olabel.split(';')
                    ounits = ounits[0].strip().upper()
                    if gmemb == iname:
                        ifound = 1
                        item[11].append([gname,glabel,len(gmembs)])
                        if idimn == "NONE":
                            idimn = dims
                            gmem0 = gmemb
                        else:
                            if idimn != dims:
                                print(" ?nbigen_sub: dimension mismatch in output group: " + gname)
                                print("  member " + gmem0 + " dimensions: " + idimn)
                                print("  member " + gmemb + " dimensions: " + dims)
                                raise nbigen_error
                        if ounits != gunits:
                            print(" nbigen_sub warning: units mismatch:")
                            print("   group " + gname + ": " + gunits)
                            print("   member " + gmemb + ": " + ounits)
                            print("   ...in output block: " + bname)
                if ifound == 0:
                    print(" ?nbigen_sub: element " + gmemb + " in group " + gname)
                    print("  does not correspond to any item in output block: " + bname)
                    raise nbigen_syntax

            #  add dimensioning info to group

            grp.append(idimn)
    # start "outputs" helpfile appendix

    nbwrite( f_help3, "3 Appendix_D_Output_Structures_&_Methods")
    nbwrite( f_help3, " ")
    nbwrite( f_help3, " Methods and structure contents are shown, with")
    nbwrite( f_help3, " comments copied from nubeam/nbspec.dat ...")
    nbwrite( f_help3, " ")
    nbwrite( f_help3, " To define the referenced fortran-90 structures,")
    nbwrite( f_help3, " user code should include the statement: ")
    nbwrite( f_help3, " ")
    nbwrite( f_help3, "     use nbi_types")
    nbwrite( f_help3, " ")

    nbwrite(f_nbicom,"  !==============================================")
    nbwrite(f_nbicom,"  ! OUTPUT items...")
    nbwrite(f_nbicom," ")

    nbwrite(f_alloc,"  !==============================================")
    nbwrite(f_alloc,"  ! output arrays")
    nbwrite(f_alloc," ")

    nbwrite(f_alloc2,"  !==============================================")
    nbwrite(f_alloc2,"  ! output arrays")
    nbwrite(f_alloc2," ")

    nbwrite(f_dalloc,"  !==============================================")
    nbwrite(f_dalloc,"  ! output arrays")
    nbwrite(f_dalloc," ")


    #  start ascii i/o routine -- for debugging purposes

    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"subroutine nbo_ascii")
    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"  use nbi_com")
    nbwrite(f_asciio," ")

    #-------------------------

    nbwrite(f_nboclr,"subroutine nbo_clear")
    nbwrite(f_nboclr," ")
    nbwrite(f_nboclr,"  use nbi_com")
    nbwrite(f_nboclr,"  implicit NONE")
    nbwrite(f_nboclr," ")

    #-------------------------

    nbwrite(f_nboldx,"subroutine nbo_load")
    nbwrite(f_nboldx," ")
    nbwrite(f_nboldx,"  use nbi_com")
    nbwrite(f_nboldx,"  use physconst_mod, only: zero")
    nbwrite(f_nboldx,"  implicit NONE")
    nbwrite(f_nboldx," ")
    nbwrite(f_nboldx,"  INTEGER :: i,j,k,ival")
    nbwrite(f_nboldx,"  real(fp) :: zdata(mj),zr8val,zsmoo,zsmoosave")
    nbwrite(f_nboldx,"  CHARACTER*32 :: zname,zunits")
    nbwrite(f_nboldx,"  CHARACTER*60 :: zlroot,zlabel")

    #-------------------------

    nbwrite(f_nboldxf,"subroutine nbo_load_frantic")
    nbwrite(f_nboldxf," ")
    nbwrite(f_nboldxf,"  use nbi_com")
    nbwrite(f_nboldxf,"  use physconst_mod, only: zero")
    nbwrite(f_nboldxf,"  implicit NONE")
    nbwrite(f_nboldxf," ")
    nbwrite(f_nboldxf,"  INTEGER :: i,j,k,ival")
    nbwrite(f_nboldxf,"  real(fp) :: zdata(mj),zr8val,zsmoo,zsmoosave")
    nbwrite(f_nboldxf,"  CHARACTER*32 :: zname,zunits")
    nbwrite(f_nboldxf,"  CHARACTER*60 :: zlroot,zlabel")

    nbwrite(f_nboldxf," ")
    ijks = ["i","j","k"]

    #-------------------------

    for curblock in oblocks:
        blk_info = curblock[0]
        nbi_items = curblock[1]
        nbi_grps = curblock[2]
        bname = blk_info[0]
        nbwrite(f_alloc,"  ! ... block: " + bname + " .........")
        nbwrite(f_alloc2,"  ! ... block: " + bname + " .........")
        nbwrite(f_dalloc,"  ! ... block: " + bname + " .........")
        nbwrite(f_nbicom,"  ! ... block: " + bname + " .........")
        nbwrite(f_nboclr,"  ! ... block: " + bname + " .........")

        if bname == "frantic":
            nbwrite(f_nboldxf," ")
            nbwrite(f_nboldxf,"  !-----------------------------------")
            nbwrite(f_nboldxf,"  ! ... block: " + bname + " .........")
            nbwrite(f_nboldxf," ")
        else:
            nbwrite(f_nboldx," ")
            nbwrite(f_nboldx,"  !-----------------------------------")
            nbwrite(f_nboldx,"  ! ... block: " + bname + " .........")
            nbwrite(f_nboldx," ")


#MG dec09,2008
#        if bname == "nclass":
#            nbwrite(f_nboldx," ")
#            nbwrite(f_nboldx,"  call r8bsmoo_get(zsmoosave)")
#            nbwrite(f_nboldx,"  zsmoo=max(abs(dxbsmoo),abs(dxbsm_nc))")
#            nbwrite(f_nboldx,"  call r8bsmoo_init(mj,lcentr,ledge,zsmoo,xi_r8)")
#            nbwrite(f_nboldx," ")

        nbwrite(f_nboget," ")
        nbwrite(f_nboget,"subroutine nbo_get_" + bname + "(zblock)")
        nbwrite(f_nboget," ")
        nbwrite(f_nboget,"  use nbi_com")
        nbwrite(f_nboget,"  use nbi_types")
        nbwrite(f_nboget," ")
        nbwrite(f_nboget,"  implicit NONE")
        nbwrite(f_nboget," ")
        nbwrite(f_nboget,"  type (nbotype_" + bname + ") :: zblock")
        nbwrite(f_nboget," ")

        ohelp_start(f_help3, bname)

        ict_asciio = 0

        for cmt in blk_info[1:]:
            nbwrite(f_nbicom,"    " + cmt)
            nbwrite(f_help3,  "    " + cmt)

        # write nbi_types -- type definitions for nbi code output
        # all have names "nbotype_" + block name

        type_name = "nbotype_" + bname
        nbwrite(f_nbityp," ")
        nbwrite(f_nbityp,"  type " + type_name)

        for item in nbi_items:

            name = item[0]
            dtype = item[1]  # data type e.g. "INTEGER"
            atype = item[2]  # scalar or array
            mode = item[3]
            dims = item[4]
            ndims = len(dims.split(","))
            defer_alloc = "NA"  # (for scalars)
            if atype == "array":
                defer_alloc = item[5]  # TRUE or FALSE (for arrays) or NA
            proftype = item[6]
            ioname = item[7]
            iodims = item[8]
            scale_fac = item[9]
            olabel = item[10]
            grplist = item[11]
            cmts = item[12:]

            # initial values...

            [dval,type_abbrev] = nbtype_dval(item[1])

            # write nbi_com

            if atype == "scalar":
                s = "  " + dtype.lower() + " :: " + name + " = " + dval
            else:

                # the array itself

                s = "  " + dtype.lower() + ", dimension("
                ctr = 0
                while ctr < ndims:
                    ctr = ctr + 1
                    s = s + ":"
                    if ctr < ndims:
                        s = s + ","
                    else:
                        s = s + ")"
                s = s + ", allocatable :: " + name

            nbwrite(f_nbicom,s)

            if ioname != "":

                # the associated xplasma id scalar or array:

                if iodims == "":
                    s = "  INTEGER :: " + ioname + " = 0"
                    str2 = "  CHARACTER*32 :: " + ioname + "_name = ' '"
                else:
                    s = "  INTEGER, dimension("
                    str2 = "  CHARACTER*32, dimension("
                    ctr = 0
                    while ctr < ndims-1:
                        ctr = ctr + 1
                        s = s + ":"
                        str2 = str2 + ":"
                        if ctr < ndims -1:
                            s = s + ","
                            str2 = str2 + ","
                        else:
                            s = s + ")"
                            str2 = str2 + ")"
                    s = s + ", allocatable :: " + ioname
                    str2 = str2 + ", allocatable :: " + ioname + "_name"

                nbwrite(f_nbicom,s)
                nbwrite(f_nbicom,str2)

            s = "        ! '" + olabel + "'"
            nbwrite(f_nbicom,s)
            for cmt in cmts:
                s = "        " + cmt
                nbwrite(f_nbicom,s)

            # write allocator... also for associated xplasma ids array if any

            if atype == "array":
                if name.lower() == "fbm_cx":
                    s = "  if(ncx0.gt.0) allocate(" + name + dims + "); "
                elif name.lower() == "fbm_ptcl":
                    s = "  if(nlfbmflr) allocate(" + name + dims + "); "
                else:
                    s = "  allocate(" + name + dims + "); "
                s = s + name + " = " + dval
                if iodims != "":
                    str2 = "  allocate(" + ioname + iodims + "); "
                    str2 = str2 + ioname + " = 0"
                    str3 = "  allocate(" + ioname + "_name" + iodims + "); "
                    str3 = str3 + ioname + "_name = ' '"
                if defer_alloc == "TRUE":
                    ialloc2_start = wr_alloc_check(f_alloc2,
                                                   "nbi_alloc2",name,ialloc2_start)
                    nbwrite(f_alloc2,s)
                    if iodims != "": nbwrite(f_alloc2,str2)
                    if iodims != "": nbwrite(f_alloc2,str3)
                elif defer_alloc == "FALSE":
                    ialloc_start = wr_alloc_check(f_alloc,
                                                  "nbi_alloc",name,ialloc_start)
                    nbwrite(f_alloc,s)
                    if iodims != "": nbwrite(f_alloc,str2)
                    if iodims != "": nbwrite(f_alloc,str3)

                # write deallocator

                s = "  if(allocated(" + name + ")) deallocate(" + name + ")"
                nbwrite(f_dalloc,s)
                if iodims != "":
                    str2 = "  if(allocated(" + ioname
                    str2 = str2 + ")) deallocate(" + ioname + ")"
                    str3 = "  if(allocated(" + ioname + "_name"
                    str3 = str3 + ")) deallocate(" + ioname + "_name)"
                    nbwrite(f_dalloc,str2)
                    nbwrite(f_dalloc,str3)

            # write type declaration component.

            nbwrite(f_help3," ")
            if atype == "scalar":
                nbwrite(f_nbityp,"    " + dtype.lower() + " :: " + name)
                nbwrite(f_help3,  "    " + dtype.lower() + " :: " + name)

            else:
                if ioname != "":

                    # profiles: write ids (only) into TYPE declaration

                    if iodims == "":
                        nbwrite(f_nbityp,"    INTEGER :: " + ioname)
                        nbwrite(f_help3,  "    INTEGER :: " + ioname)
                        nbwrite(f_help3,  "               ! XPLASMA id for " +
                                name.upper() + " profile.")
                    else:
                        cdims = nbi_dimcon(iodims,nbi_initdims,nbi_initlims)
                        s = "    INTEGER :: " + ioname + cdims
                        s = s + "  ! " + iodims
                        nbwrite(f_nbityp,s)
                        nbwrite(f_help3,  s)
                        nbwrite(f_help3,  "               ! XPLASMA ids for " +
                                name.upper() + " profiles.")
                else:
                    # not a profile

                    cdims = nbi_dimcon(dims,nbi_initdims,nbi_initlims)
                    s = "    " + dtype.lower() + " :: " + name + cdims
                    s = s + "  ! " + dims
                    nbwrite(f_nbityp,s)
                    nbwrite(f_help3,  s)

            s = "        ! '" + olabel + "'"
            nbwrite(f_help3,s)
            for cmt in cmts:
                s = "        " + cmt
                nbwrite(f_help3,s)

            # write code for ascii printout of non-profile outputs
            if proftype == "NONE":
                if atype == "scalar":
                    sname = "nbi_ascii_" + type_abbrev + "_wr0"
                    s = "  call " + sname
                    s = s + "(nonlin, '" + name + "', " + name + ")"
                else:
                    sname = "nbi_ascii_" + type_abbrev + "_wr" + repr(ndims)
                    s = "  call " + sname
                    s = s + "(nonlin, '" + name + "', " + name
                    udims = dims[1:-1].split(",")
                    for udim in udims:
                        s = s + ", " + udim
                    s = s + ")"

                ict_asciio = ict_asciio + 1
                if ict_asciio == 1:
                    nbwrite(f_asciio," ")
                    nbwrite(f_asciio,"  write(nonlin,*) ' '")
                    nbwrite(f_asciio,
                            "  write(nonlin,*) ' *** output scalars: " +
                            bname + " *** '")
                    nbwrite(f_asciio,"  write(nonlin,*) ' '")
                    nbwrite(f_asciio," ")

                nbwrite(f_asciio,s)

            # write code to clear all non-stateful outputs

            if mode != "stateful" and mode != "ptclstate":
                nbwrite(f_nboclr,"  " + name + " = " + dval)
            if mode == "stateful" :
                nbwrite(f_nboclr,
                        "  ! (" + name + " not cleared:  state variable).")
            if mode == "ptclstate" :
                nbwrite(f_nboclr,
                        "  ! (" + name + " not cleared:  ptcl state variable).")

            if ioname != "":
                nbwrite(f_nboclr,"  " + ioname + " = 0")
                nbwrite(f_nboclr,"  " + ioname + "_name = ' '")

            # write code to load all profile outputs

            if ioname != "":
                udims = iodims
            else:
                udims = dims

            ingrp = len(grplist)
            if udims == "":
                # solitary scalar or profile

                if ioname != "":
                    # profile
                    nbwrite(f_nboldx,
                            "  call nbo_lbl_split('" + olabel + "',zlabel,zunits)")
                    s = "  call nbo_smoo1('" + proftype +"'," + name + ")"
                    nbwrite(f_nboldx,s)
                    s = "  call nbo_load1('" + proftype +"', '" + name + "',"
                    s = s + " zlabel, zunits, "
                    if scale_fac != "":
                        s = s + name + "*" + scale_fac +", ival, zr8val)"
                    else:
                        s = s + name + ", ival, zr8val)"
                    nbwrite(f_nboldx,s)
                    nbwrite(f_nboldx,"  " + ioname + " = ival")
                    nbwrite(f_nboldx,"  " + ioname +
                            "_name = trim(oprefix)//'" + name + "'")
                    nbwrite(f_nboldx," ")
            else:
                # array of scalars or profiles
                dimall = dims[1:-1].split(",")
                ict = -1
                indim = 0
                imj = 1
                istr = "("
                jstr = "("
                namstr = "('" + name + "',"
                indent = "  "
                if ioname != "":
                    for adim in dimall:
                        indim = indim + 1
                        dim = adim.strip().lower()
                        if dim != "mj":
                            ict = ict + 1
                            s = indent + "do " + ijks[ict] + " = 1," + dim
                            if bname == "frantic":
                                nbwrite(f_nboldxf,s)
                            else:
                                nbwrite(f_nboldx,s)

                            indent = indent + "  "
                            istr = istr + ijks[ict]
                            jstr = jstr + ijks[ict] + ","
                            namstr = namstr + "'" + dim + "'," + ijks[ict] +","
                        else:
                            imj = 0
                            istr = istr + "1:mj"

                        if indim < ndims:
                            istr = istr + ","
                        else:
                            istr = istr + ")"
                            jstr = jstr[:-1] + ")"
                            while indim < 4-imj:
                                indim = indim + 1
                                namstr = namstr + "' ',0,"
                            namstr = namstr + "zname, &"

                    namstr2 = indent + "     zlroot, zlabel)"

                    if bname != "frantic":
                        nbwrite(f_nboldx, indent + "zdata = " + name + istr)
                        nbwrite(f_nboldx,
                                indent + "if(maxval(abs(zdata)).gt.zero) then")
                        indent = indent + "  "
                        nbwrite(f_nboldx,
                                indent + "call nbo_smoo1('" + proftype +"',zdata)")
                    else:
                        nbwrite(f_nboldxf, indent + "zdata = " + name + istr)


                    if scale_fac != "":
                        s = indent + name + istr + " = zdata"
                        s = s + "; zdata = zdata*" + scale_fac
                        if bname == "frantic":
                            nbwrite(f_nboldxf, s)
                        else:
                            nbwrite(f_nboldx, s)

                    else:
                        if bname != "frantic":
                            nbwrite(f_nboldx, indent + name + istr + " = zdata")
                    indent = indent[:-2]
                    if bname == "frantic":
                        nbwrite(f_nboldxf,indent +
                                "call nbo_lbl_split('" + olabel + "',zlroot,zunits)")
                        nbwrite(f_nboldxf,indent + "call nbo_name1" + namstr)
                        nbwrite(f_nboldxf,namstr2)

                        s = indent + "call nbo_load1('" + proftype +"', zname, "
                        s = s + "zlabel, zunits, zdata, ival, zr8val)"
                        nbwrite(f_nboldxf,s)
                        nbwrite(f_nboldxf,indent + ioname + jstr + " = ival")
                        nbwrite(f_nboldxf,indent + ioname + "_name" + jstr +
                                " = trim(oprefix)//trim(zname)")
                    else:
                        nbwrite(f_nboldx, indent + "endif")
                        nbwrite(f_nboldx,indent +
                                "call nbo_lbl_split('" + olabel + "',zlroot,zunits)")
                        nbwrite(f_nboldx,indent + "call nbo_name1" + namstr)
                        nbwrite(f_nboldx,namstr2)

                        s = indent + "call nbo_load1('" + proftype +"', zname, "
                        s = s + "zlabel, zunits, zdata, ival, zr8val)"
                        nbwrite(f_nboldx,s)
                        nbwrite(f_nboldx,indent + ioname + jstr + " = ival")
                        nbwrite(f_nboldx,indent + ioname + "_name" + jstr +
                                " = trim(oprefix)//trim(zname)")

                    for adim in dimall:
                        dim = adim.strip().lower()
                        if dim != "mj":
                            indent = indent[:-2]
                            if bname == "frantic":
                                nbwrite(f_nboldxf, indent + "enddo")
                            else:
                                nbwrite(f_nboldx, indent + "enddo")

                    if bname == "frantic":
                        nbwrite(f_nboldxf," ")
                    else:
                        nbwrite(f_nboldx," ")


            if ioname != "":
                # write nbo_get routine
                #  (ioname part)

                if iodims == "":
                    nbwrite(f_nboget,"  zblock%" + ioname + " = " + ioname)
                else:
                    nbocopy_array(f_nboget,ioname,iodims,"")

            else:
                # write nbo_get routine  (non-ioname part)

                if atype == "scalar":
                    if scale_fac != "":
                        s = "  zblock%" + name + " = " + name
                        s = s + "*" + scale_fac
                        nbwrite(f_nboget,s)
                    else:
                        nbwrite(f_nboget,"  zblock%" + name + " = " + name)
                else:
                    nbocopy_array(f_nboget,name,dims,scale_fac)

        # end nbo type declaration

        nbwrite(f_nbityp,"  end type " + type_name)

        nbwrite(f_nboget," ")
        nbwrite(f_nboget,"end subroutine nbo_get_" + bname)

#MG dec09,2008
#        if bname == "nclass":
#            nbwrite(f_nboldx,"  call r8bsmoo_init(mj,lcentr,ledge,zsmoosave,xi_r8)")

    nbwrite(f_nboldxf," ")
    nbwrite(f_nboldxf,"end subroutine nbo_load_frantic")
    nbwrite(f_nboldx," ")
    nbwrite(f_nboldx,"end subroutine nbo_load")

    nbwrite(f_nboclr," ")
    nbwrite(f_nboclr,"end subroutine nbo_clear")

    #------------------------------------
    #  state-file i/o

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_define3")

    for curblock in oblocks:
        nbi_items = curblock[1]
        for item in nbi_items:

            if item[3] == "stateful":
                dname = item[0]

                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                nbwrite_defvar(dname,dabbrev,dims)

    nbstate_trlr0(f_statio, "nbi_state_define3")

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_output3")

    sublist = []
    for curblock in oblocks:
        nbi_items = curblock[1]
        for item in nbi_items:

            if item[3] == "stateful":
                dname = item[0]
                dtype = item[1]

                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                zlist = nbwrite_putvar(dname,dtype,ndims,dims,dimstring)
                sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_output3", sublist)

    nbwrite(f_statio," ")
    nbstate_hdr(f_statio, "nbi_state_read3")

    sublist = []
    for curblock in oblocks:
        nbi_items = curblock[1]
        for item in nbi_items:

            if item[3] == "stateful":
                dname = item[0]
                dtype = item[1]
                [dval,type_abbrev] = nbtype_dval(dtype)

                [dabbrev,dims,ndims,dimstring] = nbstate_pars1(item,0)

                zlist = nbwrite_getvar(dname,dtype,dval,ndims,dims,dimstring)
                sublist = sublist + zlist

    nbstate_trlr(f_statio, "nbi_state_read3", sublist)

    # Put state (field) data (read3) into broadcast buffer

    for curblock in oblocks:
        nbi_items = curblock[1]
        for item in nbi_items:

            if item[3] == "stateful":
                dname = item[0]
                dtype = item[1]
                if dtype[0]=='R':
                 s = "  call putdat(" + dname + ",inumr)"
                 nbwrite(f_bcast_st,s)
                 s = "  call getdat(" + dname + ",inumr)"
                 nbwrite(f_bcast_st_get,s)
                if dtype[0]=='I':
                 s = "  call putdat(" + dname + ",inumi)"
                 nbwrite(f_bcast_st,s)
                 s = "  call getdat(" + dname + ",inumi)"
                 nbwrite(f_bcast_st_get,s)
                if dtype[0]=='C':
                 s = "  call putdat(" + dname + ",inumc)"
                 nbwrite(f_bcast_st,s)
                 s = "  call getdat(" + dname + ",inumc)"
                 nbwrite(f_bcast_st_get,s)
                if dtype[0]=='L':
                 s = "  call putdat(" + dname + ",inuml)"
                 nbwrite(f_bcast_st,s)
                 s = "  call getdat(" + dname + ",inuml)"
                 nbwrite(f_bcast_st_get,s)
    nbwrite(f_bcast_st," ")

    input=open("nbi_state_user.f90",'r')
    lines=input.readlines()
    input.close()
    st_list=[]
    sstr="cdfDefVar"
    for line in lines:
      if line.find(sstr)!=-1 :
        st_list.append(line)
    st_items_nest=[]
    for line in st_list:
      st_items=[]
      y=line.split("'")
      st_items.append(y[1])
      st_items.append(y[3])
      st_items_nest.append(st_items)
    for item in st_items_nest:
        dnam=item[0]
        dtyp=item[1]
        if dtyp.upper() =='INT':
         s = "  call putdat(" + dnam + ",inumi)"
         nbwrite(f_bcast_st,s)
         s = "  call getdat(" + dnam + ",inumi)"
         nbwrite(f_bcast_st_get,s)
        if dtyp.upper() =='R8':
         s = "  call putdat(" + dnam + ",inumr)"
         nbwrite(f_bcast_st,s)
         s = "  call getdat(" + dnam + ",inumr)"
         nbwrite(f_bcast_st_get,s)
        if dtyp.upper() =='CHAR':
         if dnam=="NBI_XNAMES":
             s = "  IF(nbi_numhdr.GT.0) call putdat(" + dnam + ",inumc)"
             nbwrite(f_bcast_st,s)
             nbwrite(f_bcast_st_get,"  if(allocated(NBI_XNAMES)) deallocate(NBI_XNAMES)")
             s = "  IF(nbi_numhdr.GT.0) allocate(NBI_XNAMES(nbi_numhdr))"
             nbwrite(f_bcast_st_get,s)
             s = "  IF(nbi_numhdr.GT.0) call getdat(" + dnam + ",inumc)"
             nbwrite(f_bcast_st_get,s)

         else:
             s = "  call putdat(" + dnam + ",inumc)"
             nbwrite(f_bcast_st,s)
             s = "  call getdat(" + dnam + ",inumc)"
             nbwrite(f_bcast_st_get,s)
             s = "  IF(ALLOCATED(" + dnam + ")) call getdat(" + dnam + ",inumc)"
    nbwrite(f_bcast_st," ")
    nbwrite(f_bcast_st_get," ")
    nbwrite(f_bcast_st_get,"  RNG_CURSTATE%INDEX=NBI_STATE_INDX")
    nbwrite(f_bcast_st_get,"  RNG_CURSTATE%ARRAY(0:RNG_K-1)=NBI_STATE_ARR(0:RNG_K-1)")
    nbwrite(f_bcast_st_get," ")
    nbwrite(f_bcast_st,"end subroutine nbi_fld_bufput")
    nbwrite(f_bcast_st_get," ")
    nbwrite(f_bcast_st_get,"end subroutine nbi_fld_bufget")

    #------------------------------------
    # write trailers to several routines...
    #

    nbwrite(f_dalloc," ")
    nbwrite(f_dalloc,"end subroutine nbi_dalloc")

    nbwrite(f_dalloctr," ")
    nbwrite(f_dalloctr,"end subroutine nbi_dalloc_track")

    nbwrite(f_dalloctrz," ")
    nbwrite(f_dalloctrz,"end subroutine nbi_dalloc_track_zone")

    nbwrite(f_dalloclst," ")
    nbwrite(f_dalloclst,"end subroutine nbi_dalloc_lost")

    nbwrite(f_alloc," ")
    nbwrite(f_alloc,"end subroutine nbi_alloc_init")

    nbwrite(f_spltexpnd,"  i_spltexpnd = i_spltexpnd + 1")
    nbwrite(f_spltexpnd,"  if(allocated(tmp)) deallocate(tmp)")
    nbwrite(f_spltexpnd,"  if(allocated(itmp)) deallocate(itmp)")
    nbwrite(f_spltexpnd," ")
    nbwrite(f_spltexpnd,"end subroutine nbi_spltexpnd")

    nbwrite(f_allocsplt," ")
    nbwrite(f_allocsplt,"end subroutine nbi_alloc_splt")

    nbwrite(f_dallocsplt," ")
    nbwrite(f_dallocsplt,"end subroutine nbi_dalloc_splt")

    nbwrite(f_alloc2," ")
    nbwrite(f_alloc2,"  nbi_init_flag = .TRUE.   ! nbi module is ready.")
    nbwrite(f_alloc2," ")
    nbwrite(f_alloc2," write(nonlin,*)'% nbi_alloc2_init: nbi_alloc2 done'")
    nbwrite(f_alloc2,"end subroutine nbi_alloc2_init")

    nbwrite(f_alloctr," ")
    nbwrite(f_alloctr,"  write(nonlin,*)'% nbi_alloc_track: nbi_alloc_track done'")
    nbwrite(f_alloctr,"end subroutine nbi_alloc_track")

    nbwrite(f_alloctrz," ")
    nbwrite(f_alloctrz,"  write(nonlin,*)'% nbi_alloc_track_zone: alloc done, jsize=',jsize")
    nbwrite(f_alloctrz,"end subroutine nbi_alloc_track_zone")

    nbwrite(f_nbizone," ")
    nbwrite(f_nbizone,"  mtrk0_prev = mtrk0")
    nbwrite(f_nbizone,"  if(allocated(tmp)) deallocate(tmp)")
    nbwrite(f_nbizone," ")
    nbwrite(f_nbizone,"end subroutine nbi_expand_track_zone")

    nbwrite(f_alloclst," ")
    nbwrite(f_alloclst,"  write(nonlin,*)'% nbi_alloc_lost: nbi_alloc_lost done'")
    nbwrite(f_alloclst,"end subroutine nbi_alloc_lost")

    nbwrite(f_reallocm," ")
    nbwrite(f_reallocm,"   minb=minb_new")
    nbwrite(f_reallocm," ")
    nbwrite(f_reallocm,"end subroutine nbi_realloc_minb")

    nbwrite(f_allocm," ")
    nbwrite(f_allocm," ")
    nbwrite(f_allocm,"end subroutine nbi_alloc_minb")

    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"  write(nonlin,*) ' '")
    nbwrite(f_asciio," ")
    nbwrite(f_asciio,"end subroutine nbo_ascii")

    #------------------------------------
    #  list of names...

    for curblock in oblocks:
        nbi_items = curblock[1]
        for item in nbi_items:
            dname = item[0]
            nbi_allnames.append(dname.upper())

    #------------------------------------
    # one last thing...
    #
    # write list of all names

    nbi_allnames.sort()
    pname = "???"
    ierct = 0

    f = open("nbi_allnames.dat","w")
    for name in nbi_allnames:
        f.write(name + "\n")
        if pname == name:
            print("?nbigen_sub: duplicate item name: " + name)
            ierct = ierct + 1
        pname = name

    f.close()

    if ierct > 0:
        print("?nbigen_sub: duplicate item names detected: exiting.")
        raise nbigen_error

    #------------------------------------
    # NetCDF i/o of output structures

    nbwrite(f_out_io,"subroutine nbo_outputs_write(icdf)")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "  call nbo_out_" + bname + "_def(icdf)"
        nbwrite(f_out_io,s)

    nbwrite(f_out_io," ")
    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "  call nbo_out_" + bname + "_wr(icdf)"
        nbwrite(f_out_io,s)

    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"end subroutine nbo_outputs_write")
    nbwrite(f_out_io," ")

    nbwrite(f_out_io,"subroutine nbo_outputs_read(icdf,ierr)")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_out_io,"  integer, intent(out) :: ierr ! Completion code, 0=OK")
    nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "  call nbo_out_" + bname + "_rd(icdf,ierr)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io,"  if(ierr.ne.0) return")

    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"end subroutine nbo_outputs_read")
    nbwrite(f_out_io," ")

    nbwrite(f_out_io,"subroutine nbo_outputs_avg_all(icdf,zwght,ierr)")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  use iso_c_binding, only: fp => c_double")
    nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
    nbwrite(f_out_io,"  real(fp), intent(in) :: zwght  ! weight factor")
    nbwrite(f_out_io,"  integer, intent(out) :: ierr ! Completion code, 0=OK")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  ierr = 0")
    nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "  call nbo_out_" + bname + "_avg(icdf,zwght,ierr)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io,"  if(ierr.ne.0) return")

    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"end subroutine nbo_outputs_avg_all")
    nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "subroutine nbo_out_" + bname + "_def(icdf)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  use nbi_com")
        nbwrite(f_out_io,"  use ezcdf")
        nbwrite(f_out_io,"  implicit NONE")
        nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_out_io," ")
        nbi_items = curblock[1]
        for item in nbi_items:
            #  write non-profile items only
            dname = item[7]
            if dname == "":
                dname = item[0]
                s = "  call cdf_define(icdf,'" + dname + "'," + dname + ")"
                nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        s = "end subroutine nbo_out_" + bname + "_def"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "subroutine nbo_out_" + bname + "_wr(icdf)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  use nbi_com")
        nbwrite(f_out_io,"  use ezcdf")
        nbwrite(f_out_io,"  implicit NONE")
        nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  if(icdf.eq.0) write(nonlin,*) &")
        nbwrite(f_out_io,"       'nbo_out_" + bname + "_wr: icdf=0.'")
        nbi_items = curblock[1]
        for item in nbi_items:
            #  write non-profile items only
            dname = item[7]
            if dname == "":
                dname = item[0]
                s = "  call cdf_write(icdf,'" + dname + "'," + dname + ")"
                nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        s = "end subroutine nbo_out_" + bname + "_wr"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "subroutine nbo_out_" + bname + "_rd(icdf,ierr)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  use nbi_com")
        nbwrite(f_out_io,"  use ezcdf")
        nbwrite(f_out_io,"  implicit NONE")
        nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_out_io,"  integer, intent(out) :: ierr ! Completion code, 0=OK")
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  ierr=0")
        nbwrite(f_out_io," ")
        nbi_items = curblock[1]
        for item in nbi_items:
            #  write non-profile items only
            dname = item[7]
            if dname == "":
                dname = item[0]
                s = "  call cdf_read(icdf,'" + dname + "'," + dname + ",ierr)"
                nbwrite(f_out_io,s)
                nbwrite(f_out_io,"  if(ierr.ne.0) return")
        nbwrite(f_out_io," ")
        s = "end subroutine nbo_out_" + bname + "_rd"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        s = "subroutine nbo_out_" + bname + "_avg(icdf,zwght,ierr)"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  use nbi_com")
        nbwrite(f_out_io,"  use nbi_out_avg ! helper routines")
        nbwrite(f_out_io,"  implicit NONE")
        nbwrite(f_out_io,"  integer, intent(in) :: icdf  ! NetCDF file id")
        nbwrite(f_out_io,"  real(fp), intent(in) :: zwght  ! time avg weight")
        nbwrite(f_out_io,"  integer, intent(out) :: ierr ! Completion code, 0=OK")
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  ierr = 0")
        nbwrite(f_out_io," ")
        nbi_items = curblock[1]
        for item in nbi_items:
            #  write non-profile items only
            dname = item[7]
            if dname == "":
                dname = item[0]
                s = "  call nbi_out_avg_sub(icdf,'" + dname
                s = s + "'," + dname + ",zwght,ierr)"
                nbwrite(f_out_io,s)
                nbwrite(f_out_io,"  if(ierr.ne.0) return")
        nbwrite(f_out_io," ")
        s = "end subroutine nbo_out_" + bname + "_avg"
        nbwrite(f_out_io,s)
        nbwrite(f_out_io," ")

    nbwrite(f_out_io,"subroutine nbo_names_write(ilun)")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  use nbi_com")
    nbwrite(f_out_io,"  use nbo_ascii_mod")
    nbwrite(f_out_io,"  implicit NONE")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  integer, intent(in) :: ilun  ! I/O unit number")
    nbwrite(f_out_io,"  logical  :: ilio  ! I/O FRANTIC block")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  ! block: " + bname)
        nbwrite(f_out_io," ")

        s=" "
        if bname == "frantic":
            nbwrite(f_out_io,"  ilio = (LEVMOD_HALO.eq.1) ")
            s="  if(ilio)"
        nbi_items = curblock[1]
        for item in nbi_items:
            #  write profile item names only
            dname = item[7]
            if dname != "":
                nbwrite(f_out_io,s +" call nbo_wr_aname(ilun,'" +
                        dname + "'," + dname + "_name)")

    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"end subroutine nbo_names_write")

    nbwrite(f_out_io,"subroutine nbo_names_read(ilun,ierr)")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  use nbi_com")
    nbwrite(f_out_io,"  use nbo_ascii_mod")
    nbwrite(f_out_io,"  implicit NONE")
    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"  integer, intent(in) :: ilun  ! I/O unit number")
    nbwrite(f_out_io,"  logical  :: ilio  ! I/O FRANTIC block")
    nbwrite(f_out_io,"  integer, intent(out) :: ierr ! status code, 0=OK")

    for curblock in oblocks:
        blk_info = curblock[0]
        bname = blk_info[0]
        nbwrite(f_out_io," ")
        nbwrite(f_out_io,"  ! block: " + bname)
        nbwrite(f_out_io," ")

        s=" "
        if bname == "frantic":
            nbwrite(f_out_io,"  ilio = (LEVMOD_HALO.eq.1) ")
            s="  if(ilio)"
        nbi_items = curblock[1]
        for item in nbi_items:
            #  read profile item names only
            dname = item[7]
            if dname != "":
                nbwrite(f_out_io,s+" call nbo_rd_aname(ilun,'" +
                        dname + "'," + dname + "_name," + dname + ",ierr)")
                nbwrite(f_out_io,"  if(ierr.ne.0) return")

    nbwrite(f_out_io," ")
    nbwrite(f_out_io,"end subroutine nbo_names_read")

    return 0

#--------------------------------------------------------------------
def write_pllsub(pll_section,subname,callname,pll_work):
    if callname == "r8get_dpt" and pll_section != "dpt":
        return 0

    sname = "subroutine " + subname + "_" + pll_section

    if pll_section == "dpt" and callname == "r8get_dpt" :
        nbwrite(f_pcopy,sname+"(mtrks)")
        nbwrite(f_pcopy,"! MPI run only. Read track data from black box and write to NetCdf file ")
        nbwrite(f_pcopy,"  use nbi_com")
        nbwrite(f_pcopy,"  use nbi_pllbuf")
        nbwrite(f_pcopy,"  use nbi_mpi_com")
        nbwrite(f_pcopy,"  use netcdf")
        nbwrite(f_pcopy,"  implicit NONE")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"  integer :: ir,isb,inum,ip,ic")
        nbwrite(f_pcopy,"  integer :: mdep,mtrk_0 !local")
        nbwrite(f_pcopy,"  real(fp), dimension(:,:),allocatable :: tmp !local")
        nbwrite(f_pcopy,"  integer :: id_ndep0_use, id_mdep, id_mibs_use, id_mtrk0")
        nbwrite(f_pcopy,"  character*150 fname !NetCdf file name for track data")
        nbwrite(f_pcopy,"  integer :: ierr")
        nbwrite(f_pcopy,"  character*30 :: cvar")
        nbwrite(f_pcopy,"  integer, parameter :: iversion_deptrk = 3 ! 3d arrays of the track data have been written as 1d arrays, 01/15/10")
        nbwrite(f_pcopy,"                                            ! iversion_deptrk = 2")
        nbwrite(f_pcopy,"  integer, dimension(:),allocatable :: mtrk_n, iadr_empty !local")
        nbwrite(f_pcopy,"  integer, dimension(*) :: mtrks !# of track for each species")
        nbwrite(f_pcopy,"  integer :: icdf")
        nbwrite(f_pcopy,"  integer :: id_iversion_deptrk")
        nbwrite(f_pcopy,"  integer, dimension(2) :: idims,istart,icount")
        nbwrite(f_pcopy,"  integer :: ijmem,fsystem_mem")

        nbwrite(f_wrdpt,"subroutine nbi_wrdeptrk")
        nbwrite(f_pcopy,"! Serial run only. Write track data to NetCdf file ")
        nbwrite(f_wrdpt,"  use nbi_com")
        nbwrite(f_wrdpt,"  use netcdf")
        nbwrite(f_wrdpt,"  implicit NONE")
        nbwrite(f_wrdpt,"  integer :: mdep !local")
        nbwrite(f_wrdpt,"  integer :: id_ndep0_use, id_mdep, id_mibs_use, id_mtrk0")
        nbwrite(f_wrdpt,"  character*150 fname !NetCdf file name for track data")
        nbwrite(f_wrdpt,"  integer :: ierr")
        nbwrite(f_wrdpt,"  character*30 :: cvar")
        nbwrite(f_wrdpt,"  integer, parameter :: iversion_deptrk = 3 ! 3d arrays of the track data have been written as 1d arrays, 01/15/10")
        nbwrite(f_wrdpt,"                                            ! iversion_deptrk = 2")
        nbwrite(f_wrdpt,"  integer :: icdf")
        nbwrite(f_wrdpt,"  integer :: id_iversion_deptrk")
        nbwrite(f_wrdpt,"  integer, dimension(2) :: idims,istart,icount")
        nbwrite(f_wrdpt,"  integer :: ijmem,fsystem_mem")
    elif pll_section == "dpt" and callname == "r8get":
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," if(mibs_use.le.0) then ")
        nbwrite(f_pcopy,"    write(nonlin,*) ' !nbi_pget_dpt: no beams species -- mibs_use.le.0'")
        nbwrite(f_pcopy,"    return ")
        nbwrite(f_pcopy," endif ")
        nbwrite(f_pcopy," ijmem = fsystem_mem() ! print out memory usage")

        nbwrite(f_pcopy," mdep = mdep0")
        nbwrite(f_pcopy," mdep0 = ndep0_use")
        nbwrite(f_pcopy," write(nonlin,*) ' %nbi_pget_dpt: ndep0_use=',ndep0_use,', mibs_use=',mibs_use,', mtrk0=',mtrk0")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," inum = 0")
        nbwrite(f_pcopy," mtrk_0 = 0")
        nbwrite(f_pcopy," if(allocated(mtrk_n)) deallocate(mtrk_n)")
        nbwrite(f_pcopy," allocate(mtrk_n(mibs_use))")
        nbwrite(f_pcopy," if(allocated(iadr_empty)) deallocate(iadr_empty)")
        nbwrite(f_pcopy," allocate(iadr_empty(mibs_use))")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," mtrk_n = 0")
        nbwrite(f_pcopy," iadr_empty = 0")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," ierr=0")
        nbwrite(f_pcopy," fname = trim(workpath)//trim(runid)//'_dpt.cdf'")
        nbwrite(f_pcopy,"!overwrite file")
        nbwrite(f_pcopy," ierr = nf90_create(path=trim(fname),cmode= or(NF90_CLOBBER,NF90_64BIT_OFFSET),ncid=icdf)")
        nbwrite(f_pcopy," if(ierr.ne.0) then")
        nbwrite(f_pcopy,"   write(nonlin,*) ' ?nbi_pget_dpt error: cannot create file: '//trim(fname)")
        nbwrite(f_pcopy,"   return")
        nbwrite(f_pcopy," endif")
        nbwrite(f_pcopy," call check(nf90_def_var(icdf,'iversion_deptrk',NF90_INT,id_iversion_deptrk),'iversion_deptrk')")
        nbwrite(f_pcopy," call check(nf90_def_var(icdf,'mdep',NF90_INT,id_mdep),'mdep')")
        nbwrite(f_pcopy," call check(nf90_def_dim(icdf,'ndep0_use',ndep0_use,id_ndep0_use),'ndep0_use')")
        nbwrite(f_pcopy," call check(nf90_def_dim(icdf,'mtrk0',mtrk0,id_mtrk0),'mtrk0')")
        nbwrite(f_pcopy," call check(nf90_def_dim(icdf,'mibs_use',mibs_use,id_mibs_use),'mibs_use')")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," idims = (/id_ndep0_use,id_mibs_use/)")
        nbwrite(f_pcopy," icount = (/mdep,mibs_use/)")

        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt," if(mibs_use.le.0) then ")
        nbwrite(f_wrdpt,"    write(nonlin,*) ' !nbi_wrdeptrk:no beams species -- mibs_use.le.0'")
        nbwrite(f_wrdpt,"    return ")
        nbwrite(f_wrdpt," endif ")
        nbwrite(f_wrdpt," ijmem = fsystem_mem() ! print out memory usage")
        nbwrite(f_wrdpt," mdep = mdep0")
        nbwrite(f_wrdpt," write(nonlin,*) ' %nbi_wrdeptrk: ndep0_use=',ndep0_use,', mibs_use=',mibs_use,', mtrk0=',mtrk0")
        nbwrite(f_wrdpt," ierr=0")
        nbwrite(f_wrdpt," fname = trim(workpath)//trim(runid)//'_dpt.cdf'")
        nbwrite(f_wrdpt,"!overwrite file")
        nbwrite(f_wrdpt," ierr = nf90_create(path=trim(fname),cmode= or(NF90_CLOBBER,NF90_64BIT_OFFSET),ncid=icdf)")
        nbwrite(f_wrdpt," if(ierr.ne.0) then")
        nbwrite(f_wrdpt,"   write(nonlin,*) ' ?nbi_wrdeptrk error: cannot create file: '//trim(fname)")
        nbwrite(f_wrdpt,"   return")
        nbwrite(f_wrdpt," endif")
        nbwrite(f_wrdpt," call check(nf90_def_var(icdf,'iversion_deptrk',NF90_INT,id_iversion_deptrk),'iversion_deptrk')")
        nbwrite(f_wrdpt," call check(nf90_def_var(icdf,'mdep',NF90_INT,id_mdep),'mdep')")
        nbwrite(f_wrdpt," call check(nf90_def_dim(icdf,'ndep0_use',ndep0_use,id_ndep0_use),'ndep0_use')")
        nbwrite(f_wrdpt," call check(nf90_def_dim(icdf,'mtrk0',mtrk0,id_mtrk0),'mtrk0')")
        nbwrite(f_wrdpt," call check(nf90_def_dim(icdf,'mibs_use',mibs_use,id_mibs_use),'mibs_use')")
        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt," idims = (/id_ndep0_use,id_mibs_use/)")
        nbwrite(f_wrdpt," icount = (/mdep,mibs_use/)")
        nbwrite(f_wrdpt," istart = (/1,1/)")

        for pitem in pll_work:
            sect = pitem[0]
            dims = pitem[1]
            if sect == "dpt":
                args = pitem[2]
                arg1 = args[1:-6]
                idem_tr = arg1.split("1")
                for itr in idem_tr:
                    if itr[0] != ":":
                        name_tr = itr[0:-1]
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy,"  cvar = '"+ name_tr+"'")
                        nbwrite(f_wrdpt,"  cvar = '"+ name_tr+"'")
                        if dims.lower() == "mtrk0":
                            nbwrite(f_pcopy,"  call check( nf90_def_var(icdf,cvar,NF90_DOUBLE,id_mtrk0,id_"+name_tr+"),cvar)")
                            nbwrite(f_wrdpt,"  call check( nf90_def_var(icdf,cvar,NF90_DOUBLE,id_mtrk0,id_"+name_tr+"),cvar)")
                        else:
                            nbwrite(f_pcopy,"  call check( nf90_def_var(icdf,cvar,NF90_DOUBLE,idims,id_"+name_tr+"),cvar)")
                            nbwrite(f_wrdpt,"  call check( nf90_def_var(icdf,cvar,NF90_DOUBLE,idims,id_"+name_tr+"),cvar)")



        nbwrite(f_pcopy," ierr = nf90_enddef(icdf) ! out of def mode and go to data mode")

    elif pll_section == "lst" and callname == "r8get":
        nbwrite(f_pcopy,sname)
        nbwrite(f_pcopy,"  use nbi_com")
        nbwrite(f_pcopy,"  use nbi_pllbuf")
        nbwrite(f_pcopy,"  use nbi_mpi_com")
        nbwrite(f_pcopy,"  use nbi_lost_ptcl, only: mlost_all")
        nbwrite(f_pcopy,"  implicit NONE")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"  integer ir,inum, mlst0, mlst")
        nbwrite(f_pcopy,"  real(fp), dimension(:),allocatable :: tmp !local")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," mlost_data = sum(mlost_all)")
        nbwrite(f_pcopy," if(mlost_data.eq.0) return")
        nbwrite(f_pcopy," call nbi_alloc_lost  ! allocate lost arrays only on CPU0")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy," inum = 0")
        nbwrite(f_pcopy," mlst0 = 1")
        nbwrite(f_pcopy," do ir = 1, numprocd")
        nbwrite(f_pcopy,"  mlst = mlost_all(ir)")
        nbwrite(f_pcopy,"  if(mlst.eq.0) cycle")
    else:
        nbwrite(f_pcopy,sname)
        nbwrite(f_pcopy,"  use nbi_com")
        nbwrite(f_pcopy,"  use nbi_pllbuf")
        nbwrite(f_pcopy,"  implicit NONE")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"  integer ir,ib,inum")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"  inum = 0")
        if subname == "nbi_zcheck":
            nbwrite(f_pcopy,"  nbuf_data = 0")
            nbwrite(f_pcopy,"  nbuf_" + pll_section + " = 0")

        if subname == "nbi_pput":
            if pll_section == "dpt":
                nbwrite(f_pcopy,"  nbuf_data = " + " mdep0*mibs_use*12 + mtrk0*8 ")
            elif pll_section == "lst" or  pll_section == "ntr":
                nbwrite(f_pcopy,"  nbuf_data = " + " nbuf_" + pll_section)
            else:
                nbwrite(f_pcopy,"  nbuf_data = " + " nbuf_" + pll_section + " + 1   ! count puseyp(lsbeam)")

    str_prev = "allocate"
    klst = 0
    n_wrote=0
    for pitem in pll_work:
        sect = pitem[0]
        if sect == pll_section:
            if callname != "r8get_dpt":
                nbwrite(f_pcopy," ")
            type = pitem[1]
            args = pitem[2]
            arg1 = args[1:-6]
            str_1 = ""
            if arg1[0:5] == "svn3v":
                nbwrite(f_pcopy,"  if(levmod_halo.eq.2) then")
                str_1 = "   "

            if arg1 == "puseyp(lsbeam)":
                if callname == "r8nz" or callname == "r8zero": continue

            if  sect == "dpt" and callname == "r8get_dpt" :
                idem_tr = arg1.split("1")
                idm = 0
                str_tmp = "tmp("
                wrk_trk = "("
                wrk_trk1 = "("

                for itr in idem_tr:
                    if itr[0] != ":":
                        name_tr = itr[0:-1]
                        nbwrite(f_pcopy,"  integer :: id_"+name_tr)
                        nbwrite(f_wrdpt,"  integer :: id_"+name_tr)


            if  sect == "dpt" and callname == "r8get" :
                idem_tr = arg1.split("1")
                idm = 0
                str_tmp = "tmp("
                wrk_trk = "("
                wrk_trk1 = "("

                for itr in idem_tr:
                    if itr[0] != ":":
                        name_tr = itr[0:-1]
                    else:
                        idm = idm +1
                        if itr[1:-1].lower() == "mdep0":
                            str_tmp = str_tmp + itr[1:-2] + ","
                            wrk_trk = wrk_trk + "1" + itr[0:-2] + ","
                            wrk_trk1 = wrk_trk1 + "1+(ir-1)*" + itr[1:-2] + itr[0:-2] + '*ir,'
                        elif itr[1:-1].lower() == "mtrk0":
                            str_tmp = str_tmp + itr[1:-1] + ","
                            wrk_trk = wrk_trk + "1"+itr
                        else:
                            str_tmp = str_tmp + itr[1:-1] + ","
                            wrk_trk = wrk_trk + "1" + itr
                            wrk_trk1 = wrk_trk1 + "1" + itr
                if idm == 2:
                    str_tmp = "  allocate("+ str_tmp[0:-1] + "))"
                    wrk_trk = wrk_trk [0:-1]  + ")"
                else:
                    str_tmp = "  allocate(" + str_tmp[0:-2] + "_0,1))"
                    wrk_trk = "(1:" + itr[1:-2] + "_0,1)"
                if str_prev != str_tmp:
                    if n_wrote != 0 :
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy,"  if(allocated(tmp)) deallocate(tmp)")
                        nbwrite(f_pcopy,str_tmp)
                        nbwrite(f_pcopy,"  tmp = zero")
                        nbwrite(f_pcopy,"  ")


                    else:
                        nbwrite(f_pcopy," call check( nf90_put_var(icdf,id_mdep,mdep),'mdep')")
                        nbwrite(f_pcopy," call check( nf90_put_var(icdf,id_iversion_deptrk,iversion_deptrk),'iversion_deptrk')")
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy," iadr_empty(1)=1")
                        nbwrite(f_pcopy," if(mibs_use.gt.1)then")
                        nbwrite(f_pcopy,"    do isb=2,mibs_use")
                        nbwrite(f_pcopy,"       iadr_empty(isb)=iadr_empty(isb-1)+mtrks(isb-1)")
                        nbwrite(f_pcopy,"    enddo ")
                        nbwrite(f_pcopy,"  endif")
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy," do ir = 1, numprocd")
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy,"  if(allocated(tmp)) deallocate(tmp)")
                        nbwrite(f_pcopy,str_tmp)
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy,"  istart = (/1+(ir-1)*mdep,1/)")
                        nbwrite(f_pcopy," ")
                        nbwrite(f_pcopy,"  tmp = zero")
                        nbwrite(f_pcopy," ")

                        nbwrite(f_wrdpt," ierr = nf90_enddef(icdf) ! out of def mode and go to data mode")
                        nbwrite(f_wrdpt," call check( nf90_put_var(icdf,id_mdep,mdep),'mdep')")
                        nbwrite(f_wrdpt," call check( nf90_put_var(icdf,id_iversion_deptrk,iversion_deptrk),'iversion_deptrk')")
                        nbwrite(f_wrdpt," ")

                    n_wrote=n_wrote+1


                else:
                    nbwrite(f_pcopy,"  tmp = zero")
                str_prev = str_tmp
                s =  "  call " + callname + "(" + "tmp" + wrk_trk + ",inum)"
                str1 = "  " +  name_tr + wrk_trk1 + "= tmp" + wrk_trk

                nbwrite(f_pcopy,s)
                if itr[1:-1].lower() == "mtrk0":
                    nbwrite(f_pcopy," ")
                    nbwrite(f_pcopy,"  cvar = '"+ name_tr+"'")
                    nbwrite(f_pcopy,"  ip = 1")
                    nbwrite(f_pcopy,"  ic = 0")
                    nbwrite(f_pcopy,"  do isb=1,mibs_use")
                    nbwrite(f_pcopy,"   ic = ic + mtrk_n(isb)")
                    str2 = "tmp(ip:ic,1)"
                    nbwrite(f_pcopy,"   call check( nf90_put_var(icdf,id_"+name_tr+","+str2+",start=(/iadr_empty(isb)/),count=(/mtrk_n(isb)/)),cvar)")
                    nbwrite(f_pcopy,"   ip = ic + 1")
                    nbwrite(f_pcopy,"  enddo")
                    nbwrite(f_wrdpt," ")
                    nbwrite(f_wrdpt," cvar = '"+ name_tr+"'")
                    nbwrite(f_wrdpt," call check( nf90_put_var(icdf,id_"+name_tr+","+name_tr+",start=(/1/),count=(/mtrk0/)),cvar)")
                    nbwrite(f_wrdpt," deallocate("+name_tr+")")

                else:
                    nbwrite(f_pcopy," ")
                    nbwrite(f_pcopy,"  cvar = '"+ name_tr+"'")
                    nbwrite(f_pcopy,"  call check( nf90_put_var(icdf,id_"+name_tr+",tmp,start=istart,count=icount),cvar)")
                    nbwrite(f_wrdpt," ")
                    nbwrite(f_wrdpt," cvar = '"+ name_tr+"'")
                    nbwrite(f_wrdpt," call check( nf90_put_var(icdf,id_"+name_tr+","+name_tr+",start=istart,count=icount),cvar)")
                    nbwrite(f_wrdpt," deallocate("+name_tr+")")

                    if name_tr == 'xntrack':
                        nbwrite(f_pcopy,"  mtrk_n(1:mibs_use) = sum(tmp(1:mdep,1:mibs_use),dim=1) + 0.5_fp")
                        nbwrite(f_pcopy,"  mtrk_0 = sum(tmp(1:mdep,1:mibs_use)) + 0.5_fp")
            elif  sect == "lst" and callname == "r8get" :
                idem_lst = arg1.split("1")
                for itr in idem_lst:
                    if itr[0] != ":":
                        name_lst = itr[0:-1]
                if klst == 0 :
                    nbwrite(f_pcopy,"  if(allocated(tmp)) deallocate(tmp)")
                    nbwrite(f_pcopy,"  allocate(tmp(mlst))")
                    nbwrite(f_pcopy,"  ")
                    klst = klst +1
                s =  "  call " + callname + "(" + "tmp(1:mlst)" + ",inum)"
                nbwrite(f_pcopy,s)
                s = "  " +  name_lst + "(mlst0:mlst0+mlst-1) = tmp(1:mlst)"
                nbwrite(f_pcopy,s)
                nbwrite(f_pcopy,"  tmp = zero")
            else:
                acall = str_1 + "call " + callname + args

            if type == "mib" or type == "mib_use":
                nbwrite(f_pcopy,"  do ib=1,nbeam")
                nbwrite(f_pcopy,"     if(lsbeama(ib).eq.lsbeam) then")
                nbwrite(f_pcopy,"        " + acall)
                if callname == "r8nz":
                    nbwrite(f_pcopy,"        if (inum.ne.0) then")
                    s = '           write(nonlin,*) &'
                    nbwrite(f_pcopy,s)
                    s = '"non-zero value in ' + arg1 + ' at ib=",ib'
                    nbwrite(f_pcopy,"               " + s)
                    nbwrite(f_pcopy,"        endif")
                nbwrite(f_pcopy,"     endif")
                nbwrite(f_pcopy,"  enddo")
            elif type == "mireact":
                nbwrite(f_pcopy,"  do ir=1,mireact")
                nbwrite(f_pcopy,"     if(lsbeamr(ir).eq.lsbeam) then")
                nbwrite(f_pcopy,"        " + acall)
                if callname == "r8nz":
                    nbwrite(f_pcopy,"        if (inum.ne.0) then")
                    s = '           write(nonlin,*) &'
                    nbwrite(f_pcopy,s)
                    s = '"non-zero value in ' + arg1 + ' at ir=",ir'
                    nbwrite(f_pcopy,"               " + s)
                    nbwrite(f_pcopy,"        endif")
                nbwrite(f_pcopy,"     endif")
                nbwrite(f_pcopy,"  enddo")
            else:
                if sect == "dpt" and callname == "r8get":
                    nbwrite(f_pcopy," ")
                elif sect == "lst" and callname == "r8get":
                    nbwrite(f_pcopy," ")
                else:
                    if callname != "r8get_dpt":
                       nbwrite(f_pcopy,"  " + acall)
                       if callname == "r8put" and sect == "dpt" :
                           idem_tr = arg1.split("1")
                           for itr in idem_tr:
                               if itr[0] != ":":
                                   name_tr = itr[0:-1]
                                   nbwrite(f_pcopy,"  deallocate("+name_tr+")")
                if callname == "r8nz":
                    nbwrite(f_pcopy,str_1 + "  if (inum.ne.0) then")
                    s = str_1 + '     write(nonlin,*) "non-zero value in '
                    s = s + arg1 + ' at lsbeam=",lsbeam'
                    nbwrite(f_pcopy,s)
                    nbwrite(f_pcopy,str_1 + "  endif")
                if arg1[0:5] == "svn3v":
                     nbwrite(f_pcopy,"  endif")



    if pll_section == "dpt" and callname == "r8get":
        nbwrite(f_pcopy,"  do isb=1,mibs_use")
        nbwrite(f_pcopy,"   iadr_empty(isb)=iadr_empty(isb)+mtrk_n(isb)")
        nbwrite(f_pcopy,"  enddo ")
        nbwrite(f_pcopy," enddo")
        nbwrite(f_pcopy," if(allocated(mtrk_n)) deallocate(mtrk_n)")
        nbwrite(f_pcopy," if(allocated(iadr_empty)) deallocate(iadr_empty)")
        nbwrite(f_pcopy," ierr = nf90_close( icdf)")
        nbwrite(f_pcopy," if(ierr.ne.0) then")
        nbwrite(f_pcopy,"   write(nonlin,*) ' ?"+subname+"_dpt: NETCDF close failure: ',trim(fname)")
        nbwrite(f_pcopy,"   return")
        nbwrite(f_pcopy," endif")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"contains ")
        nbwrite(f_pcopy,"  subroutine check(status,varnam)")
        nbwrite(f_pcopy,"    integer, intent ( in) :: status ")
        nbwrite(f_pcopy,"    character*(*),intent(in) :: varnam ! dimension name input ")
        nbwrite(f_pcopy," ")
        nbwrite(f_pcopy,"    if(status /= nf90_noerr) then ")
        nbwrite(f_pcopy,"       write(nonlin,*) ' ?"+subname+"_dpt error:'& ")
        nbwrite(f_pcopy,"      &// trim(nf90_strerror(status))//' for var.= '//trim(varnam) ")
        nbwrite(f_pcopy,"       call exit(status) ")
        nbwrite(f_pcopy,"    end if ")
        nbwrite(f_pcopy,"  end subroutine check ")
        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt," ierr = nf90_close( icdf)")
        nbwrite(f_wrdpt," if(ierr.ne.0) then")
        nbwrite(f_wrdpt,"   write(nonlin,*) ' ?nbi_wrdeptrk: NETCDF close failure: ',trim(fname)")
        nbwrite(f_wrdpt,"   return")
        nbwrite(f_wrdpt," endif")
        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt,"contains ")
        nbwrite(f_wrdpt,"  subroutine check(status,varnam)")
        nbwrite(f_wrdpt,"    integer, intent ( in) :: status ")
        nbwrite(f_wrdpt,"    character*(*),intent(in) :: varnam ! dimension name input ")
        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt,"    if(status /= nf90_noerr) then ")
        nbwrite(f_wrdpt,"       write(nonlin,*) ' ?nbi_wrdeptrk error:'& ")
        nbwrite(f_wrdpt,"      &// trim(nf90_strerror(status))//' for var.= '//trim(varnam) ")
        nbwrite(f_wrdpt,"       call exit(status) ")
        nbwrite(f_wrdpt,"    end if ")
        nbwrite(f_wrdpt,"  end subroutine check ")
        nbwrite(f_wrdpt," ")
        nbwrite(f_wrdpt,"end subroutine nbi_wrdeptrk ")

    elif pll_section == "lst" and callname == "r8get":
        nbwrite(f_pcopy,"  mlst0 = mlst0+mlst")
        nbwrite(f_pcopy," enddo")
    nbwrite(f_pcopy," ")

    if pll_section != "dpt" or (pll_section == "dpt" and (callname == "r8get" or callname == "r8put")):
        if subname == "nbi_zcheck":
            nbwrite(f_pcopy,"  nbuf_" + pll_section + " = nbuf_data")
        s = "end " + sname
        nbwrite(f_pcopy,s)
        nbwrite(f_pcopy," ")


    return 0

#--------------------------------------------------------------------
def nbigen_pcopy(msg):
    global nbi_pllinfo     # mpi_reduce pll buffer code generator info
    print(msg)

    pll_sections = []
    pll_work = []
    for item in nbi_pllinfo :
        name = item[0].lower().strip()
        dims = item[1]
        pll_section = item[2][0]
        idim = item[2][1]

        imatch = 0

        for old_section in pll_sections:
            if old_section == pll_section:
                imatch = 1

        if imatch == 0:
            pll_sections.append(pll_section)

        if idim == 0:
            type = ""
            workstr = "(" + name + ",inum)"
            if pll_section.lower() == "ntr":
                workstr_cx = name

        else:
            dimlist = dims[1:-1].split(",")
            ict = 0
            workstr = "(" + name + "("
            if pll_section.lower() == "ntr":
                workstr_cx = name+ "("
            for dimname1 in dimlist:
                ict = ict + 1
                dimname = dimname1.strip().lower()
                if ict == idim:
                    type = dimname
                    if dimname == "mibs" or dimname == "mibs_use" or dimname == "mtrk0":
                        if pll_section == "dpt":
                            if dimname == "mtrk0":
                                workstr = workstr + "1:mtrk0,"
                            else:
                                workstr = workstr + "1:mibs_use,"

                        else:
                            workstr = workstr + "lsbeam,"
                            if pll_section.lower() == "ntr":
                                workstr_cx = workstr_cx + "lsbeam,"
                    elif dimname == "mib" or dimname == "mib_use":
                        workstr = workstr + "ib,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + "ib,"
                    elif dimname == "mireact":
                        workstr = workstr + "ir,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + "ir,"
                    elif dimname == "mlost_data":
                        workstr = workstr + "1:mlost_data,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
                    else:
                        print(" ?? nbigen_pcopy: internal error")
                        raise nbigen_error
                else:
                    if dimname == "mig":
                        workstr = workstr + "1:ng,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
                    elif dimname == "mj":
                        workstr = workstr + "lcentr:lep1,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
                    elif dimname == "mibs":
                        workstr = workstr + "1:nsfast,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
                    elif dimname == "mib" or dimname == "mib_use":
                        workstr = workstr + "1:nbeam,"
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
                    else:
                        workstr = workstr + "1:" + dimname + ","
                        if pll_section.lower() == "ntr":
                            workstr_cx = workstr_cx + ":,"
            workstr = workstr[0:-1] + "),inum)"
            if pll_section.lower() == "ntr":
                workstr_cx = workstr_cx[0:-1] + ")"
                if type == "mib" or type == "mib_use":
                    nbwrite(f_cxnrm, "  do ib=1,nbeam")
                    nbwrite(f_cxnrm, "     if(lsbeama(ib).eq.lsbeam) then")
                    nbwrite(f_cxnrm, "        "+workstr_cx +" = "+workstr_cx +"*zcxnorm")
                    nbwrite(f_cxnrm, "     endif")
                    nbwrite(f_cxnrm, "  enddo")
                else:
                    nbwrite(f_cxnrm, "  "+workstr_cx +" = "+workstr_cx +"*zcxnorm")


        pll_work.append([pll_section,type,workstr])

    nbwrite(f_cxnrm,"  ")
    nbwrite(f_cxnrm,"end subroutine cxnrm")

    for pll_section in pll_sections:
        if pll_section.lower() != "dpt":
            write_pllsub(pll_section,"nbi_zcheck","r8nz",pll_work)
            write_pllsub(pll_section,"nbi_zzero","r8zero",pll_work)

        if pll_section.lower() == "orb":
            print("pll here")


        write_pllsub(pll_section,"nbi_pput","r8put",pll_work)
        write_pllsub(pll_section,"nbi_pget","r8get_dpt",pll_work)
        write_pllsub(pll_section,"nbi_pget","r8get",pll_work)


    return 0

#--------------------------------------------------------------------
def nbi_bogus():
    return 0
