C
C=======================================================================
C
      PROGRAM MODSRF
C for coverage of structural interfaces by polygons and for computation
C of 2-D slices through a model.
C
C Version: 5.30
C Date: 1999, May 23
C
C----------------------------------------------------------------------
C
C Structural interfaces:
C Program MODSRF covers structural interfaces by polygons composed
C of points with known cartesian coordinates. Structural interfaces
C are in MODEL package defined by implicit functions. This is very
C useful for computation purposes, but not very useful for
C visualization of models. For visualization purposes the interfaces
C must be expressed in explicit form, e.g. as sets of polygons
C composed of points with known coordinates.
C Method: The model is decomposed into a set of cubes given by input
C parameters Oi, Ni, Di. Points of intersections of cube edges with
C structural interfaces are computed together with points of
C intersection of structural edges with faces of the cubes. Points
C which belong to the same interface are then connected into
C polygons for each cube.
C This mode is started if all N1, N2, N3 are greater than 1.
C
C 2-D sections:
C If one of the values N1, N2, N3 equal 1, the 2-D sections are
C generated. Above mentioned points of intersection are computed
C along rectangles given by Oi, Ni, Di. Points which belong to the
C same complex block are then connected into polygons for each
C rectangle.
C
C
C Coded by Petr Bulant
C             Department of Geophysics, Charles University
C             Ke Karlovu 3,  121 16  Praha 2,  Czech Republic
C             E-mail: bulant@seis.karlov.mff.cuni.cz
C
C.......................................................................
C                                                    
C Description of input and output data:
C
C Main input data read from the * input device:
C     The data are read in by the list directed input (free format), by
C     a single READ statement.  The data consist of character strings
C     which have to be enclosed in apostrophes.  Note that the
C     interactive * external unit may be piped or redirected to a file.
C     The following items are read:
C (1) 'SEP' /
C     'SEP'..String in apostrophes containing the name of the main
C            input data file with parameters in the SEP format.
C            The parameters are: the filename of the data for the model,
C            dimensions of the grid of N1*N2*N3 gridpoints, the form
C            and names of the output files with points and polygons,
C            etc.
C     /...   It is recommended to terminate these data by a slash.
C     Default: 'SEP'='len-srf.h'.
C
C                                                     
C Input data file 'SEP':
C Data file 'SEP' has the form of the SEP (Stanford Exploration
C Project) parameter file:
C     All the data are specified in the form of PARAMETER=VALUE, e.g.
C     N1=50, with PARAMETER directly preceding = without intervening
C     spaces and with VALUE directly following = without intervening
C     spaces.  The PARAMETER=VALUE couple must be delimited by a space
C     or comma from both sides.
C     The PARAMETER string is not case-sensitive.
C     PARAMETER= followed by a space resets the default parameter value.
C     All other text in the input files is ignored.  The file thus may
C     contain unused data or comments without leading comment character.
C     Everything between comment character # and the end of the
C     respective line is ignored, too.
C     The PARAMETER=VALUE couples may be specified in any order.
C     The last appearance takes precedence.
C Data specifying the model by means of the MODEL package:
C     MODEL='string'... Name of the input file with the data specifying
C             the model.  Must be specified.
C             Description of MODEL.
C             Example of data set MODEL.
C             Default: MODEL=' '
C Parameters defining the basic regular rectangular grid:
C     N1=positive integer... Number of gridpoints of the basic grid
C             along the X1 axis.  Default: N1=1
C     N2=positive integer... Number of gridpoints of the basic grid
C             along the X2 axis.  Default: N2=1
C     N3=positive integer... Number of gridpoints of the basic grid
C             along the X3 axis.  Default: N3=1
C       The values of N1, N2, N3 also decide about the mode in which
C       MODSRF runs:
C         all of N1,N2,N3 greater 1: computation of polygons along
C                                    structural interfaces.
C         one of N1,N2,N3 equal 1: computation of polygons along
C                                  2-D section through the model.
C     O1=real... X1 coordinate of the origin of the grid. Default: O1=0.
C     O2=real... X2 coordinate of the origin of the grid. Default: O2=0.
C     O3=real... X3 coordinate of the origin of the grid. Default: O3=0.
C     D1=real... Grid spacing along the X1 axis.  Default: D1=1.
C     D2=real... Grid spacing along the X2 axis.  Default: D2=1.
C     D3=real... Grid spacing along the X3 axis.  Default: D3=1.
C       The grid intervals may also be negative.
C Names of the output files:
C     VRTX='string'... Name of the output file with vertices of the
C             polygons. Description of file VRTX.
C             Default: VRTX='vrtx.out'
C     PLGN='string'... Name of the output file describing the polygons.
C             Description of file PLGN.
C             Default: PLGN='plgn.out'
C     PLGNS='string'... Name of the file describing the polygons in
C             terms of the names of the vertices.
C             Description of file PLGNS.
C             Default: PLGNS=' '
C Parameters specifying the quantities to be written into the file VRTX.
C     TEXTP='string' ... First part of names of vertices. The second
C             part of the name of a vertex is formed by number giving
C             its position in the file VRTX.
C             Default: TEXTP='V'
C     COLUMN07 to COLUMN69, POWER07 to POWER69:
C     POWERii=real ... Power of the quantity to be written in column ii.
C     COLUMNii='string' ... String which specifies the quantity to be
C             written to the column ii of the file VRTX. First six
C             columns are reserved for coordinates of the vertices and
C             for the normals. Column zero is reserved for names of the
C             vertices. Following strings are allowed:
C             ' ' (a space) ... Nothing is to be written to the column
C                      ii and to all the following columns.
C             ISRF ... Index of the interface.
C             +ISB ... Index of simple block at positive side of the
C                      interface.
C             -ISB ... Index of simple block at negative side of the
C                      interface.
C             +ICB -ICB ... Index of complex block.
C             +VP  -VP  ... P-wave velocity.
C             +VS  -VS  ... S-wave velocity.
C             +DEN -DEN ... Density.
C             +QP  -QP  ... P wave loss factor.
C             +QS  -QS  ... S wave loss factor.
C             +A11 -A11 +A12 -A12 +A22 -A22 +A13 -A13 +A23 -A23
C             +A33 -A33 +A14 -A14 +A24 -A24 +A34 -A34 +A44 -A44
C             +A15 -A15 +A25 -A25 +A35 -A35 +A45 -A45 +A55 -A55
C             +A16 -A16 +A26 -A26 +A36 -A36 +A46 -A46 +A56 -A56
C             +A66 -A66 ... Reduced (i.e. divided by the density)
C               anisotropic elastic parameters
C               (components of the real part of the symmetric 6*6
C               stiffness matrix divided by the density).
C             +Q11 -Q11 +Q12 -Q12 +Q22 -Q22 +Q13 -Q13 +Q23 -Q23
C             +Q33 -Q33 +Q14 -Q14 +Q24 -Q24 +Q34 -Q34 +Q44 -Q44
C             +Q15 -Q15 +Q25 -Q25 +Q35 -Q35 +Q45 -Q45 +Q55 -Q55
C             +Q16 -Q16 +Q26 -Q26 +Q36 -Q36 +Q46 -Q46 +Q56 -Q56
C             +Q66 -Q66 ... Reduced (i.e. divided by the density)
C               imaginary anisotropic elastic parameters
C               (components of the imaginary part of the
C               symmetric 6*6 stiffness matrix divided by the density).
C             All strings may be entered either in uppercase or in
C             lowercase letters.
C             Default: COLUMN07='ISRF', COLUMN08 to COLUMN69=' ',
C                      POWER07 to POWER69=1.
C
C                                                    
C Output file VRTX with the vertices:
C (1) / ... a slash.
C (2) For each vertex data (2.1):
C (2.1) 'NAME',X1,X2,X3,Z1,Z2,Z3,/
C     'NAME'... Name of the vertex. See parameter TEXTP above.
C     X1,X2,X3... Coordinates of the vertex.
C     Z1,Z2,Z3... Normal to the interface or to the 2-D section at
C                 the vertex.
C     /...    None to several values terminated by a slash. See
C             parameters COLUMN07 to COLUMN69 above.
C (3) / ... a slash at the end of file.
C
C                                                    
C Output file PLGN with the polygons specified in terms of
C indices of vertices:
C (1) For each polygon data (1.1):
C (1.1) I1,I2,...,IN,/
C     I1,I2,...,IN... Indices of N vertices of the polygon.
C             The vertices in file VRTX are indexed by positive integers
C             according to their order.
C     /...    List of vertices is terminated by a slash.
C (2) / ... a slash at the end of file.
C
C                                                   
C Output file PLGNS with the polygons specified in terms of
C names of vertices. This enables vertices from several files
C to be combined in further application (the names of the vertices must
C differ, see the parameter TEXTP above).
C (1) For each polygon data (1.1):
C (1.1) 'VRTX1','VRTX2',...,'VRTXN',/
C     'VRTX1','VRTX2',...,'VRTXN'... Strings containing the names of N
C             vertices of the polygon.  The names correspond to the
C             names in file VRTX.
C     /...    List of vertices is terminated by a slash.
C (2) / ... a slash at the end of file.
C
C
C Subroutines and external functions required:
      EXTERNAL RKGS
      EXTERNAL FCTMS,OUTMS
      LOGICAL MSLPIF,MSLPIL
      EXTERNAL MSLPIF,MSLPIL
      INTEGER LENGTH
      EXTERNAL LENGTH
C
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Input and output data files:
      CHARACTER*80 FSEP,FMOD
      INTEGER LU,LU1,LU2
      PARAMETER (LU=1,LU1=1,LU2=2)
C     Auxiliary storage locations:
      INTEGER I1,I2,I3,I4,I5,I6,I7,J1,J2,J3,ITER,NPOINT,LEN1,LEN2,LENG
      INTEGER IL1,IL2,IL3,IL4,IF1,IF2,IF3,IF4,IF5,IF6
      INTEGER IX,IP1,IP2,ISHIFT
      INTEGER ISBOLD,ICBOLD,ISBNEW,ICBNEW,ISRF,ICBPOS,ICBNEG
      REAL X1,X2,X3,XX(3),Y1,Y2,Y3,YY(3)
      EQUIVALENCE (X1,XX(1)),(X2,XX(2)),(X3,XX(3))
      EQUIVALENCE (Y1,YY(1)),(Y2,YY(2)),(Y3,YY(3))
      REAL F(10)
      INTEGER IDUMMY(1),IY(8)
      REAL ERR,DUMMY(1),XOLD1,XOLD(3),DOLD(3),XNEW1,XNEW(3),DNEW(3),
     *     XTMP1,XTMP(3),DTMP(3),XINT1,XINT(3),DINT(3)
      REAL PRMT(5),AUX(8,3)
      INTEGER MJPT,NJPT
      PARAMETER (MJPT=8)
      INTEGER JPT(6,MJPT)
C     JPT(1 to 6,i) ... Points along the gridface: address of the point,
C       ICB,ISB,ISRF,ISB,ICB. JPT(1,i).LT.0 means that the point is
C       stored in reverse order than it is in IRAM.
      INTEGER MJCN,NJCN,NNJCN(0:7),MJSP,NJSP,
     * MJPOL,NJPOL,MLJPOL,NLJPOL,NIND
      PARAMETER (MJCN=50,MJSP=100,MJPOL=10,MLJPOL=10)
      INTEGER JCN(3,MJCN),JSP(3,MJSP),JPOL(0:MLJPOL,MJPOL),IND(MJCN)
C     JCN(1 to 3,i) ... Connection i of the face: address of the first
C       point, address of the second point, index of the interface.
C     NNJCN(1:7) ... Number of connections for first gridface, second
C     gridface, ... , sixth gridface, between edges.
C     JSP(1 to 3,i) ... Array of starting points as they go along
C       a polygon: previous point, point, following point.
C     JPOL(0,i) ... Number of points in polygon i.
C     JPOL(1 to JPOL(0,i),i) ... Points in the polygon.
      INTEGER MIPTE
      PARAMETER (MIPTE=5)
      INTEGER IPTE(MIPTE),NIPTE
C     IPTE(i) ... address of the point to be used as starting point
C       when searching for the edge. IPTE(i).LT.0 means that the point
C       is to be used in reverse order than it is stored in array IRAM.
      REAL Z(69),POWER(69),VP(10),VS(10),RHO,QP,QS,A(10,21),Q(21),
     *     OUTMIN,OUTMAX
      LOGICAL LCN
      CHARACTER*20 FORMAT,FORMA1,FORMA2,VRTX,PLGN,PLGNS,TEXTP,
     *             TEXTC(69)*4,TEXTS(MLJPOL)
C
C.......................................................................
C
C     Reading main input data:
      FSEP='len-srf.h'
      WRITE(*,'(A)')
     *' MODSRF: Enter the name of SEP parameter file: '
      READ (*,*) FSEP
      WRITE(*,'(A)')
     *'+MODSRF: Reading input data.                                   '

C     Reading all the data from file FSEP to the memory
C     (SEP parameter file form):
      CALL RSEP1(LU,FSEP)
C
C     Recalling the data specifying grid dimensions
C     (arguments: Name of value in input data, Variable, Default):
      CALL RSEP3I('N1',N1,1)
      CALL RSEP3I('N2',N2,1)
      CALL RSEP3I('N3',N3,1)
      CALL RSEP3R('O1',O1,0.)
      CALL RSEP3R('O2',O2,0.)
      CALL RSEP3R('O3',O3,0.)
      CALL RSEP3R('D1',D1,1.)
      CALL RSEP3R('D2',D2,1.)
      CALL RSEP3R('D3',D3,1.)
      IF (D1.LT.0.) THEN
        O1=O1+(N1-1)*D1
        D1=-D1
      ENDIF
      IF (D2.LT.0.) THEN
        O2=O2+(N2-1)*D2
        D2=-D2
      ENDIF
      IF (D3.LT.0.) THEN
        O3=O3+(N3-1)*D3
        D3=-D3
      ENDIF
      IF ((N1.LE.0).OR.(N2.LE.0).OR.(N3.LE.0).OR.
     *    ((D1.EQ.0.).AND.(N1.NE.1)).OR.
     *    ((D2.EQ.0.).AND.(N2.NE.1)).OR.
     *    ((D3.EQ.0.).AND.(N3.NE.1))) THEN
