00001 #ifndef CMTTENSOR_H_
00002 #define CMTTENSOR_H_
00003 #include <complex>
00004 #include "NumUtil.h"
00005 #include "miscfunc.h"
00006
00007 namespace gplib
00008 {
00009
00010 class MTTensor
00011 {
00012 private:
00013
00014 std::complex<double> Zxx;
00015 std::complex<double> Zxy;
00016 std::complex<double> Zyx;
00017 std::complex<double> Zyy;
00018
00019 double dZxx;
00020 double dZxy;
00021 double dZyx;
00022 double dZyy;
00023 double frequency;
00024 double rotangle;
00025
00026 double Rx;
00027
00028 double Ry;
00029
00030 double Nu;
00031
00032 double CalcRho(const std::complex<double> &Z) const
00033 {
00034 return mu / (2 * PI * frequency) * (Z.real() * Z.real() + Z.imag()
00035 * Z.imag()) * 1000000.0;
00036 }
00037
00038 double CalcPhase(const std::complex<double> &Z) const
00039 {
00040 if (fcmp(Z.real(), 0.0, std::numeric_limits<double>::epsilon()) != 0)
00041 return atan2(Z.imag(), Z.real()) / PI * 180;
00042 else
00043 return 0.0;
00044 }
00045
00046 double CalcPhase90(const std::complex<double> &Z) const
00047 {
00048 if (fcmp(Z.real(), 0.0, std::numeric_limits<double>::epsilon()) != 0)
00049 return atan(Z.imag() / Z.real()) / PI * 180;
00050 else
00051 return 0.0;
00052 }
00053
00054 double CalcdRho(const std::complex<double> &Z, const double dZ) const
00055 {
00056 return mu / (PI * frequency) * abs(Z) * dZ * 1000000.0;
00057 }
00058
00059 double CalcdPhase(const std::complex<double> &Z, const double dZ) const
00060 {
00061 if (fcmp(abs(Z), 0.0, std::numeric_limits<double>::epsilon()) != 0)
00062 return dZ / abs(Z) / PI * 180;
00063 else
00064 return 0.0;
00065 }
00066
00067 double CalcZStar(const std::complex<double> &Z) const
00068 {
00069 return std::abs((I / (2.0 * PI * frequency) * Z * 1000.0).real());
00070 }
00071
00072 double CalcRhoStar(const std::complex<double> &Z) const
00073 {
00074 double phase = CalcPhase(Z) / 180.0 * PI;
00075 if (phase > 45.0)
00076 return 2.0 * pow2(cos(phase)) * CalcRho(Z);
00077 else
00078 return 0.5 * 1. / pow2(sin(phase)) * CalcRho(Z);
00079 }
00080 public:
00081
00082 double GetdZero() const
00083 {
00084 return 0.0;
00085 }
00086
00087 void SetErrors(double dxx, double dxy, double dyx, double dyy)
00088 {
00089 dZxx = dxx;
00090 dZxy = dxy;
00091 dZyx = dyx;
00092 dZyy = dyy;
00093 }
00094
00095 void Rotate(double angle);
00096
00097 double GetRotangle() const
00098 {
00099 return rotangle;
00100 }
00101
00102 double &SetRotangle()
00103 {
00104 return rotangle;
00105 }
00106
00107 double GetFrequency() const
00108 {
00109 return frequency;
00110 }
00111
00112 std::complex<double> GetZyy() const
00113 {
00114 return Zyy;
00115 }
00116 std::complex<double> GetZxx() const
00117 {
00118 return Zxx;
00119 }
00120 std::complex<double> GetZxy() const
00121 {
00122 return Zxy;
00123 }
00124 std::complex<double> GetZyx() const
00125 {
00126 return Zyx;
00127 }
00128
00129 std::complex<double> &SetZyy()
00130 {
00131 return Zyy;
00132 }
00133 std::complex<double> &SetZxx()
00134 {
00135 return Zxx;
00136 }
00137 std::complex<double> &SetZxy()
00138 {
00139 return Zxy;
00140 }
00141 std::complex<double> &SetZyx()
00142 {
00143 return Zyx;
00144 }
00145
00146 double GetdZxx() const
00147 {
00148 return dZxx;
00149 }
00150 double GetdZxy() const
00151 {
00152 return dZxy;
00153 }
00154 double GetdZyx() const
00155 {
00156 return dZyx;
00157 }
00158 double GetdZyy() const
00159 {
00160 return dZyy;
00161 }
00162
00163 double &SetdZyy()
00164 {
00165 return dZyy;
00166 }
00167 double &SetdZxx()
00168 {
00169 return dZxx;
00170 }
00171 double &SetdZxy()
00172 {
00173 return dZxy;
00174 }
00175 double &SetdZyx()
00176 {
00177 return dZyx;
00178 }
00179
00180 double GetRhoxx() const
00181 {
00182 return CalcRho(Zxx);
00183 }
00184 double GetRhoxy() const
00185 {
00186 return CalcRho(Zxy);
00187 }
00188 double GetRhoyx() const
00189 {
00190 return CalcRho(Zyx);
00191 }
00192 double GetRhoyy() const
00193 {
00194 return CalcRho(Zyy);
00195 }
00196
00197 double GetPhixx() const
00198 {
00199 return CalcPhase(Zxx);
00200 }
00201 double GetPhixy() const
00202 {
00203 return CalcPhase(Zxy);
00204 }
00205 double GetPhiyx() const
00206 {
00207 return CalcPhase(Zyx);
00208 }
00209 double GetPhiyy() const
00210 {
00211 return CalcPhase(Zyy);
00212 }
00213
00214 double GetPhi90xx() const
00215 {
00216 return CalcPhase90(Zxx);
00217 }
00218 double GetPhi90xy() const
00219 {
00220 return CalcPhase90(Zxy);
00221 }
00222 double GetPhi90yx() const
00223 {
00224 return CalcPhase90(Zyx);
00225 }
00226 double GetPhi90yy() const
00227 {
00228 return CalcPhase90(Zyy);
00229 }
00230
00231 double GetdRhoxx() const
00232 {
00233 return CalcdRho(Zxx, dZxx);
00234 }
00235 double GetdRhoxy() const
00236 {
00237 return CalcdRho(Zxy, dZxy);
00238 }
00239 double GetdRhoyx() const
00240 {
00241 return CalcdRho(Zyx, dZyx);
00242 }
00243 double GetdRhoyy() const
00244 {
00245 return CalcdRho(Zyy, dZyy);
00246 }
00247
00248 double GetdPhixx() const
00249 {
00250 return CalcdPhase(Zxx, dZxx);
00251 }
00252 double GetdPhixy() const
00253 {
00254 return CalcdPhase(Zxy, dZxy);
00255 }
00256 double GetdPhiyx() const
00257 {
00258 return CalcdPhase(Zyx, dZyx);
00259 }
00260 double GetdPhiyy() const
00261 {
00262 return CalcdPhase(Zyy, dZyy);
00263 }
00264
00265 double GetRhoxxStar() const
00266 {
00267 return CalcRhoStar(Zxx);
00268 }
00269 double GetRhoxyStar() const
00270 {
00271 return CalcRhoStar(Zxy);
00272 }
00273 double GetRhoyxStar() const
00274 {
00275 return CalcRhoStar(Zyx);
00276 }
00277 double GetRhoyyStar() const
00278 {
00279 return CalcRhoStar(Zyy);
00280 }
00281
00282 double GetZxxStar() const
00283 {
00284 return CalcZStar(Zxx);
00285 }
00286 double GetZxyStar() const
00287 {
00288 return CalcZStar(Zxy);
00289 }
00290 double GetZyxStar() const
00291 {
00292 return CalcZStar(Zyx);
00293 }
00294 double GetZyyStar() const
00295 {
00296 return CalcZStar(Zyy);
00297 }
00298
00299 std::complex<double> GetS1() const
00300 {
00301 return Zxx + Zyy;
00302 }
00303 std::complex<double> GetS2() const
00304 {
00305 return Zxy + Zyx;
00306 }
00307 std::complex<double> GetD1() const
00308 {
00309 return Zxx - Zyy;
00310 }
00311 std::complex<double> GetD2() const
00312 {
00313 return Zxy - Zyx;
00314 }
00315
00316 std::complex<double> GetBerd() const
00317 {
00318 return 0.5 * GetD2();
00319 }
00320
00321 double GetdBerd() const
00322 {
00323 return 0.5 * sqrt(dZxy * dZxy + dZyx * dZyx);
00324 }
00325 double GetRhoBerd() const
00326 {
00327 return CalcRho(GetBerd());
00328 }
00329 double GetPhi90Berd() const
00330 {
00331 return CalcPhase90(GetBerd());
00332 }
00333 double GetdRhoBerd() const
00334 {
00335 return CalcdRho(GetBerd(), GetdBerd());
00336 }
00337 double GetdPhi90Berd() const
00338 {
00339 return CalcdPhase(GetBerd(), GetdBerd());
00340 }
00341
00342 std::complex<double> GetDet() const
00343 {
00344 return Zxx * Zyy - Zxy * Zyx;
00345 }
00346
00347 double GetdDet() const
00348 {
00349 return sqrt(abs(Zyy * Zyy) * dZxx * dZxx + abs(Zxx * Zxx) * dZyy
00350 * dZyy + abs(Zxy * Zxy) * dZyx * dZyx + abs(Zyx * Zyx) * dZxy
00351 * dZxy);
00352 }
00353
00354 double GetDetreal() const
00355 {
00356 return Zxx.real() * Zyy.real() - Zxy.real() * Zyx.real();
00357 }
00358
00359 double GetdDetreal() const
00360 {
00361 return sqrt(pow2(Zyy.real()) * pow2(dZxx) + pow2(
00362 Zxx.real()) * pow2(dZyy) + pow2(Zxy.real())
00363 * pow2(dZyx) + pow2(Zyx.real()) * pow2(dZxy));
00364 }
00365
00366 double GetMu() const
00367 {
00368 return sqrt(std::abs(Commute(GetD1(), GetS2())
00369 + Commute(GetS1(), GetD2()))) / abs(GetD2());
00370 }
00371
00372 double GetKappa() const
00373 {
00374 return abs(GetS1()) / abs(GetD2());
00375 }
00376 double GetSigma() const
00377 {
00378 return (pow2(abs(GetD1())) + pow2(abs(GetS2())))
00379 / pow2(abs(GetD2()));
00380 }
00381
00382 double GetEta() const
00383 {
00384 return sqrt(std::abs(Commute(GetD1(), GetS2())
00385 - Commute(GetS1(), GetD2()))) / abs(GetD2());
00386 }
00387
00388 double GetAlpha() const
00389 {
00390 double denominator = Commute(GetS1(), GetD1()) - Commute(GetS2(),
00391 GetD2());
00392 if (fcmp(denominator, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00393 return 0.5 * atan((Commute(GetS1(), GetS2()) - Commute(GetD1(),
00394 GetD2())) / (denominator));
00395 else
00396 return 0.0;
00397 }
00398
00399 double GetAlphaHigh() const
00400 {
00401 double regalpha = GetAlpha();
00402 MTTensor tmp(*this);
00403 tmp.Rotate(regalpha);
00404 if (tmp.GetPhiyx() > tmp.GetPhixy())
00405 regalpha += PI / 2.0;
00406 return regalpha;
00407 }
00408
00409 double GetMaxPhiDiff() const
00410 {
00411 MTTensor tmp(*this);
00412 tmp.Rotate(GetAlpha());
00413 return std::abs(tmp.GetPhixy() - tmp.GetPhiyx());
00414 }
00415
00416 double GetPhi11() const
00417 {
00418 const double dr = GetDetreal();
00419 if (fcmp(dr, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00420 return ((Zyy.real() * Zxx.imag() - Zxy.real() * Zyx.imag()) / dr);
00421 else
00422 return 0.0;
00423 }
00424 double GetPhi12() const
00425 {
00426 const double dr = GetDetreal();
00427 if (fcmp(dr, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00428 return ((Zyy.real() * Zxy.imag() - Zxy.real() * Zyy.imag()) / dr);
00429 else
00430 return 0.0;
00431 }
00432 double GetPhi21() const
00433 {
00434 const double dr = GetDetreal();
00435 if (fcmp(dr, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00436 return ((Zxx.real() * Zyx.imag() - Zyx.real() * Zxx.imag()) / dr);
00437 else
00438 return 0.0;
00439 }
00440 double GetPhi22() const
00441 {
00442 const double dr = GetDetreal();
00443 if (fcmp(dr,0.0,std::numeric_limits<double>::epsilon()) != 0)
00444 return ((Zxx.real() * Zyy.imag() - Zyx.real() * Zxy.imag()) / dr);
00445 else
00446 return 0.0;
00447 }
00448 double GetAlpha_phi() const
00449 {
00450 const double diff = GetPhi11() - GetPhi22();
00451 if (fcmp(diff, 0.0, std::numeric_limits<double>::epsilon()) != 0)
00452 return 0.5 * atan2((GetPhi12() + GetPhi21()), diff);
00453 else
00454 return 0.0;
00455 }
00456 double GetBeta_phi() const
00457 {
00458 return 0.5 * atan2((GetPhi12() - GetPhi21()), (GetPhi11()
00459 + GetPhi22()));
00460 }
00461 double GetPi1() const
00462 {
00463 return 0.5 * sqrt(std::pow(GetPhi11() - GetPhi22(), 2) + std::pow(GetPhi12()
00464 + GetPhi21(), 2));
00465 }
00466 double GetPi2() const
00467 {
00468 return 0.5 * sqrt(std::pow(GetPhi11() + GetPhi22(), 2) + std::pow(GetPhi12()
00469 - GetPhi21(), 2));
00470 }
00471 double GetPhiStrike() const
00472 {
00473 return GetAlpha_phi() - GetBeta_phi();
00474 }
00475 double GetPhiMax() const
00476 {
00477 return GetPi2() + GetPi1();
00478 }
00479 double GetPhiMin() const
00480 {
00481 return GetPi2() - GetPi1();
00482 }
00483 double GettrPhi() const
00484 {
00485 return GetPhi11() + GetPhi22();
00486 }
00487 double GetskPhi() const
00488 {
00489 return GetPhi12() - GetPhi21();
00490 }
00491 double GetdetPhi() const
00492 {
00493 return GetPhi11() * GetPhi22() - GetPhi12() * GetPhi21();
00494 }
00495 double GetPhi1() const
00496 {
00497 return GettrPhi() / 2.;
00498 }
00499 double GetPhi2() const
00500 {
00501 return sqrt(std::abs(GetdetPhi()));
00502 }
00503 double GetPhi2Sq() const
00504 {
00505 return GetdetPhi();
00506 }
00507 double GetPhi3() const
00508 {
00509 return GetskPhi() / 2.;
00510 }
00511 double GetPhiEllip() const
00512 {
00513 return (GetPhiMax() - GetPhiMin()) / (GetPhiMax() + GetPhiMin());
00514 }
00515
00516 double GetXi1() const
00517 {
00518 return 0.5 * (Zxx.real() + Zyy.real());
00519 }
00520 double GetXi2() const
00521 {
00522 return 0.5 * (Zxy.real() + Zyx.real());
00523 }
00524 double GetXi3() const
00525 {
00526 return 0.5 * (Zxx.real() - Zyy.real());
00527 }
00528 double GetXi4() const
00529 {
00530 return 0.5 * (Zxy.real() - Zyx.real());
00531 }
00532 double GetEta1() const
00533 {
00534 return 0.5 * (Zxx.imag() + Zyy.imag());
00535 }
00536 double GetEta2() const
00537 {
00538 return 0.5 * (Zxy.imag() + Zyx.imag());
00539 }
00540 double GetEta3() const
00541 {
00542 return 0.5 * (Zxx.imag() - Zyy.imag());
00543 }
00544 double GetEta4() const
00545 {
00546 return 0.5 * (Zxy.imag() - Zyx.imag());
00547 }
00548 double GetI1() const
00549 {
00550 return sqrt(pow2(GetXi1()) + pow2(GetXi4()));
00551 }
00552 double GetI2() const
00553 {
00554 return sqrt(pow2(GetEta1()) + pow2(GetEta4()));
00555 }
00556 double GetI3() const
00557 {
00558 return sqrt(pow2(GetXi2()) + pow2(GetXi3())) / GetI1();
00559 }
00560 double GetI4() const
00561 {
00562 return sqrt(pow2(GetEta2()) + pow2(GetEta3())) / GetI2();
00563 }
00564 double GetI5() const
00565 {
00566 return (GetXi4() * GetEta1() + GetXi1() * GetEta4()) / (GetI1()
00567 * GetI2());
00568 }
00569 double GetI6() const
00570 {
00571 return (GetXi4() * GetEta1() - GetXi1() * GetEta4()) / (GetI1()
00572 * GetI2());
00573 }
00574 double Getd13() const
00575 {
00576 return (GetXi1() * GetEta3() - GetXi3() * GetEta1()) / (GetI1()
00577 * GetI2());
00578 }
00579 double Getd12() const
00580 {
00581 return (GetXi1() * GetEta2() - GetXi2() * GetEta1()) / (GetI1()
00582 * GetI2());
00583 }
00584 double Getd24() const
00585 {
00586 return (GetXi2() * GetEta4() - GetXi4() * GetEta2()) / (GetI1()
00587 * GetI2());
00588 }
00589 double Getd34() const
00590 {
00591 return (GetXi3() * GetEta4() - GetXi4() * GetEta3()) / (GetI1()
00592 * GetI2());
00593 }
00594 double Getd41() const
00595 {
00596 return (GetXi4() * GetEta1() - GetXi1() * GetEta4()) / (GetI1()
00597 * GetI2());
00598 }
00599 double Getd23() const
00600 {
00601 return (GetXi2() * GetEta3() - GetXi3() * GetEta2()) / (GetI1()
00602 * GetI2());
00603 }
00604 double GetQ() const
00605 {
00606 return sqrt(pow2(Getd12() - Getd34()) + pow2(Getd13()
00607 + Getd24()));
00608 }
00609 double GetI7() const
00610 {
00611 return (Getd41() + Getd23()) / GetQ();
00612 }
00613 double Geta() const
00614 {
00615 return pow2(GetI5() - GetI6());
00616 }
00617 double Getb() const
00618 {
00619 return 1.0 - GetI5() * GetI6() + sqrt(1.0 + pow2(GetI5())
00620 * pow2(GetI6()) - pow2(GetI5()) - pow2(GetI6()));
00621 }
00622 double Getr() const
00623 {
00624 return GetI2() / GetI1();
00625 }
00626
00627
00628
00629
00630
00631 double GetRx() const
00632 {
00633 return Rx;
00634 }
00635
00636 double GetRy() const
00637 {
00638 return Ry;
00639 }
00640
00641 double GetNu() const
00642 {
00643 return Nu;
00644 }
00645 friend class MTStation;
00646 friend class C1DMTSynthData;
00647 friend class JParser;
00648 friend class EDIParser;
00649 MTTensor();
00650 MTTensor(const std::complex<double> &xx, const std::complex<double> &xy,
00651 const std::complex<double> &yx, const std::complex<double> &yy,
00652 const double freq = 1., const double angle = 0.0);
00653 MTTensor& operator=(const MTTensor& source);
00654 virtual ~MTTensor();
00655 };
00656
00657 std::complex<double> inline RhoPhiToZ(const double freq, const double rho,
00658 const double phi)
00659 {
00660 return sqrt(2 * PI * freq / mu) * 0.001 * sqrt(rho) * (cos(phi / 180
00661 * PI) + I * sin(phi / 180 * PI));
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 }
00685
00686 #endif