Exemplo n.º 1
0
/******************************************************************************
 *                                                                            *
 ******************************************************************************/
void add_this_layer(AED_REAL *VMsum, AED_REAL *Tsum,
                    AED_REAL *Ssum, AED_REAL *VMLOC, AED_REAL *TMLOC,
                    AED_REAL *SMLOC, AED_REAL *DFLOC, int idx)
{
    AED_REAL Layer_Mass;

    Layer_Mass = Lake[idx].Density * Lake[idx].LayerVol;

    *VMsum += Layer_Mass;
    *Tsum  += (Lake[idx].Temp * Layer_Mass);
    *Ssum  += (Lake[idx].Salinity * Layer_Mass);

    *VMLOC = *VMsum;            //Combined volumetic mass
    *TMLOC = *Tsum / (*VMLOC);  //Combined temperature
    *SMLOC = *Ssum / (*VMLOC);  //Combined salinity

    *DFLOC = calculate_density(*TMLOC,*SMLOC);
}
Exemplo n.º 2
0
/******************************************************************************
 * This subroutine checks the reservoir layer structure for compliance        *
 * with the specified volume and depth limits.  Adjustments are made          *
 * as required. Layer structure is checked for minimum limits first,          *
 * combining the  checked layer with the smallest adjacent layer if           *
 * necessary. This may result in the formation of a layer exceeding           *
 * maximum limits.Layer structure is checked for maximum limits,              *
 * splitting the checked layer if necessary.  After splitting, the            *
 * resulting layers will all be greater than their minimum limits             *
 * provided VMax >= 2 VMin.  The default value is VMax = 2 VMin.              *
 * split depths ! volumes                                                     *
 *                                                                            *
 * DMax                maximum allowable layer thickness                      *
 * DMin                minimum allowable layer thickness                      *
 * KB                  first layer above split or mixed layers                *
 * KT                  new top layer number                                   *
 * VMax                max allowed volume                                     *
 * VMin                min allowed volume                                     *
 ******************************************************************************/