C       MODSRF-01
        CALL ERROR('MODSRF-01: Wrong specification of the grid.')
C       This specification of the grid may cause problems. Please,
C       specify D1,D2,D3 nonzero and N1,N2,N3 greater than 0. Di may
C       equal zero in case that corresponding Ni equals 1.
      ENDIF
C
C     Reading the data for the model:
      CALL RSEP3T('MODEL',FMOD,' ')
      OPEN(LU,FILE=FMOD,STATUS='OLD')
      CALL MODEL1(LU)
      CLOSE(LU)
C
C     Recalling the output filenames:
      CALL RSEP3T('VRTX',VRTX,'vrtx.out')
      CALL RSEP3T('PLGN',PLGN,'plgn.out')
      CALL RSEP3T('PLGNS',PLGNS,' ')
C
C     Recalling the first part of names of points in output file VRTX:
      CALL RSEP3T('TEXTP',TEXTP,'V')
C
C     Recalling the data specifying the quantities to be written into
C     the output file with points at structural interfaces:
      FORMA1='COLUMN00'
      FORMA2='POWER00'
      I1=7
   5  CONTINUE
        FORMA1(8:8)=CHAR(ICHAR('0')+MOD(I1,10))
        FORMA2(7:7)=CHAR(ICHAR('0')+MOD(I1,10))
        FORMA1(7:7)=CHAR(ICHAR('0')+I1/10)
        FORMA2(6:6)=CHAR(ICHAR('0')+I1/10)
        IF (I1.EQ.7) THEN
          CALL RSEP3T(FORMA1,TEXTC(7),'ISRF')
        ELSE
          CALL RSEP3T(FORMA1,TEXTC(I1),' ')
        ENDIF
        CALL RSEP3R(FORMA2,POWER(I1),1.)
        IF (TEXTC(I1).NE.' ') THEN
          CALL LOWER(TEXTC(I1))
          IF ((TEXTC(I1).NE.'isrf').AND.
     *        (TEXTC(I1).NE.'+isb').AND.(TEXTC(I1).NE.'-isb').AND.
     *        (TEXTC(I1).NE.'+icb').AND.(TEXTC(I1).NE.'-icb').AND.
     *        (TEXTC(I1).NE.'+vp') .AND.(TEXTC(I1).NE.'-vp') .AND.
     *        (TEXTC(I1).NE.'+vs') .AND.(TEXTC(I1).NE.'-vs') .AND.
     *        (TEXTC(I1).NE.'+den').AND.(TEXTC(I1).NE.'-den').AND.
     *        (TEXTC(I1).NE.'+qp') .AND.(TEXTC(I1).NE.'-qp') .AND.
     *        (TEXTC(I1).NE.'+qs') .AND.(TEXTC(I1).NE.'-qs') .AND.
     *        (TEXTC(I1).NE.'+a11').AND.(TEXTC(I1).NE.'-a11').AND.
     *        (TEXTC(I1).NE.'+a12').AND.(TEXTC(I1).NE.'-a12').AND.
     *        (TEXTC(I1).NE.'+a22').AND.(TEXTC(I1).NE.'-a22').AND.
     *        (TEXTC(I1).NE.'+a13').AND.(TEXTC(I1).NE.'-a13').AND.
     *        (TEXTC(I1).NE.'+a23').AND.(TEXTC(I1).NE.'-a23').AND.
     *        (TEXTC(I1).NE.'+a33').AND.(TEXTC(I1).NE.'-a33').AND.
     *        (TEXTC(I1).NE.'+a14').AND.(TEXTC(I1).NE.'-a14').AND.
     *        (TEXTC(I1).NE.'+a24').AND.(TEXTC(I1).NE.'-a24').AND.
     *        (TEXTC(I1).NE.'+a34').AND.(TEXTC(I1).NE.'-a34').AND.
     *        (TEXTC(I1).NE.'+a44').AND.(TEXTC(I1).NE.'-a44').AND.
     *        (TEXTC(I1).NE.'+a15').AND.(TEXTC(I1).NE.'-a15').AND.
     *        (TEXTC(I1).NE.'+a25').AND.(TEXTC(I1).NE.'-a25').AND.
     *        (TEXTC(I1).NE.'+a35').AND.(TEXTC(I1).NE.'-a35').AND.
     *        (TEXTC(I1).NE.'+a45').AND.(TEXTC(I1).NE.'-a45').AND.
     *        (TEXTC(I1).NE.'+a55').AND.(TEXTC(I1).NE.'-a55').AND.
     *        (TEXTC(I1).NE.'+a16').AND.(TEXTC(I1).NE.'-a16').AND.
     *        (TEXTC(I1).NE.'+a26').AND.(TEXTC(I1).NE.'-a26').AND.
     *        (TEXTC(I1).NE.'+a36').AND.(TEXTC(I1).NE.'-a36').AND.
     *        (TEXTC(I1).NE.'+a46').AND.(TEXTC(I1).NE.'-a46').AND.
     *        (TEXTC(I1).NE.'+a56').AND.(TEXTC(I1).NE.'-a56').AND.
     *        (TEXTC(I1).NE.'+a66').AND.(TEXTC(I1).NE.'-a66').AND.
     *        (TEXTC(I1).NE.'+q11').AND.(TEXTC(I1).NE.'-q11').AND.
     *        (TEXTC(I1).NE.'+q12').AND.(TEXTC(I1).NE.'-q12').AND.
     *        (TEXTC(I1).NE.'+q22').AND.(TEXTC(I1).NE.'-q22').AND.
     *        (TEXTC(I1).NE.'+q13').AND.(TEXTC(I1).NE.'-q13').AND.
     *        (TEXTC(I1).NE.'+q23').AND.(TEXTC(I1).NE.'-q23').AND.
     *        (TEXTC(I1).NE.'+q33').AND.(TEXTC(I1).NE.'-q33').AND.
     *        (TEXTC(I1).NE.'+q14').AND.(TEXTC(I1).NE.'-q14').AND.
     *        (TEXTC(I1).NE.'+q24').AND.(TEXTC(I1).NE.'-q24').AND.
     *        (TEXTC(I1).NE.'+q34').AND.(TEXTC(I1).NE.'-q34').AND.
     *        (TEXTC(I1).NE.'+q44').AND.(TEXTC(I1).NE.'-q44').AND.
     *        (TEXTC(I1).NE.'+q15').AND.(TEXTC(I1).NE.'-q15').AND.
     *        (TEXTC(I1).NE.'+q25').AND.(TEXTC(I1).NE.'-q25').AND.
     *        (TEXTC(I1).NE.'+q35').AND.(TEXTC(I1).NE.'-q35').AND.
     *        (TEXTC(I1).NE.'+q45').AND.(TEXTC(I1).NE.'-q45').AND.
     *        (TEXTC(I1).NE.'+q55').AND.(TEXTC(I1).NE.'-q55').AND.
     *        (TEXTC(I1).NE.'+q16').AND.(TEXTC(I1).NE.'-q16').AND.
     *        (TEXTC(I1).NE.'+q26').AND.(TEXTC(I1).NE.'-q26').AND.
     *        (TEXTC(I1).NE.'+q36').AND.(TEXTC(I1).NE.'-q36').AND.
     *        (TEXTC(I1).NE.'+q46').AND.(TEXTC(I1).NE.'-q46').AND.
     *        (TEXTC(I1).NE.'+q56').AND.(TEXTC(I1).NE.'-q56').AND.
     *        (TEXTC(I1).NE.'+q66').AND.(TEXTC(I1).NE.'-q66')) THEN
C           MODSRF-02
            CALL ERROR('MODSRF-02: Wrong value of COLUMN.')
C           See allowed values of COLUMNii in the
C           description of file SEP.
          ENDIF
          I1=I1+1
          IF (I1.GT.69) THEN
C           MODSRF-03
            CALL ERROR('MODSRF-03: More than 69 COLUMNs.')
C           Currently up to 69 values of COLUMNii may be specified.
C           See allowed values of COLUMNii in the
C           description of file SEP.
          ENDIF
          GOTO 5
        ENDIF
C     End of the loop over future columns of the output file.
C
C     Preparing numbers of gridpoints, gridlegs, gridfaces
C     and gridcubes:
      N11=N1-1
      N21=N2-1
      N1N2=   N1   * N2
      N11N2= (N1-1)* N2
      N1N21=  N1   *(N2-1)
      N11N21=(N1-1)*(N2-1)
      NGPS=N1*N2*N3
      OLEG=NGPS*2+1
      NLEG1=(N1-1)*N2*N3
      NLEG2=N1*(N2-1)*N3
      NLEG3=N1*N2*(N3-1)
      NLEG12=NLEG1+NLEG2
      NLEG =NLEG12+NLEG3
      OFAC=OLEG+NLEG+1
      NFAC1=N1*(N2-1)*(N3-1)
      NFAC2=(N1-1)*N2*(N3-1)
      NFAC3=(N1-1)*(N2-1)*N3
      NFAC12=NFAC1+NFAC2
      NFAC=NFAC12+NFAC3
      NCUB=(N1-1)*(N2-1)*(N3-1)
      OPOI=OFAC+NFAC
      NPOI=OPOI
      IF (NPOI.GT.MRAM) CALL MSEROR(1)
C
      DO 10, I1=1,OPOI
        IRAM(I1)=0
  10  CONTINUE
C
C
C     Loop along all gridpoints, recording indices of blocks:
      WRITE(*,'(A)')
     *'+MODSRF: Computing indices of blocks.                          '
      DO 13, I3=1,N3
        DO 12, I2=1,N2
          DO 11, I1=1,N1
            IX=(I3-1)*N1N2+(I2-1)*N1+I1
            IX=2*(IX-1)
            X1=O1+FLOAT(I1-1)*D1
            X2=O2+FLOAT(I2-1)*D2
            X3=O3+FLOAT(I3-1)*D3
            CALL BLOCK(XX,0,0,ISRF,ISBNEW,ICBNEW)
            IRAM(IX+1)=ISBNEW
            IRAM(IX+2)=ICBNEW
  11      CONTINUE
  12    CONTINUE
  13  CONTINUE
C
C
C     Loop along all gridlegs,
C     searching for intersections with structural interfaces:
      WRITE(*,'(A)')
     *'+MODSRF: Computing intersections along gridlegs.               '
C     Address of intersection points on gridleg 0:
      IRAM(OLEG)=NPOI
C     Index of coordinate in the direction of gridlegs:
      I4=1
C     Maximum alllowed error in the position of intersection point:
      ERR=0.001*D1
C     Auxiliary quantities:
      DOLD(1)=1.
      DOLD(2)=0.
      DOLD(3)=0.
      DNEW(1)=1.
      DNEW(2)=0.
      DNEW(3)=0.
      DTMP(1)=1.
      DTMP(2)=0.
      DTMP(3)=0.
      DO 29, I1=1,NLEG
        IF (I1.EQ.NLEG1+1) THEN
          I4=2
          ERR=0.001*D2
          DOLD(1)=0.
          DOLD(2)=1.
          DNEW(1)=0.
          DNEW(2)=1.
          DTMP(1)=0.
          DTMP(2)=1.
        ENDIF
        IF (I1.EQ.NLEG12+1) THEN
          I4=3
          ERR=0.001*D3
          DOLD(2)=0.
          DOLD(3)=1.
          DNEW(2)=0.
          DNEW(3)=1.
          DTMP(2)=0.
          DTMP(3)=1.
        ENDIF
        CALL MSGLEG(I1,IP1,IP2)
        ISBOLD=IRAM(2*(IP1-1)+1)
        ISBNEW=IRAM(2*(IP2-1)+1)
        IF (ISBOLD.NE.ISBNEW) THEN
C         The points of the gridleg are in different simple blocks:
          ICBOLD=IRAM(2*(IP1-1)+2)
          ICBNEW=IRAM(2*(IP2-1)+2)
          CALL MSCP(IP1,XOLD(1),XOLD(2),XOLD(3))
          CALL MSCP(IP2,XNEW(1),XNEW(2),XNEW(3))
          XTMP(1)=XNEW(1)
          XTMP(2)=XNEW(2)
          XTMP(3)=XNEW(3)
C         Loop for intersection points along the gridleg:
          ITER=0
  21      CONTINUE
            ITER=ITER+1
            IF (ITER.GT.100) THEN
C             MODSRF-04
              CALL ERROR ('MODSRF-04: More than 100 intersections.')
C             More than 100 points of intersection of the
C             gridline element with the structural interfaces.
C             Check the input data and then contact the author.
            ENDIF
C
C           Determining the interface between points XOLD, XNEW:
            IY(4)=ISBOLD
            IY(5)=ICBOLD
            IY(6)=0
            XTMP(I4)=XNEW(I4)
            XOLD1=XOLD(I4)
            XNEW1=XNEW(I4)
            XTMP1=XNEW1
            CALL CDE(0,0,IDUMMY,0,IDUMMY,DUMMY,1,3,3,IY,ERR,
     *               XOLD1,XOLD1,XOLD,DOLD,XNEW1,XNEW,DNEW,
     *                     XTMP1,XTMP,DTMP,XINT1,XINT,DINT)
            IF ((ICBOLD.NE.ICBNEW).AND.(IY(6).EQ.0)) THEN
C             The interface was not found between the points with
C             different ICB. This may happen when the NEW point is
C             situated directly at the interface.
C             Repeating the search in reverse direction:
              DOLD(I4)=-DOLD(I4)
              DNEW(I4)=-DNEW(I4)
              DTMP(I4)=-DTMP(I4)
              XTMP1=XOLD1
              XTMP(1)=XOLD(1)
              XTMP(2)=XOLD(2)
              XTMP(3)=XOLD(3)
              IY(4)=ISBNEW
              IY(5)=ICBNEW
              CALL CDE(0,0,IDUMMY,0,IDUMMY,DUMMY,1,3,3,IY,ERR,
     *               (XTMP1-ERR),XNEW1,XNEW,DNEW,XOLD1,XOLD,DOLD,
     *                     XTMP1,XTMP,DTMP,XINT1,XINT,DINT)
              IF (IY(6).EQ.0) THEN
