Exemplo n.º 1
0
        public EruptionValues(Eruption erupt, Wind[] wind, Config config)
        {
            Guard.NotNull(erupt, "erupt");
            Guard.NotNull(wind, "wind");
            Guard.NotNull(config, "config");

            _config = config;
            SetEruptionValues(erupt, wind, config);
        }
Exemplo n.º 2
0
 private static void PrintWind(Wind[][] wind)
 {
     Console.WriteLine("Wind:");
     Console.WriteLine("\tDays: " + wind.Length);
     for (var i = 0; i < wind.Length; i++)
     {
         Console.WriteLine("\t\tDay: " + i);
         Console.WriteLine("\t\tLevels: " + wind[i].Length);
     }
 }
Exemplo n.º 3
0
 private Wind[][] GetWindArray(Config config)
 {
     var winds = new Wind[config.WindDays][];
     for (var i = 0; i < config.WindDays; i++)
     {
         winds[i] = new Wind[config.ColumnIntegrationSteps + 1];
         for (var j = 0; j <= config.ColumnIntegrationSteps; j++)
         {
             winds[i][j] = new Wind();
         }
     }
     return winds;
 }
Exemplo n.º 4
0
        // void set_eruption_values(ERUPTION *erupt, WIND *wind) { /* set_eruption_values */
        private void SetEruptionValues(Eruption erupt, Wind[] wind, Config config)
        {
            //PART_STEPS = (erupt->max_phi - erupt->min_phi) * 10;
            PartSteps = (int)Math.Abs((erupt.MaxPhi - erupt.MinPhi) * 10);

            //threshold = erupt->vent_height + (PLUME_RATIO * (erupt->max_plume_height - erupt->vent_height));
            Threshold = erupt.VentHeight + (config.Plume.Ratio * (erupt.MaxPlumeHeight - erupt.VentHeight));
            //SQRT_TWO_PI = sqrt(2.0 * pi); /* new line, 12-2-2010 */
            SqrtTwoPi = Math.Sqrt(2.0 * Config.Pi);

            //BETA_x_SQRT_TWO_PI = erupt->column_beta * SQRT_TWO_PI;
            BetaSqrtTwoPi = erupt.ColumnBeta * SqrtTwoPi;

            //TWO_BETA_SQRD = 2.0 * erupt->column_beta * erupt->column_beta;
            TwoBetaSqrd = 2.0 * erupt.ColumnBeta * erupt.ColumnBeta;

            //PDF_GRAINSIZE_DEMON1 = 1.0 / (2.506628 * erupt->sigma_phi); /* changed 12-02-2010 */
            PdfGrainSizeDemon1 = 1.0 / (2.506628 * erupt.SigmaPhi);

            //TWO_x_PART_SIGMA_SIZE = 2.0 * erupt->sigma_phi * erupt->sigma_phi;
            TwoPartSigmaSize = 2.0 * erupt.SigmaPhi * erupt.SigmaPhi;

            /*define the limits of integration */
            //ht_section_width = erupt->max_plume_height - erupt->vent_height; 
            var htSectionWidth = erupt.MaxPlumeHeight - erupt.VentHeight;
            //part_section_width = erupt->max_phi - erupt->min_phi;
            var partSectionWidth = erupt.MaxPhi - erupt.MinPhi;
            //ht_step_width = ht_section_width / (double)COL_STEPS;
            var htStepWidth = htSectionWidth / config.ColumnIntegrationSteps;
            //part_step_width = part_section_width / (double)PART_STEPS;
            var partStepWidth = partSectionWidth / PartSteps;

            /* steps for nomalization of probabilities */
            var totalPCol = GetTotalPCol(erupt, config, htSectionWidth, htStepWidth);

            var totalPPart = GetTotalPPart(erupt, partStepWidth);

            /* Normalization constant */
            var totalP = GetTotalP(totalPCol, totalPPart);

            /* End of normalization steps */

            /* Dynamically allocated table for storing integration data.
             * Used in the double integration steps below for each point considered.
             * */
            _table = CreateTableArray();

            double pmin = 10e6, pmax = 0.0;

            Logger.InfoFormat("\tpmax={0}", pmax);
            Logger.InfoFormat("\tpmin={0}", pmin);

            /* Start with the maximum particle size */
            //y = (erupt)->min_phi
            var y = erupt.MinPhi;
            for (var i = 0; i < PartSteps; i++)
            { /* PART_STEPS_LOOP */
                var partStepTable = _table[i, 0];
                //T[i][0].part_density  =  ParticleDensity(y);    
                partStepTable.SetPartDensity(ParticleDensity(y));
                //T[i][0].ashdiam = phi2m(y);
                partStepTable.SetAshDiam(Phi2M(y));

                /* the expected fraction of particles of this size based on given mean and std deviation */
                var partProb = pdf_grainsize(erupt.MeanPhi, y, partStepWidth);
                var cumFallTime = 0.0;
                var windX = 0.0;
                var windY = 0.0;

                /* Start at the height of the vent */
                var particleHt = erupt.VentHeight;
                for (var j = 0; j < config.ColumnIntegrationSteps; j++)
                { /* COL_STEPS_LOOP */
                    var table = _table[i, j];
                    /* define the small slice dz */
                    particleHt += htStepWidth;

                    /* 
                     * Calculate the time it takes a particle to fall from its release point
                     * in the column to the next column release point.
                     * */
                    //T[i][j].fall_time = PartFallTime(particle_ht, ht_step_width, T[i][0].ashdiam, T[i][0].part_density); 
                    table.SetFallTime(PartFallTime(particleHt, htStepWidth, partStepTable.GetAshDiam(), partStepTable.GetPartDensity()));

                    /* Particle diffusion time (seconds) */
                    //ht_above_vent = particle_ht - erupt->vent_height;
                    var htAboveVent = particleHt - erupt.VentHeight;

                    var temp = 0.2 * htAboveVent * htAboveVent;
                    //T[i][j].plume_diffusion_fine_particle = pow(temp, 0.4); /* 0.4 = 2.0/5.0 */
                    table.SetPlumeDiffusionFineParticle(Math.Pow(temp, 0.4));

                    //T[i][j].plume_diffusion_coarse_particle = 0.0032 * (ht_above_vent *  ht_above_vent) / DIFFUSION_COEFFICIENT; 
                    table.SetPlumeDiffusionCoarseParticle(0.0032 * (htAboveVent * htAboveVent) / config.DiffusionCoefficient);

                    /* 
                     * Sum the windspeed and wind_direction for each particle size 
                     * falling from each level. In the wind array, the first wind level
                     * gives wind speed and direction at the vent height. 
                     * Start with the next wind level, 
                     * so that we are using the wind speed and direction 
                     * starting from one step above the vent. 
                     * */

                    var windNextLevel = wind[j + 1];
                    //wind_x += T[i][j].fall_time * wind[j+1].windspeed * cos(wind[j+1].wind_dir);
                    windX += table.GetFallTime() * windNextLevel.GetWindSpeed() * Math.Cos(windNextLevel.GetWindDir());
                    //wind_y += T[i][j].fall_time * wind[j+1].windspeed * sin(wind[j+1].wind_dir);
                    windY += table.GetFallTime() * windNextLevel.GetWindSpeed() * Math.Sin(windNextLevel.GetWindDir());

                    //T[i][j].wind_sum_x = wind_x;
                    table.SetWindSumX(windX);
                    //T[i][j].wind_sum_y = wind_y;
                    table.SetWindSumY(windY);

                    /* 
                     * Accumulate the time it takes each particle size to descend
                     * from its release point down
                     * to its final resting place.This part of the code just
                     * calculates the fall_time from the release point to the
                     * height of the vent.
                     * The time it takes a particle to fall from the vent height
                     * to a grid cell will be calculated later.
                     * */
                    //cum_fall_time += T[i][j].fall_time;
                    cumFallTime += table.GetFallTime();
                    //T[i][j].total_fall_time = cum_fall_time;
                    table.SetTotalFallTime(cumFallTime);
                    //if (T[i][j].total_fall_time > pmax) pmax = T[i][j].total_fall_time;
                    if (cumFallTime > pmax)
                    {
                        pmax = table.GetTotalFallTime();
                    }
                    else
                    //if (T[i][j].total_fall_time < pmin) pmin = T[i][j].total_fall_time;
                    if (cumFallTime < pmin)
                    {
                        pmin = table.GetTotalFallTime();
                    }

                    /* the probability that a given grainsize will be released from a given height */
                    //col_prob = (*pdf)(particle_ht, j, erupt->column_beta, erupt->max_plume_height);
                    var colProb = config.Plume.PlumeModel == PlumeModel.UniformDistribution 
                        ? plume_pdf0(particleHt, j) 
                        : PlumePdf1(particleHt, j, erupt.ColumnBeta, erupt.MaxPlumeHeight);

                    /* Normalization is now done here */
                    //T[i][j].demon1 = (erupt->total_ash_mass * col_prob  * part_prob)/total_P;
                    table.SetDemon1((erupt.TotalAshMass * colProb * partProb) / totalP);

                    //T[i][j].particle_ht = particle_ht;
                    table.SetParticleHt(particleHt);
                    Logger.InfoFormat("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}\t{11}", new[] {
                              i,
                              j,
                              table.GetParticleHt(),
                              table.GetAshDiam(),
                              table.GetPartDensity(),
                              table.GetFallTime(),
                              table.GetPlumeDiffusionFineParticle(),
                              table.GetPlumeDiffusionCoarseParticle(),
                              table.GetTotalFallTime(),
                              table.GetWindSumX(),
                              table.GetWindSumY(),
                              table.GetDemon1()
                          });
                    /*      	
                      fprintf(log_file,
                      "%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\n",
                      T[i][j].particle_ht, 
                      T[i][j].ashdiam, 
                      T[i][j].part_density, 
                      T[i][j].fall_time,
                      T[i][j].plume_diffusion_fine_particle,
                      T[i][j].plume_diffusion_coarse_particle,
                      T[i][j].total_fall_time,
                      T[i][j].wind_sum_x,
                      T[i][j].wind_sum_y,
                      T[i][j].demon1);
                     */
                } /* END COL_STEPS_LOOP */

                Logger.Info(" ");
                /*     fprintf(log_file, "\n"); */
                y += partStepWidth; /* moved from beg of loop 12-02-2010 */

            } /* END PART_STEPS_LOOP */

            /*  	fprintf(log_file, "OUT\n"); */
            //  fprintf(stderr, "MIN particle fall time = %.1f\n", pmin);
            Logger.Info("MIN particle fall time = " + pmin);
            //  fprintf(stderr, "MAX particle fall time = %.1f\n", pmax);
            Logger.Info("MAX particle fall time = " + pmax);
        }