void check_layer_thickness(void)
{
//LOCALS
    AED_REAL D;
    AED_REAL DELDP;
    AED_REAL V;         // Split volume
    AED_REAL Vdown;     // Volume of layer below amalgamation
    AED_REAL Vup;       // Volume of layer above amalgamation

    int i;
    int iadd;
    int j;
    int wqidx;
    int jold;
    int k;
    int KB;
    int KLAST;
    int KT;
    int M;        // Number of layers after splitting
    int VSUMCHK;

/*----------------------------------------------------------------------------*/
    dbgprt(" CHKLAY 01 lake[44].depth = %20.15f\n", Lake[44].Height);

    //# Check against vmin
    KLAST=botmLayer;
    // while (1) { //
    while (NumLayers > 1) { // stop at 1 layer
        for (i = KLAST; i <= surfLayer; i++) {
            if (i == botmLayer)
                 DELDP = Lake[i].Height;
            else
                 DELDP = Lake[i].Height - Lake[i-1].Height;
            if ((Lake[i].LayerVol < VMin) && (DELDP < DMin)) break;
        }

        if (i > surfLayer) break;

        // Layer i is amalgamated with its smallest neighbour
        if (i == botmLayer) {
            Vup = zero;
            Vdown = 1.0;
        } else {
            if (i == surfLayer) {
                Vup = 1.0;
                Vdown = zero;
            } else {
                Vup = Lake[i+1].LayerVol;
                Vdown = Lake[i-1].LayerVol;
            }
        }

        j = i;
        if (Vup > Vdown) j = i-1;

        Lake[j].Salinity = combine(Lake[j].Salinity,   Lake[j].LayerVol,   Lake[j].Density,
                                   Lake[j+1].Salinity, Lake[j+1].LayerVol, Lake[j+1].Density);
        Lake[j].Temp = combine(Lake[j].Temp,   Lake[j].LayerVol,   Lake[j].Density,
                               Lake[j+1].Temp, Lake[j+1].LayerVol, Lake[j+1].Density);

        for (wqidx = 0; wqidx < Num_WQ_Vars; wqidx++)
            _WQ_Vars(wqidx,j) = combine_vol(_WQ_Vars(wqidx,j), Lake[j].LayerVol, _WQ_Vars(wqidx,j+1), Lake[j+1].LayerVol);

        Lake[j].Density = calculate_density(Lake[j].Temp, Lake[j].Salinity);
        Lake[j].LayerVol = Lake[j].LayerVol + Lake[j+1].LayerVol;
        Lake[j].Height = Lake[j+1].Height;
        Lake[j].Vol1 = Lake[j+1].Vol1;
        Lake[j].LayerArea = Lake[j+1].LayerArea;
        Lake[j].Epsilon = Lake[j+1].Epsilon;
        KLAST=j;

        // Renumber layers j+2,j+3,---,surfLayer
        if (j != (surfLayer-1)) {
            KT = surfLayer-1;
            KB = j + 1;
            for (k = KB; k <= KT; k++) {
                Lake[k].Height = Lake[k+1].Height;
                Lake[k].Density = Lake[k+1].Density;
                Lake[k].Temp = Lake[k+1].Temp;
                Lake[k].Salinity = Lake[k+1].Salinity;

                for (wqidx=0; wqidx < Num_WQ_Vars; wqidx++)
                    _WQ_Vars(wqidx, k) = _WQ_Vars(wqidx, k+1);

                Lake[k].LayerVol = Lake[k+1].LayerVol;
                Lake[k].Vol1 = Lake[k+1].Vol1;
                Lake[k].LayerArea = Lake[k+1].LayerArea;
                Lake[k].Epsilon = Lake[k+1].Epsilon;
            }
        }
        NumLayers--;
    }

    // here when all layers have been checked for VMin, DMin
    if (surfLayer != botmLayer) {
        for (i = botmLayer+1; i <= surfLayer; i++)
            Lake[i].MeanHeight=(Lake[i].Height+Lake[i-1].Height)/ 2.0;
    }
    Lake[botmLayer].MeanHeight = Lake[botmLayer].Height/ 2.0;

    // check layers for VMax
    //sgs Flag to prevent top layer splitting more than once
    VSUMCHK = FALSE;
    KLAST=botmLayer;
    while(1) {
        if (VSUMCHK) return;


        for (i = KLAST; i <= surfLayer; i++) {
            if (i == botmLayer)
                DELDP=Lake[i].Height;
            else
                DELDP=Lake[i].Height-Lake[i-1].Height;

            if (i == surfLayer) VSUMCHK = TRUE;

            if (Lake[i].LayerVol > VMax || DELDP > DMax) break;
        }

        // return to calling program when all layers have been checked
        if (i > surfLayer) return;

        // layer i is split into M layers
        M = 2;
        while (1) {
            V = Lake[i].LayerVol/M;
            D = DELDP/M;
            if (V <= VMax && D <= DMax) break;
            M++;

            // if M+surfLayer is greater than the max no. of layers, a mistake will occur
            //  - an array bound error
            if (M + NumLayers > MaxLayers) {
                fprintf(stderr, "Array bounds error - too many layers. NumLayers = %d, M = %d\n", NumLayers, M);
                fprintf(stderr, "i = %d V = %20.15f VMax = %20.15f D = %20.15f DMax = %20.15f\n",
                                      i, V, VMax, D, DMax);
                exit(1);
            }
        }

        // renumber layers above split. iadd is the number of added layers
        // j is the new layer number, jold is the old layer number
        // include water quality
        iadd = M - 1;
        KLAST = i;
        if (i != surfLayer) {
            KT = surfLayer+iadd;
            KB = i+M;
            for (j = KT; j >= KB; j--) {
                jold = j-iadd;
                Lake[j].Vol1 = Lake[jold].Vol1;
                Lake[j].Density = Lake[jold].Density;
                Lake[j].Temp = Lake[jold].Temp;
                Lake[j].Salinity = Lake[jold].Salinity;

                for (wqidx = 0; wqidx < Num_WQ_Vars; wqidx++)
                    _WQ_Vars(wqidx,j) = _WQ_Vars(wqidx,jold);

                Lake[j].LayerVol = Lake[jold].LayerVol;
                Lake[j].Epsilon = Lake[jold].Epsilon;
            }
        }

        // process the added layers, include water quality
        for (k=i; k <= i+iadd; k++) {
            Lake[k].LayerVol = V;
            if (k == botmLayer)
                Lake[k].Vol1=Lake[k].LayerVol;
            else
                Lake[k].Vol1=Lake[k-1].Vol1+Lake[k].LayerVol;

            Lake[k].Density = Lake[i].Density;
            Lake[k].Temp = Lake[i].Temp;
            Lake[k].Salinity = Lake[i].Salinity;

            for (wqidx = 0; wqidx < Num_WQ_Vars; wqidx++)
                _WQ_Vars(wqidx,k)=_WQ_Vars(wqidx,i);

            Lake[k].Epsilon = Lake[i].Epsilon;
        }
        NumLayers += iadd;

        // get new depths for layers i thru surfLayer
        resize_internals(2,i);
    }
}
Exemplo n.º 3
0
/******************************************************************************
 #CAB#  These comments are clearly WRONG!                                     *
 * This subroutine finds the level of Neutral Bouyancy for a given inflow     *
 * and returns the layer number (i), the half-thickness (B0), basin length    *
 * at the intrusion midpoint (AL), basin width at the intrusion               *
 * midpoint, and the mean intrusion velocity (UINF) in m/s.                   *
 ******************************************************************************/