C               The interface was not found even in reverse direction.
C               This may happen when the whole gridleg coincides with an
C               interface:
                CALL BLOCK(XOLD,0,ISBOLD,IDUMMY,IB,IDUMMY)
                IF (IB.NE.ISBOLD) CALL MSEROR(8)
                CALL BLOCK(XOLD,0,ISBNEW,IDUMMY,IB,IDUMMY)
                IF (IB.NE.ISBNEW) CALL MSEROR(8)
                CALL BLOCK(XNEW,0,ISBNEW,IDUMMY,IB,IDUMMY)
                IF (IB.NE.ISBNEW) CALL MSEROR(8)
                CALL BLOCK(XNEW,0,ISBOLD,IDUMMY,IB,IDUMMY)
                IF (IB.NE.ISBOLD) CALL MSEROR(8)
C               Whole gridleg coincides with an interface:
                CALL SEPAR(ISBNEW,ISBOLD,IDUMMY,IY(6))
                IF (IDUMMY(1).LT.1) CALL MSEROR(8)
                IY(7)=ISBOLD
                IY(8)=ICBOLD
              ENDIF
              IF (IY(8).NE.ICBOLD) THEN
C               There should be only one interface between the points.
C               
C               MODSRF-06
                CALL ERROR('MODSRF-06: More than one interface.')
C               This error should not appear. Contact the author.
              ENDIF
C             Reverting the points to the original order:
              DOLD(I4)=-DOLD(I4)
              DNEW(I4)=-DNEW(I4)
              DTMP(I4)=-DTMP(I4)
              XTMP1=XNEW1
              XTMP(1)=XNEW(1)
              XTMP(2)=XNEW(2)
              XTMP(3)=XNEW(3)
              ISBOLD=IY(7)
              ICBOLD=IY(8)
              ISBNEW=IY(4)
              ICBNEW=IY(5)
              IY(4)=ISBOLD
              IY(5)=ICBOLD
              IY(6)=-IY(6)
              IY(7)=ISBNEW
              IY(8)=ICBNEW
            ENDIF
            IF (IY(6).NE.0) THEN
C             Structural interface, recording the point of intersection:
C             XINT is the point of intersection with the interface,
C             IY(4) and IY(5) are the indices of the simple block
C             and the complex block before the interface,
C             IY(6) is the index of the interface, IY(7) and IY(8) are
C             the indices of the simple block and the complex block
C             behind the interface:
              IF (.NOT.MSLPIL(XINT,I1)) THEN
C               MODSRF-07
                CALL ERROR('MODSRF-07: Point not on the gridleg.')
C               This error should not appear. Contact the author.
              ENDIF
              IF (NPOI+NQPOI.GT.MRAM) CALL MSEROR(1)
              RAM(NPOI+1)=XINT(1)
              RAM(NPOI+2)=XINT(2)
              RAM(NPOI+3)=XINT(3)
              IRAM(NPOI+4)=IY(5)
              IRAM(NPOI+5)=IY(4)
              IRAM(NPOI+6)=IY(6)
              IRAM(NPOI+7)=IY(7)
              IRAM(NPOI+8)=IY(8)
              NPOI=NPOI+NQPOI
              IF (IY(7).NE.ISBNEW) THEN
C               IY(7) is the index of simple block behind the interface,
C               the search for intersection points must continue.
C               Shifting point XOLD to the point of intersection:
                XOLD(I4)=XINT(I4)
                XOLD1=XOLD(I4)
                ISBOLD=IY(7)
                ICBOLD=IY(8)
                GOTO 21
              ENDIF
            ENDIF
C         End of the loop for intersection points along the gridleg.
        ENDIF
        IRAM(OLEG+I1)=NPOI
  29  CONTINUE
      NPOIL=NPOI
C
C
C     Loop along all gridfaces,
C     connecting the points of intersection of structural interfaces
C     with gridlegs, if necessary computing points of intersection
C     of structural edges with gridfaces.
      WRITE(*,'(A)')
     *'+MODSRF: Connecting points along gridfaces.                     '
      IF (NCUB.NE.0) THEN
        OCON=NPOI+(NPOI-OPOI)/2
      ELSE
        OCON=NPOI + (NPOI-OPOI)*3 + NGPS*NQPOI
      ENDIF
      NCON=OCON
      IF (NCON.GT.MRAM) CALL MSEROR(1)
C     Initialization for RKGS:
      PRMT(1)=0.
      PRMT(2)=(D1+D2+D3)
      PRMT(3)=PRMT(2)/30.
      PRMT(4)=PRMT(3)/100.
      DTMP(1)=1./3.
      DTMP(2)=DTMP(1)
      DTMP(3)=DTMP(1)
C     Address of connections on gridface 0:
      IRAM(OFAC)=NCON
      DO 49, I1=1,NFAC
C       Indices of gridlegs of the gridface:
        CALL MSGFAC(I1,IL1,IL2,IL3,IL4)
C
C       Forming array with intersection points for the gridface:
        NJPT=0
        DO 31, I2=IRAM(OLEG+IL1-1),IRAM(OLEG+IL1)-NQPOI,NQPOI
C         I2 points to the start of records for intersection point.
          NJPT=NJPT+1
          IF (NJPT.GT.MJPT) CALL MSEROR(2)
          JPT(1,NJPT)=I2+NQPOI
          JPT(2,NJPT)=IRAM(I2+4)
          JPT(3,NJPT)=IRAM(I2+5)
          JPT(4,NJPT)=IRAM(I2+6)
          JPT(5,NJPT)=IRAM(I2+7)
          JPT(6,NJPT)=IRAM(I2+8)
  31    CONTINUE
        DO 32, I2=IRAM(OLEG+IL2-1),IRAM(OLEG+IL2)-NQPOI,NQPOI
C         I2 points to the start of records for intersection point.
          NJPT=NJPT+1
          IF (NJPT.GT.MJPT) CALL MSEROR(2)
          JPT(1,NJPT)=I2+NQPOI
          JPT(2,NJPT)=IRAM(I2+4)
          JPT(3,NJPT)=IRAM(I2+5)
          JPT(4,NJPT)=IRAM(I2+6)
          JPT(5,NJPT)=IRAM(I2+7)
          JPT(6,NJPT)=IRAM(I2+8)
  32    CONTINUE
        DO 33, I2=IRAM(OLEG+IL3)-NQPOI,IRAM(OLEG+IL3-1),-NQPOI
C         I2 points to the start of records for intersection point.
          NJPT=NJPT+1
          IF (NJPT.GT.MJPT) CALL MSEROR(2)
          JPT(1,NJPT)=-(I2+NQPOI)
          JPT(2,NJPT)=IRAM(I2+8)
          JPT(3,NJPT)=IRAM(I2+7)
          JPT(4,NJPT)=-IRAM(I2+6)
          JPT(5,NJPT)=IRAM(I2+5)
          JPT(6,NJPT)=IRAM(I2+4)
  33    CONTINUE
        DO 34, I2=IRAM(OLEG+IL4)-NQPOI,IRAM(OLEG+IL4-1),-NQPOI
C         I2 points to the start of records for intersection point.
          NJPT=NJPT+1
          IF (NJPT.GT.MJPT) CALL MSEROR(2)
          JPT(1,NJPT)=-(I2+NQPOI)
          JPT(2,NJPT)=IRAM(I2+8)
          JPT(3,NJPT)=IRAM(I2+7)
          JPT(4,NJPT)=-IRAM(I2+6)
          JPT(5,NJPT)=IRAM(I2+5)
          JPT(6,NJPT)=IRAM(I2+4)
  34    CONTINUE
C
C       Making connections between points of the gridface:
        DO 46, I2=1,NJPT
          DO 36, I3=I2+1,NJPT
            IF ((JPT(2,I2).EQ.JPT(6,I3)).AND.
     *          (JPT(6,I2).EQ.JPT(2,I3))) THEN
C             Same indices of complex blocks:
              IF (IABS(JPT(4,I2)).EQ.IABS(JPT(4,I3))) THEN
C               Same interface - connection found:
                IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                IF (JPT(4,I2).LT.0) THEN
                  IRAM(NCON+1)=IABS(JPT(1,I2))
                  IRAM(NCON+2)=IABS(JPT(1,I3))
                  IRAM(NCON+3)=JPT(4,I2)
                  NCON=NCON+3
                ELSE
                  IRAM(NCON+1)=IABS(JPT(1,I3))
                  IRAM(NCON+2)=IABS(JPT(1,I2))
                  IRAM(NCON+3)=JPT(4,I3)
                  NCON=NCON+3
                ENDIF
                GOTO 45
              ENDIF
            ENDIF
  36      CONTINUE
          DO 37, I3=IRAM(OFAC+I1-1),NCON-3,3
            IF ((IRAM(I3+1).EQ.IABS(JPT(1,I2))).OR.
     *          (IRAM(I3+2).EQ.IABS(JPT(1,I2))))
C             The point I2 is already connected:
     *        GOTO 45
  37      CONTINUE
C         Point I2 is not connected, looking for point of intersection
C         of structural edges with gridface. (Following the intersection
C         of the interface with the gridface to the edge.)
          IFACE=I1
          IPTE(1)=JPT(1,I2)
          NIPTE=1
C         Loop for identification of all edges connected with point I2:
  39      CONTINUE
C           Initiating the search for the edge:
            I3=IABS(IPTE(NIPTE))-NQPOI
            X1=    RAM(I3+1)
            X2=    RAM(I3+2)
            X3=    RAM(I3+3)
            IF (IPTE(NIPTE).LT.0) THEN
              ICBO1=IRAM(I3+8)
              ISBO1=IRAM(I3+7)
              ISRFO=-IRAM(I3+6)
              ISBO2=IRAM(I3+5)
              ICBO2=IRAM(I3+4)
            ELSE
              ICBO1=IRAM(I3+4)
              ISBO1=IRAM(I3+5)
              ISRFO=IRAM(I3+6)
              ISBO2=IRAM(I3+7)
              ICBO2=IRAM(I3+8)
            ENDIF
            NIPTE=NIPTE-1
C           Computing the point of intersection of the edge
C           with the gridface:
            CALL RKGS(PRMT,XX,DTMP,3,I7,FCTMS,OUTMS,AUX)
            IF (PRMT(5).NE.1.) THEN
C             MODSRF-08
              CALL ERROR('MODSRF-08: PRMT(5) not equal to 1.')
C             This error should not appear. Contact the author.
            ENDIF
            IF (.NOT.MSLPIF(XX,IFACE)) THEN
C             MODSRF-09
              CALL ERROR('MODSRF-09: Point outside the gridface.')
C             This error should not appear. Contact the author.
            ENDIF
C           Storing the first point on the edge:
            IF (NPOI+NQPOI.GT.OCON) CALL MSEROR(1)
            RAM(NPOI+1)=X1
            RAM(NPOI+2)=X2
            RAM(NPOI+3)=X3
            IRAM(NPOI+4)=ICBO1
            IRAM(NPOI+5)=ISBO1
            IRAM(NPOI+6)=ISRFO
            IRAM(NPOI+7)=ISBO2
            IRAM(NPOI+8)=ICBO2
            NPOI=NPOI+NQPOI
            J1=NPOI
C           Recording the connection:
            IF (NCON+3.GT.MRAM) CALL MSEROR(1)
            IF (ISRFO.LT.0) THEN
              IRAM(NCON+1)=IABS(IPTE(NIPTE+1))
              IRAM(NCON+2)=NPOI
              IRAM(NCON+3)=ISRFO
            ELSE
              IRAM(NCON+1)=NPOI
              IRAM(NCON+2)=IABS(IPTE(NIPTE+1))
              IRAM(NCON+3)=-ISRFO
            ENDIF
            NCON=NCON+3
C
            IF (ICBO1.NE.ICBN1) THEN
C             Storing the second point on the edge:
              IF (NPOI+NQPOI.GT.OCON) CALL MSEROR(1)
              RAM(NPOI+1)=X1
              RAM(NPOI+2)=X2
              RAM(NPOI+3)=X3
              IRAM(NPOI+4)=ICBN1
              IRAM(NPOI+5)=ISBN1
              IRAM(NPOI+6)=-ISRFN1
              IRAM(NPOI+7)=ISBO1
              IRAM(NPOI+8)=ICBO1
              NPOI=NPOI+NQPOI
              IF (NCUB.EQ.0) THEN
