SeismicModel.cpp

Go to the documentation of this file.
00001 #include "SeismicModel.h"
00002 #include <algorithm>
00003 #include <fstream>
00004 #include <iostream>
00005 #include <numeric>
00006 #include <cassert>
00007 
00008 using namespace std;
00009 
00010 namespace gplib
00011   {
00012 
00013     SeismicModel::SeismicModel(const int nlayers) :
00014       SourceDepth(0.0), dt(0.0), npts(0)
00015       {
00016         Init(nlayers);
00017       }
00018 
00019     SeismicModel::~SeismicModel()
00020       {
00021       }
00022 
00023     SeismicModel::SeismicModel(const SeismicModel& source)
00024       {
00025         //when we use the copy constructor the vectors
00026         //of the new object are empty so we can use a back_inserter
00027         copy(source.PVelocity.begin(), source.PVelocity.end(), back_inserter(
00028             this->PVelocity));
00029         copy(source.SVelocity.begin(), source.SVelocity.end(), back_inserter(
00030             this->SVelocity));
00031         copy(source.Density.begin(), source.Density.end(), back_inserter(
00032             this->Density));
00033         copy(source.Thickness.begin(), source.Thickness.end(), back_inserter(
00034             this->Thickness));
00035         copy(source.Qp.begin(), source.Qp.end(), back_inserter(this->Qp));
00036         copy(source.Qs.begin(), source.Qs.end(), back_inserter(this->Qs));
00037         SourceDepth = source.SourceDepth;
00038         dt = source.dt;
00039         npts = source.npts;
00040       }
00041 
00042     SeismicModel& SeismicModel::operator=(const SeismicModel& source)
00043       {
00044         if (this == &source)
00045           return *this;
00046         const int nelements = source.PVelocity.size();
00047         //for the regular copy operator we have to delete old data
00048         //so we allocate new space and copy the elements
00049         PVelocity.assign(nelements, 0);
00050         SVelocity.assign(nelements, 0);
00051         Density.assign(nelements, 0);
00052         Thickness.assign(nelements, 0);
00053         Qp.assign(nelements, 0);
00054         Qs.assign(nelements, 0);
00055 
00056         copy(source.PVelocity.begin(), source.PVelocity.end(),
00057             PVelocity.begin());
00058         copy(source.SVelocity.begin(), source.SVelocity.end(),
00059             SVelocity.begin());
00060         copy(source.Density.begin(), source.Density.end(), Density.begin());
00061         copy(source.Thickness.begin(), source.Thickness.end(),
00062             Thickness.begin());
00063         copy(source.Qp.begin(), source.Qp.end(), Qp.begin());
00064         copy(source.Qs.begin(), source.Qs.end(), Qs.begin());
00065         SourceDepth = source.SourceDepth;
00066         dt = source.dt;
00067         npts = source.npts;
00068         return *this;
00069       }
00070 
00071     void SeismicModel::Init(const int nlayers)
00072       {
00073         //with this function we can easily allocate
00074         //elements for the different vectors
00075         PVelocity.assign(nlayers, 0);
00076         SVelocity.assign(nlayers, 0);
00077         Density.assign(nlayers, 0);
00078         Thickness.assign(nlayers, 0);
00079         Qp.assign(nlayers, 0);
00080         Qs.assign(nlayers, 0);
00081       }
00082     //! Returns true if elem1 and elem2 agree within tolarance
00083     bool SeismicModel::FuzzComp(const double elem1, const double elem2,
00084         const double tolerance)
00085       {
00086         return (std::abs(elem1 - elem2) < tolerance);
00087       }
00088 
00089     int SeismicModel::FindLayer(const double depth)
00090       {
00091         //make sure the depth is positive
00092         assert(depth > 0.0);
00093         double currentbottom = 0;
00094         size_t i = 0;
00095         //we have to check that the bottom of the current layer
00096         //is deeper then what we are looking for
00097         //and that we don't look past the last index
00098         while (depth > currentbottom && i < Thickness.size())
00099           {
00100             currentbottom += Thickness.at(i);
00101             ++i;
00102           }
00103         //if we reach the end it means we are in the lower most
00104         //halfspace and return the index of the last layer
00105         return min(i, Thickness.size() - 1);
00106       }
00107 
00108     double SeismicModel::MatchSlowness(const double slowness,
00109         const tArrivalType mode)
00110       {
00111         double x = 0;
00112         double currdepth = 0;
00113         trealdata *velocity;
00114         const int sourcelayer = FindLayer(SourceDepth) - 1;
00115 
00116         if (mode == DirectS)
00117           velocity = &SVelocity;
00118         else
00119           velocity = &PVelocity;
00120         for (int i = 0; i < sourcelayer; ++i)
00121           {
00122             x += Thickness.at(i) * tan(asin(slowness * velocity->at(i)));
00123             currdepth += Thickness.at(i);
00124           }
00125         x += (SourceDepth - currdepth) * tan(asin(slowness * velocity->at(
00126             sourcelayer)));
00127         return x;
00128       }
00129 
00130     double SeismicModel::CalcTravelTime(const tArrivalType mode,
00131         const double sdepth, const double rdepth, const double p)
00132       {
00133         int sourceindex = FindLayer(sdepth);
00134         int recindex = FindLayer(rdepth);
00135         const double hdistance = MatchSlowness(p, mode);
00136         double currdepth = accumulate(Thickness.begin(), Thickness.begin()
00137             + recindex, 0.0);
00138         trealdata *velocity;
00139         if (mode == DirectS)
00140           velocity = &SVelocity;
00141         else
00142           velocity = &PVelocity;
00143         double t = p * hdistance;
00144         double eta = sqrt(1 / pow(velocity->at(recindex), 2) - p * p);
00145         t += (currdepth - rdepth) * eta;
00146         for (int i = recindex; i < sourceindex; ++i)
00147           {
00148             currdepth += Thickness.at(i);
00149             eta = sqrt(1 / pow(velocity->at(i), 2) - p * p);
00150             t += eta * Thickness.at(i);
00151           }
00152         eta = sqrt(1 / pow(velocity->at(sourceindex), 2) - p * p);
00153         t += (sdepth - currdepth) * eta;
00154         return t;
00155       }
00156 
00157     double SeismicModel::CalcArrival(const tArrivalType mode,
00158         const double recdist)
00159       {
00160         const double tolerance = 0.001;
00161         double angle = PI / 4.;
00162         double distance = 0;
00163         trealdata *velocity;
00164         double p = 0;
00165         double currdepth = 0;
00166         int preclevel = 3;
00167 
00168         if (mode == DirectS)
00169           velocity = &SVelocity;
00170         else
00171           velocity = &PVelocity;
00172         while (!FuzzComp(recdist, distance, tolerance))
00173           {
00174             currdepth = 0;
00175             p = sin(angle) / velocity->at(0);
00176             distance = MatchSlowness(p, mode);
00177             if (distance > recdist)
00178               angle -= PI * pow(0.5, preclevel);
00179             else
00180               angle += PI * pow(0.5, preclevel);
00181             preclevel++;
00182           }
00183         return CalcTravelTime(mode, SourceDepth, 0.0, p);
00184       }
00185 
00186     void SeismicModel::PlotVelWithErrors(const std::string &filename)
00187       {
00188         bool haveErrors = false;
00189         if (!SVelErrors.empty() && !ThickErrors.empty())
00190           haveErrors = true;
00191         ofstream outfile(filename.c_str());
00192         double cumthick = 0;
00193         const unsigned int size = Thickness.size();
00194         for (unsigned int i = 0; i < size; ++i)
00195           {
00196             outfile << cumthick << "  " << SVelocity.at(i);
00197             if (haveErrors)
00198               outfile << " " << ThickErrors.at(i) << " " << SVelErrors.at(i);
00199             outfile << endl;
00200             cumthick += Thickness.at(i);
00201             outfile << cumthick << " " << SVelocity.at(i);
00202             if (haveErrors)
00203               outfile << " " << ThickErrors.at(i) << " " << SVelErrors.at(i);
00204             outfile << endl;
00205           }
00206       }
00207 
00208     void SeismicModel::WritePlot(const std::string &filename)
00209       {
00210         ofstream outfile((filename + ".plot").c_str());
00211         double cumthick = 0;
00212         const unsigned int size = Thickness.size();
00213         for (unsigned int i = 0; i < size; ++i)
00214           {
00215             outfile << cumthick << "  " << SVelocity.at(i) << "  "
00216                 << PVelocity.at(i) << "  " << Density.at(i) << endl;
00217             cumthick += Thickness.at(i);
00218             outfile << cumthick << " " << SVelocity.at(i) << "  "
00219                 << PVelocity.at(i) << "  " << Density.at(i) << endl;
00220           }
00221         outfile << cumthick * 2.0 << " " << SVelocity.at(size - 1) << "  "
00222             << PVelocity.at(size - 1) << "  " << Density.at(size - 1) << endl;
00223       }
00224   }

Generated on Tue May 4 16:52:15 2010 for GPLIB++ by  doxygen 1.5.8