Exemplo n.º 5
0
        /*
         * ---------------------------------------------------------------------
         * FUNCTION:tephra_calc.c
         * 
         * Purpose: This function calculates and returns the expected accumulation
         * of volcanic ash (kg/m2) at a specific geogrphic location (x,y) due to an
         * eruption with specific input parameters. These points may be random or on
         * a UTM grid (m)
         * 
         * This implementation accounts for variation in wind velocity with height.
         * The model is discretized w.r.t. height and particle size.
         * 
         * This function is called for each point (x,y,) If more than one eruption
         * is involved, for example in a probabilistic analysis, the function is
         * called for each set of eruption parameters.
         * 
         * INPUTS: ERUPTION *erupt: pointer to array of eruption parameters POINT
         * *pt: pointer to an array of location specific parameters, WIND *level:
         * pointer to a day of wind data : height asl in m; wind speed in ms-1 wind
         * direction in degrees N
         * 
         * OUTPUTs: the value of the mass accumulated at the input location
         * (northing, easting) in kg/m2
         * 
         * a distribution of particle sizes the exact number of binss (i.e. sizes)
         * and phi size used per bin is an integer and is determined by
         * (erupt->max_phi - erupt->min_phi) each bin accumulates phi sizes up to
         * its integer size ex. bin[0] holds grainsizes [min_phi to min_phi+1)
         * *************************************************************************
         */
        //void tephra_calc(ERUPTION *erupt, POINT *pt, WIND *level, STATS *stats) { /* tephra_calc starts ... */
        // TODO : I have added EruptionValues, could replace Eruption with EruptionValues only?
        public void Calculate(Eruption erupt, Point pt, Wind[] level, Stats stats, EruptionValues eruptionValues)
        {
            //logger.info("IN tephra_calc ...");

            /* Initialize mass to zero */
            pt.SetMass(0.0);
            //wind_sum_x = 0.0;
            //wind_sum_y = 0.0;

            /* Transform the volcano location coordinate to 0,0 */
            var newXspace = pt.GetNorthing() - erupt.VolcanoNorthing;
            var newYspace = pt.GetEasting() - erupt.VolcanoEasting;

            /* Interpolate to find the wind speed and direction below the height of the vent.
             * Find one average wind speed and wind direction between vent and grid elevation point. 
             * The first values in the wind array give the wind speed and direction at the
             * vent height.
             * */
            var layer = erupt.VentHeight - pt.GetElevation();

            var windspeed = (level[0].GetWindSpeed() * pt.GetElevation()) / erupt.VentHeight;
            var cosWind = Math.Cos(level[0].GetWindDir()) * windspeed;
            var sinWind = Math.Sin(level[0].GetWindDir()) * windspeed;

            var bin = -1;
            double min = 10e6, max = 0.0;

            //logger.info("Beginning integration loops ...");
            //for (i = 0; i < PART_STEPS; i++) { /* PART_STEPS_LOOP */
            for (var i = 0; i < eruptionValues.PartSteps; i++)
            { /* PART_STEPS_LOOP */
              //fall_time_adj = 0.0;
                var fallTimeAdj = 0.0;
                /* Accumulate the particle sizes into bins of whole numbered phi sizes */
                //if (!(i % 10)) { 
                if ((i % 10) == 0)
                {
                    bin++;
                    //fprintf(log_file, "PART_STEP=%d phi[%d] = %g\n", i, bin, pt->phi[bin]);
                    //logger.debug("PART_STEP=" + i + " phi[" + bin + "] = " + pt.getPhi()[bin]);
                }

                /* 
                 * Modify the total fall time of each particle size (i) 
                 * by the time that it takes particle size (i) to descend from vent height to the grid cell. 
                 * This is only necessary when the elevation of the grid cell < elevation of the vent.
                 * */
                if (layer > 0)
                {
                    //fall_time_adj = PartFallTime(erupt->vent_height, layer, T[i][0].ashdiam, T[i][0].part_density);
                    fallTimeAdj = eruptionValues.PartFallTime(erupt.VentHeight, layer, eruptionValues.GetT()[i, 0].GetAshDiam(), eruptionValues.GetT()[i, 0].GetPartDensity());
                    //fprintf(log_file, "%d %g %g\n",  i, layer, fall_time_adj) ;
                    //logger.debug("\tS=" + i + " layer=" + layer + " fall_time_adj=" + fall_time_adj);
                }

                //for (j = 0; j < COL_STEPS; j++) { /* COL_STEPS_LOOP */
                for (var j = 0; j < _config.ColumnIntegrationSteps; j++)
                { /* COL_STEPS_LOOP */
                  //total_fall_time = T[i][j].total_fall_time + fall_time_adj;
                    var totalFallTime = eruptionValues.GetT()[i, j].GetTotalFallTime() + fallTimeAdj;
                    //logger.debug("\tS=" + i + ","+ j + " total_fall_time=" + total_fall_time);
                    // fprintf(stderr, "%g %g %g ", T[i][j].total_fall_time, total_fall_time, fall_time_adj);
                    //logger.debug("\tPART_STEP=" + i + " layer=" + layer + " fall_time_adj=" + fall_time_adj);

                    /* Sum the adjustments (windspeed and wind_direction) 
                     * for each particle size  falling from each level.
                     */
                    /* removed 2 lines, 12-2-2010
                    wind_sum_x = cos_wind * fall_time_adj * windspeed;
                    wind_sum_y = sin_wind * fall_time_adj * windspeed;
                     */
                    /* change 2 lines, 12-2-2010 */
                    var windSumX = cosWind * fallTimeAdj;
                    var windSumY = sinWind * fallTimeAdj;

                    //logger.debug("\tPART_STEP=" + i + " wind_sum_x=" + wind_sum_x + " wind_sum_y=" + wind_sum_y);
                    /* Now add the summed adjustments to the already summed
                     * windspeeds and directions 
                     * and 
                     * Account for the wind:
                     * Find the average windspeed in the x and y directions
                     * over the total fall time.
                     * */
                    //average_windspeed_x = (T[i][j].wind_sum_x + wind_sum_x)/total_fall_time;
                    var averageWindspeedX = (eruptionValues.GetT()[i, j].GetWindSumX() + windSumX) / totalFallTime;

                    //average_windspeed_y = (T[i][j].wind_sum_y + wind_sum_y)/total_fall_time;
                    var averageWindspeedY = (eruptionValues.GetT()[i, j].GetWindSumY() + windSumY) / totalFallTime;

                    /* If zero, make windspeed a very small value (cannot divide by zero in next step) */
                    //if (!average_windspeed_x) average_windspeed_x = .001;
                    if (averageWindspeedX == 0) averageWindspeedX = .001;
                    //if (!average_windspeed_y) average_windspeed_y = .001;
                    if (averageWindspeedY == 0) averageWindspeedY = .001;

                    double averageWindDirection;
                    /* Find the average wind direction (direction of the velocity vector) */
                    if (averageWindspeedX < 0)
                    {
                        //average_wind_direction = atan(average_windspeed_y/average_windspeed_x ) + pi;
                        averageWindDirection = Math.Atan(averageWindspeedY / averageWindspeedX) + Config.Pi;
                    }
                    else {
                        //average_wind_direction = atan(average_windspeed_y/average_windspeed_x);
                        averageWindDirection = Math.Atan(averageWindspeedY / averageWindspeedX);
                    }
                    //logger.debug("\tPART_STEP=" + i + " average_wind_direction=" + average_wind_direction);
                    /* Find the average windspeed ( magnitude of the velocity vector) */
                    //average_windspeed = sqrt(average_windspeed_x*average_windspeed_x + average_windspeed_y*average_windspeed_y);
                    var averageWindspeed = Math.Sqrt(averageWindspeedX * averageWindspeedX + averageWindspeedY * averageWindspeedY);
                    //logger.debug("\tPART_STEP=" + i + " average_windspeed=" + average_windspeed);

                    if (totalFallTime > max) max = totalFallTime;
                    if (totalFallTime < min) min = totalFallTime;

                    /* calculate the value of sigma (dispersion) based on total_fall_time  
                     * to acct for the change in the shape of the column with ht - increasing radius 
                     */
                    //ht_above_vent = T[i][j].particle_ht - erupt->vent_height;
                    //double ht_above_vent = eruptionValues.getT()[i][j].getParticleHt() - erupt.getVentHeight();

                    double sigma;
                    /* falltime for fine particles */
                    //if (total_fall_time >= FALL_TIME_THRESHOLD) {
                    if (totalFallTime >= _config.FallTimeThreshold)
                    {
                        //sigma = EDDY_CONST_x_8_div_5 * pow((total_fall_time + T[i][j].plume_diffusion_fine_particle), 2.5);
                        sigma = (8.0 * _config.EddyDiff / 5.0) * Math.Pow((totalFallTime + eruptionValues.GetT()[i, j].GetPlumeDiffusionFineParticle()), 2.5);
                        //fprintf(stderr,"f");
                    }
                    else {
                        /* falltime for coarse particles */
                        //sigma = 4.0 * DIFFUSION_COEFFICIENT * (total_fall_time + T[i][j].plume_diffusion_coarse_particle);
                        sigma = 4.0 * _config.DiffusionCoefficient * (totalFallTime + eruptionValues.GetT()[i, j].GetPlumeDiffusionCoarseParticle());
                        //fprintf(stderr, "c");
                    }

                    var demon2 = Config.Pi * sigma;

                    /* Modify fall time by the variation of wind velocity with height */
                    //				demon3 = 
                    //				strat_average( average_wind_direction, 
                    //	      	             average_windspeed,             
                    //					             new_xspace, new_yspace, 
                    //					             total_fall_time,
                    //					             sigma); 
                    var demon3 = strat_average(averageWindDirection,
                            averageWindspeed,
                            newXspace, newYspace,
                            totalFallTime,
                            sigma);
                    /*
                                if (!demon2 || isnan(demon2) || isinf(demon2) || isnan(demon3) || isinf(demon3)) {
                                    fprintf(stderr, 
                            "[%d][%d] layer= %.1f totalfalltime=%g [falltimeadj=%g] demon1=%g demon2=%g demon3=%g sigma=%g\n",
                            i,j, layer,total_fall_time, fall_time_adj, T[i][j].demon1, demon2, demon3, sigma);
                            exit(-1);
                                }
                     */
                    //ash_fall = (T[i][j].demon1 / demon2) * demon3;
                    var ashFall = (eruptionValues.GetT()[i, j].GetDemon1() / demon2) * demon3;
                    //pt->mass += ash_fall;
                    pt.SetMass(pt.GetMass() + ashFall);
                    //pt->phi[bin] += ash_fall;
                    pt.GetPhi()[bin] += ashFall;
                    //fprintf(stderr, "\n");

                    //logger.debug("\tS=" + i + ", " + j + " layer=" + layer + "d1=" + eruptionValues.getT()[i][j].getDemon1() + " d2=" + demon2 + " d3=" + demon3 + " sigma=" + sigma + " ash_fall=" + ash_fall);
                }
                //logger.debug("S=" + i + " mass=" + pt.getMass() + " phi[" + bin + "]=" + pt.getPhi()[bin]);
            }
            //	#ifdef _PRINT
            //	  fprintf(log_file, "PART_STEP=%d phi[%d] = %g\n", i, bin, pt->phi[bin]);
            //	  fprintf(log_file, "OUT\n");
            //	#endif
            //stats->min_falltime = min;
            stats.SetMinFallTime(min);
            //stats->max_falltime = max;
            stats.SetMaxFallTime(max);
        }