C               'Connection' between first and second point on the edge:
                IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                J2=NPOI-NQPOI
                IF (IRAM(J2-NQPOI+6).LT.0) J2=-J2
                J3=NPOI
                IF (IRAM(J3-NQPOI+6).GT.0) J3=-J3
                IRAM(NCON+1)=J2
                IRAM(NCON+2)=J3
                IRAM(NCON+3)=0
                NCON=NCON+3
              ENDIF
              DO 40, I3=1,NJPT
                IF ((ICBN1.EQ.JPT(2,I3)).AND.
     *              (ISBN1.EQ.JPT(3,I3)).AND.
     *              (ISBO1.EQ.JPT(5,I3)).AND.
     *              (ICBO1.EQ.JPT(6,I3)).AND.
     *              (IABS(ISRFN1).EQ.IABS(JPT(4,I3)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (JPT(4,I3).LT.0) THEN
                    IRAM(NCON+1)=IABS(JPT(1,I3))
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=JPT(4,I3)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=IABS(JPT(1,I3))
                    IRAM(NCON+3)=-JPT(4,I3)
                  ENDIF
                  NCON=NCON+3
                  GOTO 405
                ENDIF
  40          CONTINUE
              DO 401, I3=1,NIPTE
                I4=IABS(IPTE(I3))-NQPOI
                IF ((ICBN1.EQ.IRAM(I4+8)).AND.
     *              (ISBN1.EQ.IRAM(I4+7)).AND.
     *              (ISBO1.EQ.IRAM(I4+5)).AND.
     *              (ICBO1.EQ.IRAM(I4+4)).AND.
     *              (IABS(ISRFN1).EQ.IABS(IRAM(I4+6)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (IRAM(I4+6).LT.0) THEN
                    IRAM(NCON+1)=I4+NQPOI
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=IRAM(I4+6)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=I4+NQPOI
                    IRAM(NCON+3)=-IRAM(I4+6)
                  ENDIF
                  NCON=NCON+3
                  GOTO 405
                ENDIF
  401         CONTINUE
C             More than one edge, current point will become a starting
C             point of the search for new edge:
              NIPTE=NIPTE+1
              IF (NIPTE.GT.MIPTE) CALL MSEROR(3)
              IPTE(NIPTE)=-NPOI
  405         CONTINUE
            ENDIF
C
            IF (ICBN2.NE.ICBN1) THEN
C             Storing the third point on the edge:
              IF (NPOI+NQPOI.GT.OCON) CALL MSEROR(1)
              RAM(NPOI+1)=X1
              RAM(NPOI+2)=X2
              RAM(NPOI+3)=X3
              IRAM(NPOI+4)=ICBN2
              IRAM(NPOI+5)=ISBN2
              IRAM(NPOI+6)=-ISRFO
              IRAM(NPOI+7)=ISBN1
              IRAM(NPOI+8)=ICBN1
              NPOI=NPOI+NQPOI
              IF (NCUB.EQ.0) THEN
C               'Connection' between second and third point on the edge:
                IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                J2=NPOI-NQPOI
                IF (IRAM(J2-NQPOI+6).LT.0) J2=-J2
                J3=NPOI
                IF (IRAM(J3-NQPOI+6).GT.0) J3=-J3
                IRAM(NCON+1)=J2
                IRAM(NCON+2)=J3
                IRAM(NCON+3)=0
                NCON=NCON+3
              ENDIF
              DO 42, I3=1,NJPT
                IF ((ICBN2.EQ.JPT(2,I3)).AND.
     *              (ISBN2.EQ.JPT(3,I3)).AND.
     *              (ISBN1.EQ.JPT(5,I3)).AND.
     *              (ICBN1.EQ.JPT(6,I3)).AND.
     *              (IABS(ISRFO).EQ.IABS(JPT(4,I3)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (JPT(4,I3).LT.0) THEN
                    IRAM(NCON+1)=IABS(JPT(1,I3))
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=JPT(4,I3)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=IABS(JPT(1,I3))
                    IRAM(NCON+3)=-JPT(4,I3)
                  ENDIF
                  NCON=NCON+3
                  GOTO 425
                ENDIF
  42          CONTINUE
              DO 421, I3=1,NIPTE
                I4=IABS(IPTE(I3))-NQPOI
                IF ((ICBN2.EQ.IRAM(I4+8)).AND.
     *              (ISBN2.EQ.IRAM(I4+7)).AND.
     *              (ISBN1.EQ.IRAM(I4+5)).AND.
     *              (ICBN1.EQ.IRAM(I4+4)).AND.
     *              (IABS(ISRFO).EQ.IABS(IRAM(I4+6)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (IRAM(I4+6).LT.0) THEN
                    IRAM(NCON+1)=I4+NQPOI
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=IRAM(I4+6)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=I4+NQPOI
                    IRAM(NCON+3)=-IRAM(I4+6)
                  ENDIF
                  NCON=NCON+3
                  GOTO 425
                ENDIF
  421         CONTINUE
C             More than one edge, current point will become a starting
C             point of the search for new edge:
              NIPTE=NIPTE+1
              IF (NIPTE.GT.MIPTE) CALL MSEROR(3)
              IPTE(NIPTE)=-NPOI
  425         CONTINUE
            ENDIF
C
            IF (ICBO2.NE.ICBN2) THEN
C             Storing the fourth point on the edge:
              IF (NPOI+NQPOI.GT.OCON) CALL MSEROR(1)
              RAM(NPOI+1)=X1
              RAM(NPOI+2)=X2
              RAM(NPOI+3)=X3
              IRAM(NPOI+4)=ICBO2
              IRAM(NPOI+5)=ISBO2
              IRAM(NPOI+6)=ISRFN2
              IRAM(NPOI+7)=ISBN2
              IRAM(NPOI+8)=ICBN2
              NPOI=NPOI+NQPOI
              IF (NCUB.EQ.0) THEN
C               'Connection' between third and fourth point on the edge:
                IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                J2=NPOI-NQPOI
                IF (IRAM(J2-NQPOI+6).LT.0) J2=-J2
                J3=NPOI
                IF (IRAM(J3-NQPOI+6).GT.0) J3=-J3
                IRAM(NCON+1)=J2
                IRAM(NCON+2)=J3
                IRAM(NCON+3)=0
                NCON=NCON+3
              ENDIF
              DO 41, I3=1,NJPT
                IF ((ICBO2.EQ.JPT(2,I3)).AND.
     *              (ISBO2.EQ.JPT(3,I3)).AND.
     *              (ISBN2.EQ.JPT(5,I3)).AND.
     *              (ICBN2.EQ.JPT(6,I3)).AND.
     *              (IABS(ISRFN2).EQ.IABS(JPT(4,I3)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (JPT(4,I3).LT.0) THEN
                    IRAM(NCON+1)=IABS(JPT(1,I3))
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=JPT(4,I3)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=IABS(JPT(1,I3))
                    IRAM(NCON+3)=-JPT(4,I3)
                  ENDIF
                  NCON=NCON+3
                  GOTO 415
                ENDIF
  41          CONTINUE
              DO 411, I3=1,NIPTE
                I4=IABS(IPTE(I3))-NQPOI
                IF ((ICBO2.EQ.IRAM(I4+8)).AND.
     *              (ISBO2.EQ.IRAM(I4+7)).AND.
     *              (ISBN2.EQ.IRAM(I4+5)).AND.
     *              (ICBN2.EQ.IRAM(I4+4)).AND.
     *              (IABS(ISRFN2).EQ.IABS(IRAM(I4+6)))) THEN
C                 Recording the connection:
                  IF (NCON+3.GT.MRAM) CALL MSEROR(1)
                  IF (IRAM(I4+6).LT.0) THEN
                    IRAM(NCON+1)=I4+NQPOI
                    IRAM(NCON+2)=NPOI
                    IRAM(NCON+3)=IRAM(I4+6)
                  ELSE
                    IRAM(NCON+1)=NPOI
                    IRAM(NCON+2)=I4+NQPOI
                    IRAM(NCON+3)=-IRAM(I4+6)
                  ENDIF
                  NCON=NCON+3
                  GOTO 415
                ENDIF
  411         CONTINUE
C             More than one edge, current point will become a starting
C             point of the search for new edge:
              NIPTE=NIPTE+1
              IF (NIPTE.GT.MIPTE) CALL MSEROR(3)
              IPTE(NIPTE)=-NPOI
  415         CONTINUE
            ENDIF
C
            IF (NCUB.EQ.0) THEN
C             'Connection' between fourth and first point on the edge:
              IF (NCON+3.GT.MRAM) CALL MSEROR(1)
              J2=NPOI
              IF (IRAM(J2-NQPOI+6).LT.0) J2=-J2
              J3=J1
              IF (IRAM(J3-NQPOI+6).GT.0) J3=-J3
              IRAM(NCON+1)=J2
              IRAM(NCON+2)=J3
              IRAM(NCON+3)=0
              NCON=NCON+3
            ENDIF
          IF (NIPTE.GE.1)
C           Continuing with the search for next edge:
     *      GOTO 39
C
C         No more edges, the point is connected.
  45      CONTINUE
C         Continuing with next point of the gridface:
  46    CONTINUE
        IRAM(OFAC+I1)=NCON
  49  CONTINUE
      NPOIE=NPOI
C
C
      IF (NCUB.NE.0) THEN
C       Loop along all gridcubes,
C       merging the connections between the points on structural
C       interfaces into polygons approximating the interfaces.
        WRITE(*,'(A)')
     *'+MODSRF: Making polygons approximating the interfaces.          '
        NPOL=MRAM+1
        DO 100, I1=1,NCUB
C         Indices of gridfaces of the gridcube:
          CALL MSGCUB(I1,IF1,IF2,IF3,IF4,IF5,IF6)
C
C         Forming array with connections for the gridcube:
          NJCN=0
          NNJCN(0)=NJCN
          DO 51, I2=IRAM(OFAC+IF1-1),IRAM(OFAC+IF1)-3,3
C           Connections of the gridface IF1:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+1)
            JCN(2,NJCN)=IRAM(I2+2)
            JCN(3,NJCN)=IRAM(I2+3)
  51      CONTINUE
          NNJCN(1)=NJCN
          DO 52, I2=IRAM(OFAC+IF2-1),IRAM(OFAC+IF2)-3,3
C           Connections of the gridface IF2:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+1)
            JCN(2,NJCN)=IRAM(I2+2)
            JCN(3,NJCN)=IRAM(I2+3)
  52      CONTINUE
          NNJCN(2)=NJCN
          DO 53, I2=IRAM(OFAC+IF3-1),IRAM(OFAC+IF3)-3,3
C           Connections of the gridface IF3:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+1)
            JCN(2,NJCN)=IRAM(I2+2)
            JCN(3,NJCN)=IRAM(I2+3)
  53      CONTINUE
          NNJCN(3)=NJCN
          DO 54, I2=IRAM(OFAC+IF4-1),IRAM(OFAC+IF4)-3,3
C           Connections of the gridface IF4:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+2)
            JCN(2,NJCN)=IRAM(I2+1)
            JCN(3,NJCN)=IRAM(I2+3)
  54      CONTINUE
          NNJCN(4)=NJCN
          DO 55, I2=IRAM(OFAC+IF5-1),IRAM(OFAC+IF5)-3,3
C           Connections of the gridface IF5:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+2)
            JCN(2,NJCN)=IRAM(I2+1)
            JCN(3,NJCN)=IRAM(I2+3)
  55      CONTINUE
          NNJCN(5)=NJCN
          DO 56, I2=IRAM(OFAC+IF6-1),IRAM(OFAC+IF6)-3,3
C           Connections of the gridface IF6:
            NJCN=NJCN+1
            IF (NJCN.GT.MJCN) CALL MSEROR(4)
            JCN(1,NJCN)=IRAM(I2+2)
            JCN(2,NJCN)=IRAM(I2+1)
            JCN(3,NJCN)=IRAM(I2+3)
  56      CONTINUE
          NNJCN(6)=NJCN
          DO 58, I2=1,NNJCN(6)
C           Connections between points on edges:
            IF (JCN(2,I2).GT.NPOIL) THEN
              ICBO1=IRAM(JCN(2,I2)-NQPOI+4)
              ICBO2=IRAM(JCN(2,I2)-NQPOI+8)
              LCN=.FALSE.
              DO 57, I3=1,NNJCN(6)
                IF (I3.NE.I2) THEN
                  IF ((JCN(1,I3).GT.NPOIL).AND.
     *                (IABS(JCN(3,I2)).EQ.IABS(JCN(3,I3)))) THEN
                    ICBN1=IRAM(JCN(1,I3)-NQPOI+4)
                    ICBN2=IRAM(JCN(1,I3)-NQPOI+8)
                    IF (((ICBO1.EQ.ICBN1).AND.(ICBO2.EQ.ICBN2)).OR.
     *                  ((ICBO2.EQ.ICBN1).AND.(ICBO1.EQ.ICBN2))) THEN
                      NJCN=NJCN+1
                      IF (NJCN.GT.MJCN) CALL MSEROR(4)
                      JCN(1,NJCN)=JCN(2,I2)
                      JCN(2,NJCN)=JCN(1,I3)
                      JCN(3,NJCN)=JCN(3,I3)
                      LCN=.TRUE.
                    ENDIF
                  ENDIF
                ENDIF
  57          CONTINUE
              IF (.NOT.LCN) THEN
C               Connection for edge not found, this connection is to be
C               canceled by means of creation of linear 'triangle':
                NJCN=NJCN+1
                IF (NJCN.GT.MJCN) CALL MSEROR(4)
                JCN(1,NJCN)=JCN(2,I2)
                JCN(2,NJCN)=JCN(1,I2)
                JCN(3,NJCN)=JCN(3,I2)
              ENDIF
            ENDIF
  58      CONTINUE
          NNJCN(7)=NJCN
C
C         Forming array with starting points
C         (from point, point, to point)
          NJSP=0
          DO 60, I2=1,NJCN
            DO 59, I3=1,NJCN
              IF ((JCN(2,I2).EQ.JCN(1,I3)).AND.
     *            (JCN(2,I3).NE.JCN(1,I2))) THEN
                NJSP=NJSP+1
                IF (NJSP.GT.MJSP) CALL MSEROR(5)
                JSP(1,NJSP)=JCN(1,I2)
                JSP(2,NJSP)=JCN(2,I2)
                JSP(3,NJSP)=JCN(2,I3)
              ENDIF
  59        CONTINUE
  60      CONTINUE
C
C         Looking for polygons on the faces of the cube.
          NJPOL=0
C         Loop for faces of the cube:
          DO 70, I2=1,6
C           Initiating indices of connections:
            DO 61, I3=1,MJCN
              IND(I3)=0
  61        CONTINUE
            NIND=NNJCN(I2)-NNJCN(I2-1)
C           Loop along connections:
            I3=1
  62        CONTINUE
              IF (NJPOL+1.GT.MJPOL) CALL MSEROR(6)
C             Search for first unused connection:
              IF (I3.LE.NIND-2) THEN
                IF (IND(I3).GE.0) THEN
C                 Unused connection, recording first two points
C                 of the polygon:
                  NLJPOL=2
                  JPOL(1,NJPOL+1)=JCN(1,NNJCN(I2-1)+I3)
                  JPOL(2,NJPOL+1)=JCN(2,NNJCN(I2-1)+I3)
                  IND(I3)=-1
                ELSE
                  I3=I3+1
                  GOTO 62
                ENDIF
C               Search for next point of polygon:
  63            CONTINUE
                DO 69, I4=I3+1,NIND
                  IF ( JCN(1,NNJCN(I2-1)+I4)       .EQ.
     *                 JPOL(NLJPOL,NJPOL+1) ) THEN
C                   Recording next point of polygon:
                    NLJPOL=NLJPOL+1
                    IF (NLJPOL.GT.MLJPOL) CALL MSEROR(7)
                    JPOL(NLJPOL,NJPOL+1)=JCN(2,NNJCN(I2-1)+I4)
                    IND(I4)=-1
                    DO 68, I5=NLJPOL-3,1,-1
C                     Examining whether the polygon is closed:
                      IF (JPOL(I5,NJPOL+1).EQ.JPOL(NLJPOL,NJPOL+1)) THEN
C                       Polygon is closed.
C                       Recording the polygon:
                        NJPOL=NJPOL+1
                        NLJPOL=NLJPOL-I5
                        JPOL(0,NJPOL)=NLJPOL
                        DO 65, I6=1,NLJPOL
                          JPOL(I6,NJPOL)=JPOL(I5+I6,NJPOL)
  65                    CONTINUE
C                       Removing used starting points:
                        DO 67, I6=1,NLJPOL
                          IF (I6.EQ.1) THEN
                            J1=JPOL(NLJPOL,NJPOL)
                          ELSE
                            J1=JPOL(I6-1,NJPOL)
                          ENDIF
                          J2=JPOL(I6,NJPOL)
                          IF (I6.EQ.NJPOL) THEN
                            J3=JPOL(1,NJPOL)
                          ELSE
                            J3=JPOL(I6+1,NJPOL)
                          ENDIF
                          DO 66, I7=1,NJSP
                            IF ((J1.EQ.JSP(1,I7)).AND.(J2.EQ.JSP(2,I7))
     *                          .AND.(J3.EQ.JSP(3,I7))) THEN
                              JSP(1,I7)=0
                              JSP(2,I7)=0
                              JSP(3,I7)=0
                            ENDIF
  66                      CONTINUE
  67                    CONTINUE
C                       Continuing with next polygon:
                        GOTO 62
                      ENDIF
  68                CONTINUE
                    GOTO 63
                  ENDIF
  69            CONTINUE
C               Polygon is opened, searching for other polygon:
                GOTO 62
              ENDIF
C             No more unused connections,
C             no more polygons on this face of the cube.
C           End of the loop along connections.
  70      CONTINUE
C
C         If there are two or more polygons on the faces of the cube,
C         the polygons are to be omitted:
          IF (NJPOL.GE.2) THEN
C           MODSRF-10
            CALL ERROR('MODSRF-10: Two or more polygons on gridface.')
C           This situation cannot be handled by current version of
C           MODSRF. Try to reduce the gridstep (D1,D2,D3).
          ENDIF
C
C         If there is one polygon on the faces of the cube,
C         the polygon is to be recorded as a polygon approximating
C         a structural interface:
          IF (NJPOL.EQ.1) THEN
C           Searching, whether the polygon is to be recorded:
C           Loop for already recorded polygons:
            I2=MRAM+1
  73        CONTINUE
              IF (I2.GT.NPOL) THEN
                J1=IRAM(I2-1)
                I2=I2-J1-1
                IF (J1.EQ.JPOL(0,1)) THEN
                  DO 74, I3=1,J1
                    IF (IRAM(I2+I3).NE.JPOL(I3,1)) GOTO 73
  74              CONTINUE
C                 The polygon is already recorded:
                  GOTO 77
                ELSE
                  GOTO 73
                ENDIF
              ENDIF
C           End of the loop for already recorded polygons.
C           Recording the polygon:
            IF (NPOL-JPOL(0,1)-1.LE.NCON) CALL MSEROR(1)
            NPOL=NPOL-1
            IRAM(NPOL)=JPOL(0,1)
            DO 75, I2=1,JPOL(0,1)
              NPOL=NPOL-1
              IRAM(NPOL)=JPOL(I2,1)
  75        CONTINUE
  77        CONTINUE
          ENDIF
C
C         Recording polygons approximating structural interfaces:
          NJPOL=0
  80      CONTINUE
C         Loop for adding new polygons
C           Initializing a polygon:
            DO 82, I2=1,NJSP
C             Prefering points on edges:
              IF (JSP(1,I2).GT.NPOIL) THEN
                NJPOL=NJPOL+1
                IF (NJPOL.GT.MJPOL) CALL MSEROR(6)
                NLJPOL=3
                JPOL(0,NJPOL)=0
                JPOL(1,NJPOL)=JSP(1,I2)
                JPOL(2,NJPOL)=JSP(2,I2)
                JPOL(3,NJPOL)=JSP(3,I2)
                JSP(1,I2)=0
                JSP(2,I2)=0
                JSP(3,I2)=0
                GOTO  85
              ENDIF
  82        CONTINUE
            DO 84, I2=1,NJSP
C             No points on edges, taking remaining points:
              IF (JSP(1,I2).NE.0) THEN
                NJPOL=NJPOL+1
                IF (NJPOL.GT.MJPOL) CALL MSEROR(6)
                NLJPOL=3
                JPOL(0,NJPOL)=0
                JPOL(1,NJPOL)=JSP(1,I2)
                JPOL(2,NJPOL)=JSP(2,I2)
                JPOL(3,NJPOL)=JSP(3,I2)
                JSP(1,I2)=0
                JSP(2,I2)=0
                JSP(3,I2)=0
                GOTO  85
              ENDIF
  84        CONTINUE
C           No other point to initialize a polygon:
            GOTO 95
C
  85        CONTINUE
C           Loop for adding a points to the polygon:
              DO 93, I2=1,NJSP
                IF ((JSP(1,I2).EQ.JPOL(NLJPOL-1,NJPOL)).AND.
     *              (JSP(2,I2).EQ.JPOL(NLJPOL  ,NJPOL))) THEN
                  DO 87, I3=2,NLJPOL-2
                    IF (JSP(3,I2).EQ.JPOL(I3,NJPOL)) THEN
C                     This point would cause overlooping of the polygon:
                      JSP(1,I2)=0
                      JSP(2,I2)=0
                      JSP(3,I2)=0
                      DO 86, I4=1,NJSP
                        IF ((JSP(1,I4).EQ.JPOL(NLJPOL,NJPOL)).AND.
     *                      (JSP(2,I4).EQ.JPOL(I3    ,NJPOL)).AND.
     *                      (JSP(3,I4).EQ.JPOL(I3+1  ,NJPOL))) THEN
                          JSP(1,I4)=0
                          JSP(2,I4)=0
                          JSP(3,I4)=0
                          GOTO 85
                        ENDIF
  86                  CONTINUE
C                     
C                     MODSRF-11
                      CALL ERROR('MODSRF-11: Disorder in array JSP.')
C                     This error should not appear. Contact the author.
                    ENDIF
  87              CONTINUE
                  IF (JSP(3,I2).EQ.JPOL(1,NJPOL)) THEN
C                   This point would close the polygon:
                    DO 91, I3=I2+1,NJSP
C                     Looking for other possible continuation, which
C                     would make polygon longer:
                      IF ((JSP(1,I3).EQ.JPOL(NLJPOL-1,NJPOL)).AND.
     *                    (JSP(2,I3).EQ.JPOL(NLJPOL  ,NJPOL)).AND.
     *                    (JSP(3,I3).NE.JPOL(1,NJPOL))) THEN
C                       Other possible continuation of the polygon:
                        DO 90, I4=2,NLJPOL-2
                          IF (JSP(3,I3).EQ.JPOL(I4,NJPOL)) THEN
C                           This point would cause overlooping of the
C                           polygon:
                            JSP(1,I3)=0
                            JSP(2,I3)=0
                            JSP(3,I3)=0
                            DO 89, I5=1,NJSP
                              IF (   (JSP(1,I5).EQ.JPOL(NLJPOL,NJPOL))
     *                          .AND.(JSP(2,I5).EQ.JPOL(I4    ,NJPOL))
     *                          .AND.(JSP(3,I5).EQ.JPOL(I4+1  ,NJPOL)))
     *                          THEN
                                JSP(1,I5)=0
                                JSP(2,I5)=0
                                JSP(3,I5)=0
                                GOTO 85
                              ENDIF
  89                        CONTINUE
C                           
C                           MODSRF-12
                            CALL ERROR
     *                      ('MODSRF-12: Disorder in array JSP.')
C                           This error should not appear.
C                           Contact the author.
                          ENDIF
  90                    CONTINUE
C                       Continuation I2 is to be omitted because
C                       continuation I3 makes the polygon longer:
                        JSP(1,I2)=0
                        JSP(2,I2)=0
                        JSP(3,I2)=0
                        IF (JPOL(0,NJPOL).EQ.0) THEN
C                         Removing the second point which closes the
C                         polygon from JSP:
                          DO 88, I4=1,NJSP
                            IF ((JSP(1,I4).EQ.JPOL(NLJPOL,NJPOL)).AND.
     *                          (JSP(2,I4).EQ.JPOL(1,NJPOL)).AND.
     *                          (JSP(3,I4).EQ.JPOL(2,NJPOL))) THEN
                              JSP(1,I4)=0
                              JSP(2,I4)=0
                              JSP(3,I4)=0
                              JPOL(0,NJPOL)=0
                              GOTO 85
                            ENDIF
  88                      CONTINUE
C                         
C                         MODSRF-13
                          CALL ERROR
     *                    ('MODSRF-13: Disorder in array JSP.')
C                         This error should not appear.
C                         Contact the author.
                        ELSE
                          JPOL(0,NJPOL)=0
                          GOTO 85
                        ENDIF
                      ENDIF
  91                CONTINUE
C                   No other continuation, polygon is to be closed:
                    JSP(1,I2)=0
                    JSP(2,I2)=0
                    JSP(3,I2)=0
                    IF (JPOL(0,NJPOL).EQ.0) THEN
C                     First point which closes the polygon.
                      JPOL(0,NJPOL)=NLJPOL
                      GOTO 85
                    ELSE
C                     Second point which closes the polygon.
                      GOTO 80
                    ENDIF
                  ELSE
C                   Adding a point to the polygon:
                    NLJPOL=NLJPOL+1
                    IF (NLJPOL.GT.MLJPOL) CALL MSEROR(7)
                    JPOL(NLJPOL,NJPOL)=JSP(3,I2)
                    JSP(1,I2)=0
                    JSP(2,I2)=0
                    JSP(3,I2)=0
                    GOTO 85
                  ENDIF
                ELSEIF ((JSP(1,I2).EQ.JPOL(NLJPOL,NJPOL)).AND.
     *                  (JSP(2,I2).EQ.JPOL(1,NJPOL)).AND.
     *                  (JSP(3,I2).EQ.JPOL(2,NJPOL))) THEN
C                 The polygon is closed.
                  JSP(1,I2)=0
                  JSP(2,I2)=0
                  JSP(3,I2)=0
                  IF (JPOL(0,NJPOL).EQ.0) THEN
C                   First point which closes the polygon.
                    JPOL(0,NJPOL)=NLJPOL
                    GOTO 85
                  ELSE
C                   Second point which closes the polygon.
                    GOTO 80
                  ENDIF
                ENDIF
  93          CONTINUE
C             MODSRF-14
              CALL ERROR ('MODSRF-14: Polygon opened.')
C             This error should not appear. Contact the author.
C           End of the loop for adding new points to the polygon.
C         End of the loop for adding new polygons.
C
  95      CONTINUE
C         Writing polygons to IRAM:
          DO 97, I2=1,NJPOL
            IF (NPOL-JPOL(0,I2)-1.LE.NCON) CALL MSEROR(1)
            NPOL=NPOL-1
            IRAM(NPOL)=JPOL(0,I2)
            DO 96, I3=1,JPOL(0,I2)
              NPOL=NPOL-1
              IRAM(NPOL)=JPOL(I3,I2)
  96        CONTINUE
  97      CONTINUE
          NJPOL=0
C
C       End of the loop over gridcubes.
 100    CONTINUE
C
C
      ELSE
C       Loop over faces of the 2-D grid, making polygons along the 2-D
C       slice through the model.
        WRITE(*,'(A)')
     *'+MODSRF: Making polygons along the 2-D slice.                   '
        NPOL=MRAM+1
C
C       Rewriting points on interfaces as points on + side of interface:
        ISHIFT=NPOIE-OPOI
        IF (NPOI+ISHIFT.GT.OCON) CALL MSEROR(1)
        DO 102, I1=OPOI,NPOIE-NQPOI,NQPOI
          RAM(NPOI+1)=RAM(I1+1)
          RAM(NPOI+2)=RAM(I1+2)
          RAM(NPOI+3)=RAM(I1+3)
          IF (IRAM(I1+6).LT.0) THEN
            IRAM(NPOI+4)=IRAM(I1+8)
            IRAM(NPOI+5)=IRAM(I1+7)
            IRAM(NPOI+6)=0
            IRAM(NPOI+7)=IRAM(I1+7)
            IRAM(NPOI+8)=IRAM(I1+8)
          ELSE
            IRAM(NPOI+4)=IRAM(I1+4)
            IRAM(NPOI+5)=IRAM(I1+5)
            IRAM(NPOI+6)=0
            IRAM(NPOI+7)=IRAM(I1+5)
            IRAM(NPOI+8)=IRAM(I1+4)
          ENDIF
          NPOI=NPOI+NQPOI
 102    CONTINUE
        NPOILP=NPOIL+ISHIFT
        NPOIEP=NPOIE+ISHIFT
C
C       Rewriting points on interfaces as points on - side of interface:
        DO 104, I1=OPOI,NPOIE-NQPOI,NQPOI
          IF (IRAM(I1+6).LT.0) THEN
            IRAM(I1+7)=IRAM(I1+5)
            IRAM(I1+8)=IRAM(I1+4)
          ELSE
            IRAM(I1+4)=IRAM(I1+8)
            IRAM(I1+5)=IRAM(I1+7)
          ENDIF
          IRAM(NPOI+6)=0
 104    CONTINUE
C
C       Recording gridpoints to the array of points:
        IF (NPOI+NGPS*NQPOI.GT.OCON) CALL MSEROR(1)
        DO 106, I1=1,NGPS
          CALL MSCP(I1,X1,X2,X3)
          RAM(NPOI+1)=X1
          RAM(NPOI+2)=X2
          RAM(NPOI+3)=X3
          IRAM(NPOI+4)=IRAM(2*(I1-1)+2)
          IRAM(NPOI+5)=IRAM(2*(I1-1)+1)
          IRAM(NPOI+6)=0
          IRAM(NPOI+7)=IRAM(2*(I1-1)+1)
          IRAM(NPOI+8)=IRAM(2*(I1-1)+2)
          NPOI=NPOI+NQPOI
 106    CONTINUE
C       Loop over gridfaces:
        DO 200, I1=1,NFAC
C         Forming array with connections for the gridface:
          NJCN=0
C         Connections inside the gridface:
          DO 110, I2=IRAM(OFAC+I1-1),IRAM(OFAC+I1)-3,3
C           Connections of the gridface I1:
            IF (IRAM(I2+3).NE.0) THEN
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN) CALL MSEROR(4)
              JCN(1,NJCN)=IRAM(I2+1)
              JCN(2,NJCN)=IRAM(I2+2)
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN) CALL MSEROR(4)
              JCN(1,NJCN)=IRAM(I2+2)+ISHIFT
              JCN(2,NJCN)=IRAM(I2+1)+ISHIFT
              JCN(3,NJCN)=1
            ELSE
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN) CALL MSEROR(4)
              IF (IRAM(I2+1).LT.0) THEN
                JCN(1,NJCN)=-IRAM(I2+1)
              ELSE
                JCN(1,NJCN)=IRAM(I2+1)+ISHIFT
              ENDIF
              IF (IRAM(I2+2).LT.0) THEN
                JCN(2,NJCN)=-IRAM(I2+2)
              ELSE
                JCN(2,NJCN)=IRAM(I2+2)+ISHIFT
              ENDIF
              JCN(3,NJCN)=1
            ENDIF
 110      CONTINUE
C         Connections along the gridface:
C         Indices of gridlegs of the gridface:
          CALL MSGFAC(I1,IL1,IL2,IL3,IL4)
C
          CALL MSGLEG(IL1,IP1,IP2)
          NJCN=NJCN+1
          IF (NJCN.GT.MJCN)  CALL MSEROR(4)
          JCN(1,NJCN)=NPOIEP+IP1*NQPOI
          DO 112, I2=IRAM(OLEG+IL1-1)+NQPOI,IRAM(OLEG+IL1),NQPOI
            ICBOLD=IRAM(JCN(1,NJCN)-NQPOI+4)
            ICBNEW=IRAM(I2         -NQPOI+4)
            IF (ICBOLD.NE.ICBNEW) THEN
              JCN(2,NJCN)=I2+ISHIFT
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2
            ELSE
              JCN(2,NJCN)=I2
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2+ISHIFT
            ENDIF
 112      CONTINUE
          JCN(2,NJCN)=NPOIEP+IP2*NQPOI
          JCN(3,NJCN)=1
C
          CALL MSGLEG(IL2,IP1,IP2)
          NJCN=NJCN+1
          IF (NJCN.GT.MJCN)  CALL MSEROR(4)
          JCN(1,NJCN)=NPOIEP+IP1*NQPOI
          DO 114, I2=IRAM(OLEG+IL2-1)+NQPOI,IRAM(OLEG+IL2),NQPOI
            ICBOLD=IRAM(JCN(1,NJCN)-NQPOI+4)
            ICBNEW=IRAM(I2         -NQPOI+4)
            IF (ICBOLD.NE.ICBNEW) THEN
              JCN(2,NJCN)=I2+ISHIFT
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2
            ELSE
              JCN(2,NJCN)=I2
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2+ISHIFT
            ENDIF
 114      CONTINUE
          JCN(2,NJCN)=NPOIEP+IP2*NQPOI
          JCN(3,NJCN)=1
C
          CALL MSGLEG(IL3,IP2,IP1)
          NJCN=NJCN+1
          IF (NJCN.GT.MJCN)  CALL MSEROR(4)
          JCN(1,NJCN)=NPOIEP+IP1*NQPOI
          DO 116, I2=IRAM(OLEG+IL3),IRAM(OLEG+IL3-1)+NQPOI,-NQPOI
            ICBOLD=IRAM(JCN(1,NJCN)-NQPOI+4)
            ICBNEW=IRAM(I2         -NQPOI+4)
            IF (ICBOLD.NE.ICBNEW) THEN
              JCN(2,NJCN)=I2+ISHIFT
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2
            ELSE
              JCN(2,NJCN)=I2
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2+ISHIFT
            ENDIF
 116      CONTINUE
          JCN(2,NJCN)=NPOIEP+IP2*NQPOI
          JCN(3,NJCN)=1
C
          CALL MSGLEG(IL4,IP2,IP1)
          NJCN=NJCN+1
          IF (NJCN.GT.MJCN)  CALL MSEROR(4)
          JCN(1,NJCN)=NPOIEP+IP1*NQPOI
          DO 118, I2=IRAM(OLEG+IL4),IRAM(OLEG+IL4-1)+NQPOI,-NQPOI
            ICBOLD=IRAM(JCN(1,NJCN)-NQPOI+4)
            ICBNEW=IRAM(I2         -NQPOI+4)
            IF (ICBOLD.NE.ICBNEW) THEN
              JCN(2,NJCN)=I2+ISHIFT
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2
            ELSE
              JCN(2,NJCN)=I2
              JCN(3,NJCN)=1
              NJCN=NJCN+1
              IF (NJCN.GT.MJCN)  CALL MSEROR(4)
              JCN(1,NJCN)=I2+ISHIFT
            ENDIF
 118      CONTINUE
          JCN(2,NJCN)=NPOIEP+IP2*NQPOI
          JCN(3,NJCN)=1
C         Array with connections is done.
C
C         Forming polygons along the gridface:
 124      CONTINUE
          DO 130, I2=1,NJCN
            IF (JCN(3,I2).NE.0) THEN
C             Initiating polygon:
              NLJPOL=2
              JPOL(1,1)=JCN(1,I2)
              JPOL(2,1)=JCN(2,I2)
              JCN(3,I2)=0
 126          CONTINUE
              DO 128, I3=1,NJCN
                IF ((JCN(3,I3).NE.0).AND.
     *              (JCN(1,I3).EQ.JPOL(NLJPOL,1))) THEN
                  NLJPOL=NLJPOL+1
                  IF (NLJPOL.GT.MLJPOL) CALL MSEROR(7)
                  JPOL(NLJPOL,1)=JCN(2,I3)
                  JCN(3,I3)=0
                  IF (JPOL(NLJPOL,1).EQ.JPOL(1,1)) THEN
C                   Polygon is closed - recording the polygon to IRAM:
                    NLJPOL=NLJPOL-1
                    IF (NPOL-NLJPOL-1.LE.NCON) CALL MSEROR(1)
                    NPOL=NPOL-1
                    IRAM(NPOL)=NLJPOL
                    DO 127, I4=1,NLJPOL
                      NPOL=NPOL-1
                      IRAM(NPOL)=JPOL(I4,1)
 127                CONTINUE
                    GOTO 124
                  ELSE
                    GOTO 126
                  ENDIF
                ENDIF
 128          CONTINUE
C             MODSRF-15
              CALL ERROR ('MODSRF-15: Polygon not closed.')
C             This error should not appear. Contact the author.
            ENDIF
 130      CONTINUE
C       End of the loop along gridfaces of the 2-D slice.
 200    CONTINUE
C
C       Preparing the normal to the 2-D slice:
        F(2)=0.
        F(3)=0.
        F(4)=0.
        IF (N1.EQ.1) F(2)=1.
        IF (N2.EQ.1) F(3)=1.
        IF (N3.EQ.1) F(4)=1.
C
      ENDIF
C
C
C     Storing points on structural interfaces and polygons:
      WRITE(*,'(A)')
     *'+MODSRF: Writing.                                               '
C
C     Storing points:
      OPEN(LU,FILE=VRTX,FORM='FORMATTED')
      WRITE(LU,'(A)') '/'
      NPOINT=(NPOI-OPOI)/NQPOI
C     Length of the names of points:
      LEN1=LENGTH(TEXTP)
      LEN2=0
 202  CONTINUE
        IF (NPOINT.GE.10**LEN2) THEN
          LEN2=LEN2+1
          GOTO 202
        ENDIF
      LENG=LEN1+LEN2
C     Loop over points:
      DO 218, I1=1,NPOINT
C       Address in RAM just before the current point:
        J1=OPOI+(I1-1)*NQPOI
C       Name of the point:
        DO 204, I2=0,LEN2-1
          TEXTP(LENG-I2:LENG-I2)=
     *    CHAR(ICHAR('0')+MOD(I1,10**(I2+1))/10**I2)
 204    CONTINUE
C       Coordinates of the point:
        Z(1)=RAM(J1+1)
        Z(2)=RAM(J1+2)
        Z(3)=RAM(J1+3)
C       Normal to the interface at the point:
        IF (NCUB.NE.0) CALL SRFC2(IRAM(J1+6),RAM(J1+1),F)
        Z(4)=F(2)
        Z(5)=F(3)
        Z(6)=F(4)
C       Other quantities:
        J2=6
 206    CONTINUE
          IF ((TEXTC(J2+1).NE.' ').AND.(J2+1.LE.69)) THEN
            J2=J2+1
            IF (IRAM(J1+6).LT.0) THEN
              ICBPOS=IRAM(J1+8)
              ICBNEG=IRAM(J1+4)
            ELSE
              ICBPOS=IRAM(J1+4)
              ICBNEG=IRAM(J1+8)
            ENDIF
            IF     (TEXTC(J2).EQ.'isrf') THEN
              Z(J2)=FLOAT(IABS(IRAM(J1+6)))**POWER(J2)
            ELSEIF (TEXTC(J2).EQ.'+icb') THEN
              Z(J2)=FLOAT(ICBPOS)**POWER(J2)
            ELSEIF (TEXTC(J2).EQ.'-icb') THEN
              Z(J2)=FLOAT(ICBNEG)**POWER(J2)
            ELSEIF (TEXTC(J2).EQ.'+isb') THEN
              IF (IRAM(J1+6).LT.0) THEN
                Z(J2)=FLOAT(IRAM(J1+7))**POWER(J2)
              ELSE
                Z(J2)=FLOAT(IRAM(J1+5))**POWER(J2)
              ENDIF
            ELSEIF (TEXTC(J2).EQ.'-isb') THEN
              IF (IRAM(J1+6).LT.0) THEN
                Z(J2)=FLOAT(IRAM(J1+5))**POWER(J2)
              ELSE
                Z(J2)=FLOAT(IRAM(J1+7))**POWER(J2)
              ENDIF
            ELSEIF ((TEXTC(J2)(2:2).EQ.'v')
     *          .OR.(TEXTC(J2)(2:2).EQ.'d')
     *          .OR.(TEXTC(J2)(2:3).EQ.'qp')
     *          .OR.(TEXTC(J2)(2:3).EQ.'qs')) THEN
              VP(1)=0.
              VS(1)=0.
              RHO=0.
              QP=0.
              QS=0.
              IF (TEXTC(J2)(1:1).EQ.'+') THEN
                IF (ICBPOS.NE.0) CALL PARM2(ICBPOS,Z(1),VP,VS,RHO,QP,QS)
              ELSE
                IF (ICBNEG.NE.0) CALL PARM2(ICBNEG,Z(1),VP,VS,RHO,QP,QS)
              ENDIF
              IF     (TEXTC(J2)(2:3).EQ.'vp') THEN
                Z(J2)=VP(1)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:3).EQ.'vs') THEN
                Z(J2)=VS(1)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:3).EQ.'de') THEN
                Z(J2)=RHO**POWER(J2)
              ELSEIF (TEXTC(J2)(2:3).EQ.'qp') THEN
                Z(J2)=QP**POWER(J2)
              ELSEIF (TEXTC(J2)(2:3).EQ.'qs') THEN
                Z(J2)=QS**POWER(J2)
              ENDIF
            ELSEIF ((TEXTC(J2)(2:2).EQ.'a')
     *          .OR.(TEXTC(J2)(2:2).EQ.'q')) THEN
              DO 208, I3=1,21
                A(1,I3)=0.
                Q(I3)=0.
 208          CONTINUE
              IF (TEXTC(J2)(1:1).EQ.'+') THEN
                IF (ICBPOS.NE.0) CALL PARM3(ICBPOS,Z(1),A,RHO,Q)
              ELSE
                IF (ICBNEG.NE.0) CALL PARM3(ICBNEG,Z(1),A,RHO,Q)
              ENDIF
              IF     (TEXTC(J2)(2:4).EQ.'a11') THEN
                Z(J2)=A(1, 1)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a12') THEN
                Z(J2)=A(1, 2)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a22') THEN
                Z(J2)=A(1, 3)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a13') THEN
                Z(J2)=A(1, 4)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a23') THEN
                Z(J2)=A(1, 5)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a33') THEN
                Z(J2)=A(1, 6)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a14') THEN
                Z(J2)=A(1, 7)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a24') THEN
                Z(J2)=A(1, 8)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a34') THEN
                Z(J2)=A(1, 9)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a44') THEN
                Z(J2)=A(1,10)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a15') THEN
                Z(J2)=A(1,11)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a25') THEN
                Z(J2)=A(1,12)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a35') THEN
                Z(J2)=A(1,13)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a45') THEN
                Z(J2)=A(1,14)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a55') THEN
                Z(J2)=A(1,15)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a16') THEN
                Z(J2)=A(1,16)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a26') THEN
                Z(J2)=A(1,17)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a36') THEN
                Z(J2)=A(1,18)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a46') THEN
                Z(J2)=A(1,19)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a56') THEN
                Z(J2)=A(1,20)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'a66') THEN
                Z(J2)=A(1,21)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q11') THEN
                Z(J2)=Q( 1)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q12') THEN
                Z(J2)=Q( 2)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q22') THEN
                Z(J2)=Q( 3)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q13') THEN
                Z(J2)=Q( 4)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q23') THEN
                Z(J2)=Q( 5)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q33') THEN
                Z(J2)=Q( 6)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q14') THEN
                Z(J2)=Q( 7)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q24') THEN
                Z(J2)=Q( 8)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q34') THEN
                Z(J2)=Q( 9)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q44') THEN
                Z(J2)=Q(10)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q15') THEN
                Z(J2)=Q(11)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q25') THEN
                Z(J2)=Q(12)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q35') THEN
                Z(J2)=Q(13)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q45') THEN
                Z(J2)=Q(14)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q55') THEN
                Z(J2)=Q(15)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q16') THEN
                Z(J2)=Q(16)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q26') THEN
                Z(J2)=Q(17)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q36') THEN
                Z(J2)=Q(18)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q46') THEN
                Z(J2)=Q(19)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q56') THEN
                Z(J2)=Q(20)**POWER(J2)
              ELSEIF (TEXTC(J2)(2:4).EQ.'q66') THEN
                Z(J2)=Q(21)**POWER(J2)
              ENDIF
            ENDIF
            GOTO 206
          ENDIF
C       End of the loop for other quantities.
C       Writing the quantities at the point:
C       Setting output format for the array:
        FORMAT='(3A,00(F00.0,1X),A)'
        FORMAT(6:6)=CHAR(ICHAR('0')+MOD(J2,10))
        FORMAT(5:5)=CHAR(ICHAR('0')+J2/10)
        OUTMIN=0.
        OUTMAX=0.
        DO 214, I2=1,J2
          IF (OUTMIN.GT.Z(I2)) OUTMIN=Z(I2)
          IF (OUTMAX.LT.Z(I2)) OUTMAX=Z(I2)
 214    CONTINUE
        CALL FORM1(OUTMIN,OUTMAX,FORMAT(8:15))
        FORMAT(14:17)= '1X),'
C       Output format is set.
        WRITE(LU,FORMAT) '''',TEXTP(1:LENG),''' ',(Z(I2),I2=1,J2),'/'
 218  CONTINUE
C     End of the loop over all points.
      WRITE(LU,'(A)') '/'
      CLOSE(LU)
C
C     Storing polygons:
      IF(PLGN.NE.' ') OPEN(LU1,FILE=PLGN,FORM='FORMATTED')
      IF(PLGNS.NE.' ')OPEN(LU2,FILE=PLGNS,FORM='FORMATTED')
      FORMA1='(00(I8,1X),A)'
      FORMA2='(00(3A,1X),A)'
      I1=MRAM
C     Loop over polygons:
 220  CONTINUE
      IF (I1.GT.NPOL) THEN
        J1=IRAM(I1)
        I3=MOD(J1,10)
        FORMA1(3:3)=CHAR(ICHAR('0')+I3)
        FORMA2(3:3)=CHAR(ICHAR('0')+I3)
        I3=J1/10
        FORMA1(2:2)=CHAR(ICHAR('0')+I3)
        FORMA2(2:2)=CHAR(ICHAR('0')+I3)
        J2=IRAM(I1-1)
        IF ((IRAM(J2-NQPOI+4).NE.0).OR.
     *      (IRAM(J2-NQPOI+8).NE.0)) THEN
          IF (PLGN.NE.' ') THEN
            WRITE(LU1,FORMA1)
     *           ((IRAM(I2)-OPOI)/NQPOI,I2=I1-1,I1-J1,-1),'/'
          ENDIF
          IF (PLGNS.NE.' ') THEN
            IF (J1.GT.MLJPOL) THEN
C             MODSRF-16
              CALL ERROR ('MODSRF-16: Disorder in polygons.')
C             This error should not appear. Contact the author.
            ENDIF
            DO 224, I2=I1-1,I1-J1,-1
C             Index of the point (from 1 to NPOINT):
              J2=(IRAM(I2)-OPOI)/NQPOI
C             Name of the point:
              I4=I1-I2
              DO 222, I3=0,LEN2-1
                TEXTS(I4)(1:LEN1)=TEXTP(1:LEN1)
                TEXTS(I4)(LENG-I3:LENG-I3)=
     *          CHAR(ICHAR('0')+MOD(J2,10**(I3+1))/10**I3)
 222          CONTINUE
 224        CONTINUE
            WRITE(LU2,FORMA2)
     *           ('''',TEXTS(I2)(1:LENG),'''',I2=1,J1),'/'
          ENDIF
        ENDIF
        I1=I1-(J1+1)
        GOTO 220
      ENDIF
C     End of the loop over polygons.
      IF (PLGN.NE.' ') THEN
        WRITE(LU1,'(A)') '/'
        CLOSE(LU1)
      ENDIF
      IF (PLGNS.NE.' ') THEN
        WRITE(LU2,'(A)') '/'
        CLOSE(LU2)
      ENDIF
C
      WRITE(*,'(A)')
     *'+MODSRF: Finished                                              '
      END
C
C=======================================================================
C
      SUBROUTINE FCTMS(X,Y,T)
C
C-----------------------------------------------------------------------
C
      REAL X,Y(*),T(*)
C
C Subroutine evaluating the right-hand sides of the interface tracing
C equations. I.E. subroutine computing vector T tangent to the
C interface.
C
C Input:
C     X...    Value of the independent variable.
C     Y...    Array containing two coordinates of a
C             point of the interface, determined by means of numerical
C             integration.
C Output:
C     Y...    Array containing two coordinates of the
C             interface, corrected by means of the linearization in
C             the direction of the gradient (perpendicular to the
C             interface).
C     T...    Array containing derivatives of the coordinates
C             Y with respect to X (vector tangent to the interface).
C-----------------------------------------------------------------------
C
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      REAL S1,S2,S3,F(10),AUX
C
C.......................................................................
C
      CALL SRFC2(ISRFO,Y,F)
      IF (ISRFO.LT.0) THEN
        S1=F(2)
        S2=F(3)
        S3=F(4)
      ELSE
        S1=-F(2)
        S2=-F(3)
        S3=-F(4)
      ENDIF
      IF (IFACE.LE.NFAC1) THEN
        F(2)=0.
        S1=0.
        T(1)=0.
        AUX=SQRT(S2*S2+S3*S3)
        T(2)=-S3/AUX
        T(3)= S2/AUX
      ELSEIF (IFACE.LE.NFAC12) THEN
        F(3)=0.
        S2=0.
        T(2)=0.
        AUX=SQRT(S1*S1+S3*S3)
        T(3)=-S1/AUX
        T(1)= S3/AUX
      ELSE
        F(4)=0.
        S3=0.
        T(3)=0.
        AUX=SQRT(S1*S1+S2*S2)
        T(1)=-S2/AUX
        T(2)= S1/AUX
      ENDIF
C
C     Correction of the isoline
      AUX=F(1)/AUX/AUX
      Y(1)=Y(1)-F(2)*AUX
      Y(2)=Y(2)-F(3)*AUX
      Y(3)=Y(3)-F(4)*AUX
C
      RETURN
      END
C
C=======================================================================
C
      SUBROUTINE OUTMS(X,Y,DERY,IHLF,NDIM,PRMT)
C
C-----------------------------------------------------------------------
C
      INTEGER IHLF,NDIM
      REAL X,Y(NDIM),DERY(NDIM),PRMT(*)
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
      EXTERNAL ISIDE
      INTEGER ISIDE
C     Auxiliary storage locations:
      REAL XTMP1,XTMP(3),DTMP(3),DUMMY(1),ERR,XINT1,DINT(3)
      REAL X01,X02,X1(3),X2(3)
      INTEGER IDUMMY,IY1(8),IY2(8),ISUR(2)
C.......................................................................
      IF (IHLF.GT.10) THEN
C       MODSRF-17
        CALL ERROR ('MODSRF-17: Wrong IHLF.')
C       This error should not appear. Contact the author.
      ENDIF
      IF (X.GT.PRMT(1)) THEN
        X01=0.
        X02=0.
C       Calling CDE along side 1:
        ERR=PRMT(4)
        XTMP1=X
        XTMP(1)=Y(1)
        XTMP(2)=Y(2)
        XTMP(3)=Y(3)
        DTMP(1)=DERY(1)
        DTMP(2)=DERY(2)
        DTMP(3)=DERY(3)
        IY1(4)=ISBO1
        IY1(5)=ICBO1
        IY1(6)=0
        CALL CDE(ISRFO,0,IDUMMY,0,IDUMMY,DUMMY,1,3,3,IY1,ERR,
     *    X0,X0,YOLD,DYOLD,X,Y,DERY,XTMP1,XTMP,DTMP,XINT1,X1,DINT)
        IF (IY1(6).NE.0) THEN
C         Interface crossed:
          X01=XINT1
        ENDIF
C
C       Calling CDE along side 2:
        XTMP1=X
        XTMP(1)=Y(1)
        XTMP(2)=Y(2)
        XTMP(3)=Y(3)
        DTMP(1)=DERY(1)
        DTMP(2)=DERY(2)
        DTMP(3)=DERY(3)
        IY2(4)=ISBO2
        IY2(5)=ICBO2
        IY2(6)=0
        CALL CDE(ISRFO,0,IDUMMY,0,IDUMMY,DUMMY,1,3,3,IY2,ERR,
     *    X0,X0,YOLD,DYOLD,X,Y,DERY,XTMP1,XTMP,DTMP,XINT1,X2,DINT)
        IF (IY2(6).NE.0) THEN
C         Interface crossed:
          X02=XINT1
        ENDIF
C
        IF ((X01.NE.0.).OR.(X02.NE.0.)) THEN
C         Interface crossed.
C
          IF ((X01.NE.0.).AND.(X02.NE.0.)) THEN
C           Choosing the nearer of the two crossed interfaces:
            IF (X01.LT.X02) THEN
              X02=0.
            ELSEIF (X02.LT.X01) THEN
              X01=0.
            ENDIF
          ENDIF
C
C         Recording indices of blocks computed by CDE:
          IF (X01.NE.0.) THEN
            ISBO1= IY1(4)
            ISRFN1=IY1(6)
            ISBN1= IY1(7)
            ICBN1= IY1(8)
            Y(1)=X1(1)
            Y(2)=X1(2)
            Y(3)=X1(3)
          ENDIF
          IF (X02.NE.0.) THEN
            ISBO2= IY2(4)
            ISRFN2=IY2(6)
            ISBN2= IY2(7)
            ICBN2= IY2(8)
            Y(1)=X2(1)
            Y(2)=X2(2)
            Y(3)=X2(3)
          ENDIF
C         Computing remaining indices of blocks:
          IF (X01.EQ.0.) THEN
            ISUR(1)=ISRFO
            ISUR(2)=ISRFN2
            CALL BLOCKS(X2,2,ISUR,ISBO2,IDUMMY,ISBO1,ICBO1)
            ISRFN1=ISRFN2
            IF (ISIDE(ISRFO,ISBN2).LT.2) THEN
              CALL BLOCKS(X2,2,ISUR,ISBN2,IDUMMY,ISBN1,ICBN1)
            ELSE
              ISBN1=ISBN2
              ICBN1=ICBN2
            ENDIF
          ENDIF
          IF (X02.EQ.0.) THEN
            ISUR(1)=ISRFO
            ISUR(2)=ISRFN1
            CALL BLOCKS(X1,2,ISUR,ISBO1,IDUMMY,ISBO2,ICBO2)
            ISRFN2=ISRFN1
            IF (ISIDE(ISRFO,ISBN1).LT.2) THEN
              CALL BLOCKS(X1,2,ISUR,ISBN1,IDUMMY,ISBN2,ICBN2)
            ELSE
              ISBN2=ISBN1
              ICBN2=ICBN1
            ENDIF
          ENDIF
          PRMT(5)=1.
        ENDIF
      ENDIF
C
C     Storing the old point:
      X0=X
      YOLD(1)=Y(1)
      YOLD(2)=Y(2)
      YOLD(3)=Y(3)
      DYOLD(1)=DERY(1)
      DYOLD(2)=DERY(2)
      DYOLD(3)=DERY(3)
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSGLEG(ILEG,IPOIN1,IPOIN2)
C
C-----------------------------------------------------------------------
C
      INTEGER ILEG,IPOIN1,IPOIN2
C Input:
C     ILEG ... Index of gridleg.
C Output:
C     IPOIN1,IPOIN2 ... Indices of gridpoints forming the gridleg.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,ILEG1
C.......................................................................
C
      ILEG1=ILEG-1
      IF (ILEG.LE.NLEG1) THEN
        I31=ILEG1 / N11N2
        I21=(ILEG1 - I31*N11N2) / N11
        I1=ILEG - I31*N11N2 - I21*N11
        IPOIN1=I31*N1N2+I21*N1+I1
        IPOIN2=IPOIN1+1
      ELSEIF (ILEG.LE.NLEG12) THEN
        I31=(ILEG1-NLEG1) / N1N21
        I21=((ILEG1-NLEG1) - I31*N1N21) / N1
        I1=(ILEG-NLEG1) - I31*N1*N21 - I21*N1
        IPOIN1=I31*N1N2+I21*N1+I1
        IPOIN2=IPOIN1+N1
      ELSEIF (ILEG.LE.NLEG) THEN
        I31=(ILEG1-NLEG12) / N1N2
        I21=((ILEG1-NLEG12) - I31*N1N2) / N1
        I1=(ILEG-NLEG12) - I31*N1N2 - I21*N1
        IPOIN1=I31*N1N2+I21*N1+I1
        IPOIN2=IPOIN1+N1*N2
      ELSE
C       MODSRF-18
        CALL ERROR ('MODSRF-18: Wrong ILEG.')
C       This error should not appear. Contact the author.
      ENDIF
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSGFAC(IFAC,ILEG1,ILEG2,ILEG3,ILEG4)
C
C-----------------------------------------------------------------------
C
      INTEGER IFAC,ILEG1,ILEG2,ILEG3,ILEG4
C     IFAC ... Index of gridface.
C     ILEG1,ILEG2,ILEG3,ILEG4 ... Indices of gridlegs forming
C              the gridface.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,IFAC1
C.......................................................................
C
      IFAC1=IFAC-1
      IF (IFAC.LE.NFAC1) THEN
        I31= IFAC1 / N1N21
        I21=(IFAC1 - I31*N1N21) / N1
        I1 = IFAC - I31*N1N21 - I21*N1
        ILEG1=NLEG1 + I31*N1N21+I21*N1+I1
        ILEG4=NLEG12 + I31*N1N2+I21*N1+I1
        ILEG2=ILEG4+N1
        ILEG3=ILEG1+N1N21
      ELSEIF (IFAC.LE.NFAC12) THEN
        I31= (IFAC1-NFAC1) / N11N2
        I21=((IFAC1-NFAC1) - I31*N11N2) / N11
        I1 = (IFAC-NFAC1) - I31*N11N2 - I21*N11
        ILEG1=NLEG12 + I31*N1N2+I21*N1+I1
        ILEG4=         I31*N11N2+I21*N11+I1
        ILEG2=ILEG4+N11N2
        ILEG3=ILEG1+1
      ELSEIF (IFAC.LE.NFAC) THEN
        I31= (IFAC1-NFAC12) / N11N21
        I21=((IFAC1-NFAC12) - I31*N11N21) / N11
        I1 = (IFAC-NFAC12) - I31*N11N21 - I21*N11
        ILEG1=        I31*N11N2+I21*N11+I1
        ILEG4=NLEG1 + I31*N1N21+I21*N1+I1
        ILEG2=ILEG4+1
        ILEG3=ILEG1+N11
      ELSE
C       MODSRF-19
        CALL ERROR ('MODSRF-19: Wrong IFAC.')
C       This error should not appear. Contact the author.
      ENDIF
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSGCUB(ICUB,IFAC1,IFAC2,IFAC3,IFAC4,IFAC5,IFAC6)
C
C-----------------------------------------------------------------------
C
      INTEGER ICUB,IFAC1,IFAC2,IFAC3,IFAC4,IFAC5,IFAC6
C     ICUB ... Index of gridcube.
C     IFAC1,...,IFAC6 ... Indices of gridfaces forming the gridcube.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,ICUB1
C.......................................................................
C
      IF ((ICUB.LT.1).OR.(ICUB.GT.NCUB)) THEN
C       MODSRF-20
        CALL ERROR ('MODSRF-20: Wrong ICUB.')
C       This error should not appear. Contact the author.
      ENDIF
      ICUB1=ICUB-1
      I31= ICUB1 / N11N21
      I21=(ICUB1 - I31*N11N21) / N11
      I1=  ICUB  - I31*N11N21 - I21*N11
      IFAC1=       I31*N1N21 +I21*N1 +I1
      IFAC2=NFAC1 +I31*N11N2 +I21*N11+I1
      IFAC3=NFAC12+I31*N11N21+I21*N11+I1
      IFAC4=IFAC1+1
      IFAC5=IFAC2+N11
      IFAC6=IFAC3+N11N21
      RETURN
      END
C
C
C=======================================================================
C
      LOGICAL FUNCTION MSLPIF(XX,IFAC)
C
C-----------------------------------------------------------------------
C     Subroutine for decision, whether the point with coordinates XX
C     lies inside gridface IFAC.
C
      INTEGER IFAC
      REAL XX(3)
C Input:
C     XX   ... Coordinates of the point.
C     IFAC ... Index of the gridface.
C Output:
C     MSLPIF ... .TRUE. when the point lies inside the gridface.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,IFAC1,IP1,IP2
      INTEGER ILEG1,ILEG2
      REAL XA1,XA2,XA3,XB1,XB2,XB3,XC1,XC2,XC3
C.......................................................................
C
      IFAC1=IFAC-1
      IF (IFAC.LE.NFAC1) THEN
        I31= IFAC1 / N1N21
        I21=(IFAC1 - I31*N1N21) / N1
        I1 = IFAC - I31*N1N21 - I21*N1
        ILEG1=NLEG1 + I31*N1N21+I21*N1+I1
        ILEG2=NLEG12 + I31*N1N2+I21*N1+I1 + N1
      ELSEIF (IFAC.LE.NFAC12) THEN
        I31= (IFAC1-NFAC1) / N11N2
        I21=((IFAC1-NFAC1) - I31*N11N2) / N11
        I1 = (IFAC-NFAC1) - I31*N11N2 - I21*N11
        ILEG1=NLEG12 + I31*N1N2+I21*N1+I1
        ILEG2=         I31*N11N2+I21*N11+I1 + N11N2
      ELSEIF (IFAC.LE.NFAC) THEN
        I31= (IFAC1-NFAC12) / N11N21
        I21=((IFAC1-NFAC12) - I31*N11N21) / N11
        I1 = (IFAC-NFAC12) - I31*N11N21 - I21*N11
        ILEG1=        I31*N11N2+I21*N11+I1
        ILEG2=NLEG1 + I31*N1N21+I21*N1+I1 + 1
      ELSE
C       MODSRF-21
        CALL ERROR ('MODSRF-21: Wrong IFAC.')
C       This error should not appear. Contact the author.
      ENDIF
C
      MSLPIF=.TRUE.
C
      CALL MSGLEG(ILEG1,IP1,IP2)
      CALL MSCP(IP1,XA1,XA2,XA3)
      CALL MSCP(IP2,XB1,XB2,XB3)
      CALL MSGLEG(ILEG2,IP1,IP2)
      CALL MSCP(IP2,XC1,XC2,XC3)
      IF ((XX(1).LT.AMIN1(XA1,XB1,XC1)).OR.
     *    (XX(1).GT.AMAX1(XA1,XB1,XC1))) MSLPIF=.FALSE.
      IF ((XX(2).LT.AMIN1(XA2,XB2,XC2)).OR.
     *    (XX(2).GT.AMAX1(XA2,XB2,XC2))) MSLPIF=.FALSE.
      IF ((XX(3).LT.AMIN1(XA3,XB3,XC3)).OR.
     *    (XX(3).GT.AMAX1(XA3,XB3,XC3))) MSLPIF=.FALSE.
      RETURN
      END
C
C
C=======================================================================
C
      LOGICAL FUNCTION MSLPIL(XX,ILEG)
C
C-----------------------------------------------------------------------
C     Subroutine for decision, whether the point with coordinates XX
C     lies inside gridleg ILEG.
C
      INTEGER ILEG
      REAL XX(3)
C Input:
C     XX   ... Coordinates of the point.
C     ILEG ... Index of the gridleg.
C Output:
C     MSLPIF ... .TRUE. when the point lies inside the gridleg.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER IP1,IP2
      REAL XA1,XA2,XA3,XB1,XB2,XB3
C.......................................................................
C
      CALL MSGLEG(ILEG,IP1,IP2)
      CALL MSCP(IP1,XA1,XA2,XA3)
      CALL MSCP(IP2,XB1,XB2,XB3)
      MSLPIL=.TRUE.
      IF ((XX(1).LT.AMIN1(XA1,XB1)).OR.
     *    (XX(1).GT.AMAX1(XA1,XB1))) MSLPIL=.FALSE.
      IF ((XX(2).LT.AMIN1(XA2,XB2)).OR.
     *    (XX(2).GT.AMAX1(XA2,XB2))) MSLPIL=.FALSE.
      IF ((XX(3).LT.AMIN1(XA3,XB3)).OR.
     *    (XX(3).GT.AMAX1(XA3,XB3))) MSLPIL=.FALSE.
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSGCGP(ICUB,IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8)
C
C-----------------------------------------------------------------------
C     Subroutine for debugging purposes,  gives indices of points
C     of cube ICUB.
C
C
      INTEGER ICUB,IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8
C     ICUB ... Index of gridcube.
C     IP1,...,IP8 ... Indices of gridpoints forming the gridcube.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,ICUB1
C.......................................................................
C
      IF ((ICUB.LT.1).OR.(ICUB.GT.NCUB)) THEN
C       MODSRF-22
        CALL ERROR ('MODSRF-22: Wrong ICUB.')
C       This error should not appear. Contact the author.
      ENDIF
      ICUB1=ICUB-1
      I31= ICUB1 / N11N21
      I21=(ICUB1 - I31*N11N21) / N11
      I1=  ICUB  - I31*N11N21 - I21*N11
      IP1=I31*N1N2+I21*N1+I1
      IP2=IP1+N1
      IP3=IP2+N1N2
      IP4=IP1+N1N2
      IP5=IP1+1
      IP6=IP5+N1
      IP7=IP6+N1N2
      IP8=IP5+N1N2
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSXFAC(IFAC)
C
C-----------------------------------------------------------------------
C     Subroutine for debugging purposes,  gives coordinates of points
C     of face IFAC.
C
      INTEGER IFAC,ILEG1,ILEG2,ILEG3,ILEG4
C     IFAC ... Index of gridface.
C     ILEG1,ILEG2,ILEG3,ILEG4 ... Indices of gridlegs forming
C              the gridface.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I1,IFAC1,IP1,IP2
      REAL X1,X2,X3
C.......................................................................
C
      IFAC1=IFAC-1
      IF (IFAC.LE.NFAC1) THEN
        I31= IFAC1 / N1N21
        I21=(IFAC1 - I31*N1N21) / N1
        I1 = IFAC - I31*N1N21 - I21*N1
        ILEG1=NLEG1 + I31*N1N21+I21*N1+I1
        ILEG4=NLEG12 + I31*N1N2+I21*N1+I1
        ILEG2=ILEG4+N1
        ILEG3=ILEG1+N1N21
      ELSEIF (IFAC.LE.NFAC12) THEN
        I31= (IFAC1-NFAC1) / N11N2
        I21=((IFAC1-NFAC1) - I31*N11N2) / N11
        I1 = (IFAC-NFAC1) - I31*N11N2 - I21*N11
        ILEG1=NLEG12 + I31*N1N2+I21*N1+I1
        ILEG4=         I31*N11N2+I21*N11+I1
        ILEG2=ILEG4+N11N2
        ILEG3=ILEG1+1
      ELSEIF (IFAC.LE.NFAC) THEN
        I31= (IFAC1-NFAC12) / N11N21
        I21=((IFAC1-NFAC12) - I31*N11N21) / N11
        I1 = (IFAC-NFAC12) - I31*N11N21 - I21*N11
        ILEG1=        I31*N11N2+I21*N11+I1
        ILEG4=NLEG1 + I31*N1N21+I21*N1+I1
        ILEG2=ILEG4+1
        ILEG3=ILEG1+N11
      ELSE
C       MODSRF-23
        CALL ERROR ('MODSRF-23: Wrong IFAC.')
C       This error should not appear. Contact the author.
      ENDIF
      CALL MSGLEG(ILEG1,IP1,IP2)
      CALL MSCP(IP1,X1,X2,X3)
      CALL MSCP(IP2,X1,X2,X3)
C
      CALL MSGLEG(ILEG2,IP1,IP2)
      CALL MSCP(IP1,X1,X2,X3)
      CALL MSCP(IP2,X1,X2,X3)
C
      CALL MSGLEG(ILEG3,IP1,IP2)
      CALL MSCP(IP1,X1,X2,X3)
      CALL MSCP(IP2,X1,X2,X3)
C
      CALL MSGLEG(ILEG4,IP1,IP2)
      CALL MSCP(IP1,X1,X2,X3)
      CALL MSCP(IP2,X1,X2,X3)
C
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSCP(IPOIN,X1,X2,X3)
C
C-----------------------------------------------------------------------
C
      INTEGER IPOIN
      REAL X1,X2,X3
C     IPOIN ... Index of a point.
C     X1,X2,X3 ... Coordinates of the point.
C.......................................................................
C Common block /RAMC/ to store the information about points on
C structural interfaces and common block /MSC/ to store auxiliary
C quantities:
      INCLUDE 'modsrf.inc'
C modsrf.inc.
C ...........................
C     Auxiliary storage locations:
      INTEGER I31,I21,I11,IPOIN1
C.......................................................................
C
      IPOIN1=IPOIN-1
      I31= IPOIN1 / N1N2
      I21=(IPOIN1 - I31*N1N2) / N1
      I11= IPOIN  - I31*N1N2 - I21*N1 - 1
      X1=O1+FLOAT(I11)*D1
      X2=O2+FLOAT(I21)*D2
      X3=O3+FLOAT(I31)*D3
      RETURN
      END
C
C
C=======================================================================
C
      SUBROUTINE MSEROR(IERR)
C
C-----------------------------------------------------------------------
C
      INTEGER IERR
C     IERR ... Index of the error.
C.......................................................................
      IF (IERR.EQ.1) THEN
C       MODSRF-24
        CALL ERROR('MODSRF-24: Small array (I)RAM.')
C       Try to enlarge the dimension MRAM in the file
C       ram.inc. If this does not help,
C       contact the author.
      ELSEIF (IERR.EQ.2) THEN
C       MODSRF-25
        CALL ERROR('MODSRF-25: Small array JPT.')
C       Try to enlarge the dimension MJPT at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.3) THEN
C       MODSRF-26
        CALL ERROR('MODSRF-26: Small array IPTE.')
C       Try to enlarge the dimension MIPTE at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.4) THEN
C       MODSRF-27
        CALL ERROR('MODSRF-27: Small array JCN.')
C       Try to enlarge the dimension MJCN at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.5) THEN
C       MODSRF-28
        CALL ERROR('MODSRF-28: Small array JSP.')
