00001 #include "C1DAnisoMTSynthData.h"
00002 #include <cassert>
00003 #include <limits>
00004 #include <fstream>
00005 #include "NumUtil.h"
00006 #include "FatalException.h"
00007
00008 namespace gplib
00009 {
00010 const int frequenzen = 50;
00011 const float T[frequenzen] =
00012 { 0.0025, 0.00308337, 0.00513901, 0.00625, 0.0104167, 0.0125, 0.0208333,
00013 0.025, 0.0416667, 0.05, 0.0833333, 0.1, 0.166667, 0.2, 0.333333, 0.4,
00014 0.667, 0.64, 1.06667, 1.29333, 2.15554, 2.59997, 4.33332, 5.19994,
00015 8.66701, 10.666667, 16.000, 21.333, 32.000, 42.667, 64.0, 85.332,
00016 127.992, 170.678, 256.016, 341.297, 512.033, 682.594, 1023.541,
00017 1366.120, 2049.180, 2732.240, 4098.361, 5464.481, 8196.722,
00018 10869.565, 16393.443, 28800, 43200, 86400 };
00019
00020 void C1DAnisoMTSynthData::TransformRho()
00021 {
00022 assert(rho1.size() == rho2.size());
00023 assert(rho1.size() == rho3.size());
00024 assert(rho1.size() == strikes.size());
00025 assert(rho1.size() == slants.size());
00026 assert(rho1.size() == dips.size());
00027
00028 const unsigned int nlayers = rho1.size();
00029 effcond1.assign(nlayers, 0.0);
00030 effcond2.assign(nlayers, 0.0);
00031 effstrike.assign(nlayers, 0.0);
00032 for (unsigned int i = 0; i < nlayers; ++i)
00033 {
00034 double s1 = 1. / rho1.at(i);
00035 double s2 = 1. / rho2.at(i);
00036 double s3 = 1. / rho3.at(i);
00037 double strike = PI * strikes.at(i) / 180.0;
00038 double dip = PI * dips.at(i) / 180.0;
00039 double slant = PI * slants.at(i) / 180.0;
00040
00041 double sps = sin(strike);
00042 double cps = cos(strike);
00043 double sth = sin(dip);
00044 double cth = cos(dip);
00045 double sfi = sin(slant);
00046 double cfi = cos(slant);
00047 double pom1 = s1 * cfi * cfi + s2 * sfi * sfi;
00048 double pom2 = s1 * sfi * sfi + s2 * cfi * cfi;
00049 double pom3 = (s1 - s2) * sfi * cfi;
00050 double c2ps = cps * cps;
00051 double s2ps = sps * sps;
00052 double c2th = cth * cth;
00053 double s2th = sth * sth;
00054 double csps = cps * sps;
00055 double csth = cth * sth;
00056
00057 double sg11 = pom1 * c2ps + pom2 * s2ps * c2th - 2. * pom3 * cth
00058 * csps + s3 * s2th * s2ps;
00059 double sg12 = pom1 * csps - pom2 * c2th * csps + pom3 * cth * (c2ps
00060 - s2ps) - s3 * s2th * csps;
00061 double sg13 = -pom2 * csth * sps + pom3 * sth * cps + s3 * csth
00062 * sps;
00063 double sg21 = sg12;
00064 double sg22 = pom1 * s2ps + pom2 * c2ps * c2th + 2. * pom3 * cth
00065 * csps + s3 * s2th * c2ps;
00066 double sg23 = pom2 * csth * cps + pom3 * sth * sps - s3 * csth
00067 * cps;
00068 double sg31 = sg13;
00069 double sg32 = sg23;
00070 double sg33 = pom2 * s2th + s3 * c2th;
00071 double axx = sg11 - sg13 * sg31 / sg33;
00072 double axy = sg12 - sg13 * sg32 / sg33;
00073 double ayx = sg21 - sg31 * sg23 / sg33;
00074 double ayy = sg22 - sg23 * sg32 / sg33;
00075
00076 double da12 = sqrt((axx - ayy) * (axx - ayy) + 4.0 * axy * ayx);
00077 effcond1.at(i) = (0.5 * (axx + ayy + da12));
00078 effcond2.at(i) = (0.5 * (axx + ayy - da12));
00079 if (fcmp(da12, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00080 {
00081 effstrike.at(i) = 0.5 * acos((axx - ayy) / da12);
00082 }
00083 else
00084 {
00085 effstrike.at(i) = 0.0;
00086 }
00087 if (axy < 0.0)
00088 effstrike.at(i) *= -1.0;
00089
00090
00091 }
00092 }
00093
00094 void C1DAnisoMTSynthData::GetData()
00095 {
00096
00097 calc_frequencies = GetFrequencies();
00098 if (calc_frequencies.empty())
00099 {
00100 for (int i = 0; i < frequenzen; ++i)
00101 calc_frequencies.push_back(1.0 / T[i]);
00102 }
00103 Assign(calc_frequencies.size());
00104 TransformRho();
00105 CalcZ();
00106 Update();
00107
00108 }
00109
00110 inline dcomp dfp(const dcomp x)
00111 {
00112
00113 return 1.0 + exp(-2.0 * x);
00114 }
00115
00116 inline dcomp dfm(const dcomp x)
00117 {
00118
00119 return 1.0 - exp(-2.0 * x);
00120 }
00121
00122 void C1DAnisoMTSynthData::CalcZ()
00123 {
00124 dcomp omegamu;
00125 const double convfactor = 1. / (1000. * mu);
00126
00127 for (unsigned int i = 0; i < calc_frequencies.size(); ++i)
00128 {
00129 omegamu = -I * 8e-7 * PI * PI * calc_frequencies.at(i);
00130 dcomp k0 = (1. - I) * 2.0e-3 * PI * sqrt(calc_frequencies.at(i)
00131 / 10.0);
00132 dcomp zxyrot = k0 / sqrt(effcond1.back());
00133 dcomp zyxrot = -k0 / sqrt(effcond2.back());
00134 double currstrike = effstrike.back();
00135 MTTensor CurrZ(dcomp(0.0, 0.0), zxyrot, zyxrot, dcomp(0.0, 0.0),
00136 calc_frequencies.at(i));
00137 for (int j = thicknesses.size() - 2; j >= 0; --j)
00138 {
00139 double currthick = 1000.0 * thicknesses.at(j);
00140 if (currstrike != effstrike.at(j) && effcond1.at(j)
00141 != effcond2.at(j))
00142 {
00143 CurrZ.Rotate(effstrike.at(j) - currstrike);
00144 currstrike = effstrike.at(j);
00145 }
00146 MTTensor BottomZ(CurrZ);
00147
00148 dcomp dz1 = k0 / sqrt(effcond1.at(j));
00149 dcomp dz2 = k0 / sqrt(effcond2.at(j));
00150 dcomp ag1 = k0 * sqrt(effcond1.at(j)) * currthick;
00151 dcomp ag2 = k0 * sqrt(effcond2.at(j)) * currthick;
00152
00153 dcomp detzbottom = BottomZ.GetDet();
00154 dcomp denominator = detzbottom * dfm(ag1) * dfm(ag2) / (dz1
00155 * dz2) + BottomZ.GetZxy() * dfm(ag1) * dfp(ag2) / dz1
00156 - BottomZ.GetZyx() * dfp(ag1) * dfm(ag2) / dz2 + dfp(ag1)
00157 * dfp(ag2);
00158
00159 CurrZ.SetZxx() = 4.0 * BottomZ.GetZxx() * exp(-ag1 - ag2)
00160 / denominator;
00161 CurrZ.SetZxy() = (BottomZ.GetZxy() * dfp(ag1) * dfp(ag2)
00162 - BottomZ.GetZyx() * dfm(ag1) * dfm(ag2) * dz1 / dz2
00163 + detzbottom * dfp(ag1) * dfm(ag2) / dz2 + dfm(ag1) * dfp(
00164 ag2) * dz1) / denominator;
00165 CurrZ.SetZyx() = (BottomZ.GetZyx() * dfp(ag1) * dfp(ag2)
00166 - BottomZ.GetZxy() * dfm(ag1) * dfm(ag2) * dz2 / dz1
00167 - detzbottom * dfm(ag1) * dfp(ag2) / dz1 - dfp(ag1) * dfm(
00168 ag2) * dz2) / denominator;
00169 CurrZ.SetZyy() = 4.0 * BottomZ.GetZyy() * exp(-ag1 - ag2)
00170 / denominator;
00171 }
00172 CurrZ.SetRotangle() = currstrike;
00173 CurrZ.SetZxx() = convfactor * conj(CurrZ.SetZxx());
00174 CurrZ.SetZxy() = convfactor * conj(CurrZ.SetZxy());
00175 CurrZ.SetZyx() = convfactor * conj(CurrZ.SetZyx());
00176 CurrZ.SetZyy() = convfactor * conj(CurrZ.SetZyy());
00177
00178 CurrZ.Rotate(-CurrZ.GetRotangle());
00179
00180 SetMTData().at(i) = CurrZ;
00181
00182
00183
00184
00185
00186
00187
00188 }
00189 }
00190
00191 void C1DAnisoMTSynthData::WriteModel(std::string filename)
00192 {
00193 assert(rho1.size() == thicknesses.size());
00194 assert(rho2.size() == thicknesses.size());
00195 assert(rho3.size() == thicknesses.size());
00196 assert(strikes.size() == thicknesses.size());
00197 assert(slants.size() == thicknesses.size());
00198 assert(dips.size() == thicknesses.size());
00199 std::ofstream outfile(filename.c_str());
00200 if (outfile)
00201 {
00202 outfile << thicknesses.size() << std::endl;
00203 for (unsigned int i = 0; i < thicknesses.size(); ++i)
00204 {
00205 outfile << thicknesses.at(i) << " " << rho1.at(i) << " ";
00206 outfile << rho2.at(i) << " " << rho3.at(i) << " ";
00207 outfile << strikes.at(i) << " " << slants.at(i) << " ";
00208 outfile << dips.at(i) << std::endl;
00209 }
00210 }
00211 else
00212 {
00213 throw FatalException("Problem writing to file: " + filename);
00214 }
00215
00216 }
00217
00218 void C1DAnisoMTSynthData::ReadModel(std::string filename)
00219 {
00220
00221 int layers;
00222 double currthick, currho1, currho2, currho3, currstrike, currslant,
00223 currdip;
00224 int i = 0;
00225
00226 std::ifstream infile(filename.c_str());
00227 infile >> layers;
00228 if (!infile.good() || layers < 0)
00229 throw FatalException("Problem reading file: " + filename);
00230 thicknesses.reserve(layers);
00231 rho1.reserve(layers);
00232 rho2.reserve(layers);
00233 rho3.reserve(layers);
00234 strikes.reserve(layers);
00235 slants.reserve(layers);
00236 dips.reserve(layers);
00237 while (infile.good())
00238 {
00239 infile >> currthick >> currho1 >> currho2 >> currho3 >> currstrike
00240 >> currslant >> currdip;
00241 if (infile.good())
00242 {
00243 thicknesses.push_back(currthick);
00244 rho1.push_back(currho1);
00245 rho2.push_back(currho2);
00246 rho3.push_back(currho3);
00247 strikes.push_back(currstrike);
00248 slants.push_back(currslant);
00249 dips.push_back(currdip);
00250 ++i;
00251 }
00252 }
00253 assert(rho1.size() == thicknesses.size());
00254 assert(rho2.size() == thicknesses.size());
00255 assert(rho3.size() == thicknesses.size());
00256 assert(strikes.size() == thicknesses.size());
00257 assert(slants.size() == thicknesses.size());
00258 assert(dips.size() == thicknesses.size());
00259 assert(i==layers);
00260 }
00261
00262 void C1DAnisoMTSynthData::WritePlot(std::string filename)
00263 {
00264 std::ofstream outfile(filename.c_str());
00265 double cumthick = 0;
00266 TransformRho();
00267 assert(effcond1.size() == thicknesses.size());
00268 assert(effcond2.size() == thicknesses.size());
00269 assert(effstrike.size() == thicknesses.size());
00270 for (unsigned int i = 0; i < thicknesses.size(); ++i)
00271 {
00272 outfile << cumthick << " " << 1. / effcond1.at(i) << " ";
00273 outfile << 1. / effcond2.at(i) << " " << effstrike.at(i) * 180.
00274 / PI;
00275 outfile << std::endl;
00276 cumthick += thicknesses.at(i);
00277 outfile << cumthick << " " << 1. / effcond1.at(i) << " ";
00278 outfile << 1. / effcond2.at(i) << " " << effstrike.at(i) * 180.
00279 / PI;
00280 outfile << std::endl;
00281 }
00282 }
00283
00284 gplib::rvec C1DAnisoMTSynthData::GetModelVector()
00285 {
00286 TransformRho();
00287 assert(effcond1.size() == thicknesses.size());
00288 assert(effcond2.size() == thicknesses.size());
00289 assert(effstrike.size() == thicknesses.size());
00290 const unsigned int length = thicknesses.size();
00291 gplib::rvec result(length * 4);
00292 for (unsigned int i = 0; i < length; ++i)
00293 {
00294 result(i) = log10(1. / effcond1.at(i));
00295 result(i + length) = thicknesses.at(i);
00296 result(i + 2 * length) = log10(effcond1.at(i) / effcond2.at(i));
00297 result(i + 3 * length) = effstrike.at(i) * 180. / PI;
00298 }
00299 return result;
00300 }
00301
00302 C1DAnisoMTSynthData::C1DAnisoMTSynthData(const C1DAnisoMTSynthData &old) :
00303 MTStation(old), calc_frequencies(old.calc_frequencies), thicknesses(
00304 old.thicknesses), strikes(old.strikes), slants(old.slants), dips(
00305 old.dips), rho1(old.rho1), rho2(old.rho2), rho3(old.rho3), effcond1(
00306 old.effcond1), effcond2(old.effcond2), effstrike(old.effstrike)
00307 {
00308
00309 }
00310 C1DAnisoMTSynthData::C1DAnisoMTSynthData()
00311 {
00312 }
00313
00314 C1DAnisoMTSynthData::~C1DAnisoMTSynthData()
00315 {
00316 }
00317 }