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
00026
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
00048
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
00074
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
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
00092 assert(depth > 0.0);
00093 double currentbottom = 0;
00094 size_t i = 0;
00095
00096
00097
00098 while (depth > currentbottom && i < Thickness.size())
00099 {
00100 currentbottom += Thickness.at(i);
00101 ++i;
00102 }
00103
00104
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 }