C       Try to enlarge the dimension MJSP at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.6) THEN
C       MODSRF-29
        CALL ERROR('MODSRF-29: Small array JPOL.')
C       Try to enlarge the dimension MJPOL at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.7) THEN
C       MODSRF-30
        CALL ERROR('MODSRF-30: Small array JPOL.')
C       Try to enlarge the dimension MLJPOL at the beginning of this file.
C       If this does not help, contact the author.
      ELSEIF (IERR.EQ.8) THEN
C       MODSRF-05
        CALL ERROR('MODSRF-05: Interface not found.')
C       This might happen when the whole gridleg coincides with an
C       interface. If possible, slightly change the origin of
C       the grid. If this does not help, contact the author.
      ELSE
C       MODSRF-31
        CALL ERROR('MODSRF-31: Wrong IERR.')
C       This subroutine was invocated with wrong value of IERR.
C       This error should not appear, please contact the author.
      ENDIF
      END
C
C=======================================================================
C
      INCLUDE 'model.for'
C     model.for
      INCLUDE 'metric.for'
C     metric.for
      INCLUDE 'srfc.for'
C     srfc.for
      INCLUDE 'parm.for'
C     parm.for
      INCLUDE 'val.for'
C     val.for
      INCLUDE 'fit.for'
C     fit.for
      INCLUDE 'means.for'
C     means.for
      INCLUDE 'rkgs.for'
C     rkgs.for
      INCLUDE 'sep.for'
C     sep.for
      INCLUDE 'forms.for'
C     forms.for
      INCLUDE 'length.for'
C     length.for
      INCLUDE 'error.for'
C     error.for
C
C=======================================================================
C