void insert(AED_REAL q, AED_REAL di, AED_REAL bsl, AED_REAL temp, AED_REAL salt,
                             AED_REAL *wqx, int ntims, AED_REAL *width, int *ll)
{
    AED_REAL AHLE;
    AED_REAL AL;
    AED_REAL ALSQ;
    AED_REAL BL;
    AED_REAL B0;
    AED_REAL DBB,DELT,DELB;
    AED_REAL DHLE;
    AED_REAL DT;
#ifndef _VISUAL_C_
    // The visual c compiler doesn't like this so must malloc manually
    AED_REAL DVR[MaxLayers];
#else
    AED_REAL *DVR;
#endif
    AED_REAL DZ;
    AED_REAL F;
    AED_REAL GD;
    AED_REAL GR;
    AED_REAL R;
    AED_REAL TDASH;
    AED_REAL UINF;
    AED_REAL VISCOS;
    AED_REAL XN;
    AED_REAL XNSQ;
    AED_REAL ZP,ZT,ZB;

    int wqidx;
    int i,j,k;
    int iz;
    int JB,JT;
    int KX,KY;
    int NB1;
    int NT1;

/*----------------------------------------------------------------------------*/

#ifdef _VISUAL_C_
    DVR = malloc(sizeof(AED_REAL) * MaxLayers);
#endif

    DELT=0.;
    DELB=0.;

    for (iz = botmLayer; iz <= surfLayer; iz++)
       if (Lake[iz].Height > 0.) break;
    if (iz > surfLayer) iz = surfLayer;

    DHLE = Lake[iz].Height;
    AHLE = Lake[iz].LayerArea;

    if (di <= Lake[surfLayer].Density) {
        // Here for surface overflow
        i = surfLayer;
        *ll = i;
        B0 = (Lake[surfLayer].Height-Lake[surfLayer-1].Height)/ 2.0;
        AL = LenAtCrest;
        if (*width <= 1E-7) *width = Lake[surfLayer].LayerArea / AL;
        UINF = q / ( 2.0 * B0 * (*width));
    } else {
        // Find level of neutral buoyancy
        for (i = surfLayer; i > botmLayer; i--)
            if (di <= Lake[i-1].Density) break;

        if (i <= botmLayer) {
            //  Here for underflow
            i = botmLayer;
            *ll = i;
            AL = DHLE/sin(bsl);
            if ((*width) <= 1E-7) (*width) = AHLE / AL;
            B0 = (DHLE/ 2.0)/ 2.0;
            UINF = q / ( 2.0 * B0 * (*width));
        } else {
            //  Here for intrusion
            JT = i;
            *ll = i;
            JB = i-1;
            AL = Lake[i].Height/sin(bsl);
            ALSQ = sqr(AL);
            if ((*width) <= 1E-7) (*width) = Lake[i].LayerArea/AL;

            while(1) {
                DT = Lake[JT].MeanHeight;
                DBB = Lake[JB].MeanHeight;
                DZ = DT - DBB;
                XNSQ = g*(Lake[JB].Density-Lake[JT].Density)/(di*DZ);
                if (XNSQ  <=  zero)
                    //  Here for unstable stratification
                    BL=AL;
                else {
                    //  here for stable stratification
                    XN = sqrt(XNSQ);
                    F = q/((*width)*ntims*XN*ALSQ);
                    VISCOS = Lake[i].Epsilon * 20.0;
                    if (VISCOS <= 0.) VISCOS=Visc;
                    GR = XNSQ*sqr(ALSQ)/sqr(VISCOS);

                    R = F*pow(GR,(1.0/3.0));
                    TDASH=ntims*XN/(pow(GR,(1.0/6.0)));
                    R /= TDASH;
                    if (R > 1.)
                        BL = 0.44*TDASH*AL*sqrt(R);
                    else
                        BL = 0.57*AL*pow(R, (3.0/ 2.0))*pow((TDASH/R), (5.0/6.0));

                    BL = MIN(BL,AL);
                    if (BL < 1.0) BL = 1.0;
                }

                // B0 is 1/2 the intrusion thickness
                B0 = q/((*width)*BL);
                if (B0 > DZ) {
                    if ( !((JT == surfLayer) && (JB == botmLayer)) ) {
                        if (JT != surfLayer) JT++;
                        if (JB != botmLayer) JB--;
                        continue;
                    }
                }
                break;
            }

            if (Lake[i].Height < (DHLE + 1.0)) {
                AL = DHLE/sin(bsl);
                if ((*width) <= 1E-7) (*width) = AHLE / AL;
                B0 = (DHLE+ 2.0)/ 2.0;
            }
            UINF = q/( 2.0*B0*(*width));
        }
    }

    //  Mix the inflow with the appropriate layers.
    NT1=i;
    ZP=Lake[i].MeanHeight;
    if ( ! (i > botmLayer && i < surfLayer) ) {
        //  Here for underflow, overflow, or fully mixed
        NB1=i;
        DVR[i]=q;
    } else {
        // Here for intrusion
        while(1) {
            NT1++;
            DELT = 0.0;
            if (NT1  !=  surfLayer) {
                GD=gprime(Lake[NT1].Density,Lake[i].Density);
                if (GD > zero) DELT = 0.15 * pow((UINF/(ntims)),2) / GD;
                if (DELT > (Lake[NT1].MeanHeight-ZP) || GD <= zero) continue;
                if (Lake[NT1-1].Height > (ZP+DELT)) NT1--;
            }
            break;
        }

        ZT=Lake[NT1].Height;
        NB1=i;
        while(1) {
            NB1--;
            if (NB1 != botmLayer) {
                GD = gprime(Lake[i].Density,Lake[NB1].Density);
                if (GD > zero) DELB = 0.15 * sqr((UINF/(ntims))) / GD;
                if (DELB > (ZP-Lake[NB1].MeanHeight) || GD <= zero) continue;
                if (Lake[NB1].Height < (ZP-DELB)) NB1++;
            }
            break;
        }

        ZB = zero;
        if (NB1 > botmLayer) ZB = Lake[NB1-1].Height;
        if (NB1 == NT1) {
            // Here if intrusion is entirely within layer i
            DVR[NB1]=q;
        } else {
            // Aportion inflow amongst layers NB1,NB1+1,---,NT1
            DELT = ZT - ZP;
            DELB = ZP - ZB;
            if (NB1 != i) {
                DVR[NB1]=q*(Lake[NB1].Height-ZB+DELB*sin(Pi*(Lake[NB1].Height-ZP)/DELB)/Pi)/(ZT-ZB);
                if (NB1 != (i-1)) {
                    KX = NB1+1;
                    KY = i-1;
                    for (k = KX; k <= KY; k++)
                        DVR[k]=q*(Lake[k].Height-Lake[k-1].Height+DELB *
                            (sin(Pi*(ZP-Lake[k-1].Height)/DELB)-sin(Pi*(ZP-Lake[k].Height)/DELB))/Pi)/(ZT-ZB);
                }
            }
            DVR[i]=q*(ZP-Lake[i-1].Height+DELB*sin(Pi*(ZP-Lake[i-1].Height)/DELB)/Pi)/(ZT-ZB);
            DVR[i]=DVR[i]+q*(Lake[i].Height-ZP+DELT*sin(Pi*(Lake[i].Height-ZP)/DELT)/Pi)/(ZT-ZB);
            if (NT1 != i) {
                if (NT1 != (i+1)) {
                    KX=i+1;
                    KY=NT1-1;
                    for (k = KX; k<=KY; k++)
                        DVR[k]=q*(Lake[k].Height-Lake[k-1].Height+DELT*(sin(Pi*(Lake[k].Height-ZP)/
                                  DELT)-sin(Pi*(Lake[k-1].Height-ZP)/DELT))/Pi)/(ZT-ZB);
                }
                DVR[NT1]=q*(ZT-Lake[NT1-1].Height+DELT*sin(Pi*(ZP-Lake[NT1-1].Height)/DELT)/Pi)/(ZT-ZB);
            }
        }
    }

    // Insert inflow into reservoir and adjust layer properties
    // Include water quality and particles
    for (k = NB1; k <= NT1; k++) {
        Lake[k].Temp = combine(Lake[k].Temp,Lake[k].LayerVol,Lake[k].Density, temp,DVR[k],di);
        Lake[k].Salinity = combine(Lake[k].Salinity,Lake[k].LayerVol,Lake[k].Density,salt,DVR[k],di);

        for (wqidx = 0; wqidx < Num_WQ_Vars; wqidx++)
            _WQ_Vars(wqidx,k) = combine_vol(_WQ_Vars(wqidx,k),Lake[k].LayerVol,wqx[wqidx],DVR[k]);

        Lake[k].Density=calculate_density(Lake[k].Temp,Lake[k].Salinity);
        Lake[k].LayerVol=Lake[k].LayerVol+DVR[k];
    }

    Lake[botmLayer].Vol1 = Lake[botmLayer].LayerVol;
    if (surfLayer != botmLayer) {
        for (j = (botmLayer+1); j <= surfLayer; j++)
            Lake[j].Vol1 = Lake[j-1].Vol1 + Lake[j].LayerVol;
    }

#ifdef _VISUAL_C_
    free(DVR);
#endif
}
Exemplo n.º 4
0
/******************************************************************************
 * From the given physical data evaluates arrays of depths and areas          *
 * corresponding to an array of volumes (icode=2) or arrays of volume         *
 * and areas from depths (icode=1) starting at layer LNU                      *
 ******************************************************************************/
void resize_internals(int icode, int lnu)
{
   AED_REAL VolSum, x, y;

   int i, j, ij, k, l, ln;

//-------------------------------------------------------------------------------

    ln = lnu;
    if (icode == 1) {
        /**********************************************************************
         * Find volumes and areas given depths; ij points to storage table    *
         * entry closest to but less than the given depth, Y is the relative  *
         * location of DEPTH between storage table entries ij and ij+1.       *
         * Begin by calculating the total volume in the layer structure.      *
         **********************************************************************/
        VolSum = 0.0;
        for (k = 0; k < NumInf; k++)
            VolSum += Inflows[k].TotIn;

 //     while(1) {
        while(NumLayers > 1) { // stop at 1
            one_layer(surfLayer, MphLevelVol, dMphLevelVol);

            Lake[surfLayer].Vol1 -= VolSum;

            /* compute to one below current surface layer */
            for (i = ln; i < surfLayer; i++)
                one_layer(i, MphLevelVoldash, dMphLevelVolda);

            if (surfLayer <= botmLayer ||
                             Lake[surfLayer].Vol1 > Lake[surfLayer-1].Vol1)
                break;

            Lake[surfLayer-1].Vol1 = Lake[surfLayer].Vol1 + VolSum;
            Lake[surfLayer-1].LayerArea = Lake[surfLayer].LayerArea;
            Lake[surfLayer-1].Height = Lake[surfLayer].Height;
            Lake[surfLayer-1].Temp =
                    combine(Lake[surfLayer-1].Temp, Lake[surfLayer-1].LayerVol, Lake[surfLayer-1].Density,
                            Lake[surfLayer].Temp,   Lake[surfLayer].LayerVol,   Lake[surfLayer].Density);
            Lake[surfLayer-1].Salinity =
                    combine(Lake[surfLayer-1].Salinity, Lake[surfLayer-1].LayerVol, Lake[surfLayer-1].Density,
                            Lake[surfLayer].Salinity,   Lake[surfLayer].LayerVol,   Lake[surfLayer].Density);
            Lake[surfLayer-1].Density = calculate_density(Lake[surfLayer-1].Temp, Lake[surfLayer-1].Salinity);

            NumLayers--;
            if (surfLayer < ln) {
                if (--ln < botmLayer) {
                    fprintf(stderr,"surface layer less than bottom layer.\n");
                    exit(1);
                }
            }
        }
    } else {
        /**********************************************************************
         * calculate depths given volumes; J points to storage table volume   *
         * closest to but not greater than the given layer volume             *
         **********************************************************************/
        VolSum = Lake[surfLayer].Vol1;
        for (i = 0; i < NumInf; i++)
            VolSum += Inflows[i].TotIn;

        j = 0;
        while (j < Nmorph) {
            if (VolSum <= MphLevelVol[j]) {
                j--;
                break;
            }
            j++;
        }
        if (j >= Nmorph) j = Nmorph - 1;
        Lake[surfLayer].Height = ((j+1) + ((VolSum - MphLevelVol[j]) / dMphLevelVol[j])) / 10.;

        if (lnu <= botmLayer) {
            l = 0;
            j = 0;

            /* find lowest layer (L) whose volume exceeds the first table entry */
            while (Lake[l].Vol1 <= MphLevelVoldash[0]) {
                Lake[l].Height = (Lake[l].Vol1 / MphLevelVoldash[0]) / 10.;
                l++;
            }
        } else {
            x = Lake[lnu-1].Height * 10.;
            y = AMOD(x, 1.0);
            j = (x - y) - 1;
            l = lnu;
        }

        /* comupute to one below current surface */
        for (k = l; k < surfLayer; k++) {
            while (j < Nmorph) {
                if (Lake[k].Vol1 <= MphLevelVoldash[j]) {
                    j--;
                    break;
                }
                j++;
            }
            if (j >= Nmorph) j = Nmorph - 1;

            Lake[k].Height = ((j+1) + (Lake[k].Vol1 - MphLevelVoldash[j]) / dMphLevelVolda[j]) / 10.;
        }

        //# determine areas
        for (i = lnu; i <= surfLayer; i++) {
            x = Lake[i].Height * 10.;
            y = AMOD(x, 1.0);
            ij = (x - y) - 1;
            if (ij >= Nmorph) ij = Nmorph - 1;

            if (ij != -1) Lake[i].LayerArea = MphLevelArea[ij] + y * dMphLevelArea[ij];
            if (ij == -1) Lake[i].LayerArea = MphLevelArea[0] * Lake[i].Height * 10.;
        }
    }

    //# calculate layer volumes and mean depths
    ln = lnu;
    if (lnu == botmLayer) {
        Lake[botmLayer].LayerVol  = Lake[botmLayer].Vol1;
        Lake[botmLayer].MeanHeight = Lake[botmLayer].Height / 2.;
        ln = lnu+1;
    }

    for (i=ln; i <= surfLayer; i++) {
        Lake[i].LayerVol  = Lake[i].Vol1 - Lake[i-1].Vol1;
        Lake[i].MeanHeight = (Lake[i].Height + Lake[i-1].Height) / 2.;
    }
}
Exemplo n.º 5
0
Arquivo: node.cpp Projeto: brbr520/LBM
// catch-all function to update macroscopic properties of a node
void Node::update_macroscopic_properties(void) {
    calculate_density();
    calculate_velocity();
    calculate_feq();
}