muMECH  1.0
esei_OblateSpheroid.cpp
Go to the documentation of this file.
1 //********************************************************************************************************
2 // code: ### ### ##### #### ## ##
3 // ## ## ######## ## ## ## ## ##
4 // ## ## ## ## ## ### ## ######
5 // ## ## ## ## ## ## ## ## ##
6 // ##### ## ## ##### #### ## ##
7 // ##
8 //
9 // name: eshelbySoluEllipticIntegralsOblateSpheroid.cpp
10 // author(s): Jan Novak, Tomas Janda
11 // language: C, C++
12 // license: This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 //********************************************************************************************************
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <cmath>
31 #include <iostream>
32 
33 #include "macros.h"
34 #include "eshelbySoluLambda.h"
35 #include "legendreIntegrals.h"
36 #include "elementaryFunctions.h"
37 #include "esei_OblateSpheroid.h"
38 #include "inclusion.h"
39 
40 
41 namespace mumech {
42 
43 
44 // --------------------------------------------------------------------------
45 // PUBLIC FUNCTIONS
46 
47 // Function gives the values of Ferers-Dysons integrals
48 // Last edit: 11-Sep-2013
49 void eshelbySoluEllipticIntegralsOblateSpheroid::giveEllipticIntegrals(double J[13], double lambda, bool intpoint)
50 {
51 #ifdef DEBUG
52  // Oblate spheroid: a1 = a2 > a3
53  if (I->a[0] != I->a[1]) _errorr( "Values of semiaxes do not fit the condition for oblate spheroid (a1 = a2). " );
54  if (I->a[0] <= I->a[2]) _errorr( "Values of semiaxes do not fit the condition for oblate spheroid (a1 > a3)." );
55 #endif
56 
57  double a1 = I->a[0];
58  double a3 = I->a[2];
59 
60  J[0] = 0.;
61 
62  J[1] = this->I1(a1, a3, lambda, intpoint); // I1
63  J[2] = this->I2(J[1]); // I2
64  J[3] = this->I3(a1, a3, J[1], lambda, intpoint); // I3
65 
66  // (Order changed due to sequential evaluation I13 -> I12 -> I11)
67  J[6] = this->I13(a1, a3, J[1], J[3]); // I13
68  J[5] = this->I12(a1, a3, J[6], lambda, intpoint); // I12
69  J[4] = this->I11(J[5]); // I11
70 
71  J[7] = J[5]; // I21
72  J[8] = this->I22(J[5]); // I22
73  J[9] = this->I23(J[6]); // I23
74 
75  J[10] = J[6]; // I31
76  J[11] = J[9]; // I32
77  J[12] = this->I33(a1, a3, J[6], lambda, intpoint); // I33
78 
79  //#ifdef MY_DEBUG
80  // std::cout << "Ii, Iij = ";
81  // for (int i = 0; i < 13; i++)
82  // std::cout << J[i] << ", ";
83  // std::cout << std::endl;
84  //#endif
85 }
86 
87 // Function gives the derivatives of Ferers-Dysons integrals
88 // Last edit: 11-Sep-2013
90 {
91  if (intpoint) _errorr("derivatives are 0, this function should not be called");
92 
93  double ndiff = I->ndiff_1;
94 
95  // NUMERICAL DERIVATIVES (using REAL ARGUMENTS)
96 
97  // Get perturbated points and their lambdas
98  double lambdas[NUM_PERTURB];
99  this->getPerturbatedLambdas(lambdas, point->loc_x);
100 
101  // Create and fill a two dimensional array containing values of J-integrals at perturbated points.
102  const int NUM_ELLIP_INT = 13;
103  double J_pert[NUM_PERTURB][NUM_ELLIP_INT]; // All perturbations of all elliptical integrals.
104  for (int i = 0; i < NUM_PERTURB; i++) // For each perturbated point
105  this->giveEllipticIntegrals(J_pert[i], lambdas[i], intpoint); // Get elliptical integrals for lambda of perturbated point.
106 
107  // Compute numerial derivatives of first and second order of J_i integrals.
108  for (int i = 0; i < 3; i++) // For each elliptic integral Ji
109  {
110  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
111  // Ji_j = dJi[3*i+j-4], i,j=1..3.
112  point->dJi[3*i] = (J_pert[_Xp_][i+1] - J_pert[_Xm_][i+1]) / (2.0 * ndiff);
113  point->dJi[3*i+1] = (J_pert[_Yp_][i+1] - J_pert[_Ym_][i+1]) / (2.0 * ndiff);
114  point->dJi[3*i+2] = (J_pert[_Zp_][i+1] - J_pert[_Zm_][i+1]) / (2.0 * ndiff);
115 
116  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
117  // Ji_jk = ddJi[9*i+3*j+k-13], i,j,k=1..3.
118  point->ddJi[9*i] = (J_pert[_Xp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Xm_][i+1]) / (ndiff * ndiff); // d^2f(x,y,z)/dx^2 = (f(x+h,y,z) - 2*f(x,y,z) + f(x-h,y,z)) / h^2
119  point->ddJi[9*i+1] = (J_pert[_XpYp_][i+1] - J_pert[_XpYm_][i+1] - J_pert[_XmYp_][i+1] + J_pert[_XmYm_][i+1]) / (4.0*ndiff*ndiff); // d^2f(x,y,z)/dxdy = (f(x+h,y+h,z) - f(x+h,y-h,z) - f(x-h,y+h,z) + f(x-h,y-h,z)) / (4*h^2)
120  point->ddJi[9*i+2] = (J_pert[_XpZp_][i+1] - J_pert[_XpZm_][i+1] - J_pert[_XmZp_][i+1] + J_pert[_XmZm_][i+1]) / (4.0*ndiff*ndiff);
121 
122  point->ddJi[9*i+3] = point->ddJi[9*i+1];
123  point->ddJi[9*i+4] = (J_pert[_Yp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Ym_][i+1]) / (ndiff * ndiff);
124  point->ddJi[9*i+5] = (J_pert[_YpZp_][i+1] - J_pert[_YpZm_][i+1] - J_pert[_YmZp_][i+1] + J_pert[_YmZm_][i+1]) / (4.0*ndiff*ndiff);
125 
126  point->ddJi[9*i+6] = point->ddJi[9*i+2];
127  point->ddJi[9*i+7] = point->ddJi[9*i+5];
128  point->ddJi[9*i+8] = (J_pert[_Zp_][i+1] - 2.0 * J_pert[_CENTER_][i+1] + J_pert[_Zm_][i+1]) / (ndiff * ndiff);
129  }
130 
131  // Compute numerial derivatives of first and second order of J_ij integrals.
132  for (int i = 0; i < 9; i++) // For each elliptic integral Jij
133  {
134  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
135  // Jij_k = dJij[9*k+3*i+j-13], i,j,k=1..3.
136  point->dJij[i] = (J_pert[_Xp_][i+4] - J_pert[_Xm_][i+4]) / (2.0 * ndiff);
137  point->dJij[i+9] = (J_pert[_Yp_][i+4] - J_pert[_Ym_][i+4]) / (2.0 * ndiff);
138  point->dJij[i+18] = (J_pert[_Zp_][i+4] - J_pert[_Zm_][i+4]) / (2.0 * ndiff);
139 
140  // See types.c, section "Derivatives of Ferers-Dysons' integrals".
141  // Jij_kl = ddJi[27*i+9*j+3*k+l-40] i,j,k,l=1..3.
142  point->ddJij[9*i] = (J_pert[_Xp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Xm_][i+4]) / (ndiff * ndiff);
143  point->ddJij[9*i+1] = (J_pert[_XpYp_][i+4] - J_pert[_XpYm_][i+4] - J_pert[_XmYp_][i+4] + J_pert[_XmYm_][i+4]) / (4.0*ndiff*ndiff);
144  point->ddJij[9*i+2] = (J_pert[_XpZp_][i+4] - J_pert[_XpZm_][i+4] - J_pert[_XmZp_][i+4] + J_pert[_XmZm_][i+4]) / (4.0*ndiff*ndiff);
145 
146  point->ddJij[9*i+3] = point->ddJij[9*i+1];
147  point->ddJij[9*i+4] = (J_pert[_Yp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Ym_][i+4]) / (ndiff * ndiff);
148  point->ddJij[9*i+5] = (J_pert[_YpZp_][i+4] - J_pert[_YpZm_][i+4] - J_pert[_YmZp_][i+4] + J_pert[_YmZm_][i+4]) / (4.0*ndiff*ndiff);
149 
150  point->ddJij[9*i+6] = point->ddJij[9*i+2];
151  point->ddJij[9*i+7] = point->ddJij[9*i+5];
152  point->ddJij[9*i+8] = (J_pert[_Zp_][i+4] - 2.0 * J_pert[_CENTER_][i+4] + J_pert[_Zm_][i+4]) / (ndiff * ndiff);
153  }
154 
155 }
156 
157 // --------------------------------------------------------------------------
158 // PROTECTED FUNCTIONS
159 
160 // Function gives the solution of the integral I
161 // last edit: 11-Sep-2013
162 double eshelbySoluEllipticIntegralsOblateSpheroid::eI( double a[3], double k, double Theta, double mult )
163 {
164  double a1 = a[0], a3 = a[2];
165  legendreIntegrals ellInt;
166 
167  return( mult * ellInt.ellf( Theta, k ) / sqrt( SQR( a1 ) - SQR( a3 ) ) );
168 }
169 
170 // Function gives the solution of the integral I_1
171 // Last edit: 11-Sep-2013
172 double eshelbySoluEllipticIntegralsOblateSpheroid::I1(double a1, double a3, double lambda, bool intpoint)
173 {
174  if(intpoint) // Internal points
175  {
176  // Mura (11.28)
177  return 2.0 * PI * SQR(a1) * a3 / pow(SQR(a1) - SQR(a3), 3.0 / 2.0) * (acos(a3 / a1) - a3 / a1 * sqrt(1.0 - SQR(a3 / a1)));
178  }
179  else // External points
180  {
181  // Mura (12.21)
182  double b = get_b(a1, a3, lambda);
183  double d = get_d(a1, a3, lambda);
184  return 2.0 * PI * SQR(a1) * a3 / pow(SQR(a1) - SQR(a3), 3.0 / 2.0) * (acos(b) - b * d);
185  }
186 }
187 
188 // Function gives the solution of the integral I_2
189 // Last edit: 11-Sep-2013
191 {
192  // Mura (11.28), (12.21)
193  return I1;
194 }
195 
196 // Function gives the solution of the integral I_3
197 // Last edit: 11-Sep-2013
198 double eshelbySoluEllipticIntegralsOblateSpheroid::I3(double a1, double a3, double I1, double lambda, bool intpoint)
199 {
200  if(intpoint) // Internal points
201  {
202  // Mura (11.28)
203  return _4PI_ - 2.0 * I1;
204  }
205  else // External points
206  {
207  // Mura (12.21)
208  double b = get_b(a1, a3, lambda);
209  double d = get_d(a1, a3, lambda);
210  return _4PI_ * SQR(a1) * a3 * (d / b - acos(b)) / pow(SQR(a1) - SQR(a3), 3.0 / 2.0);
211  }
212 }
213 
214 // Function gives the solution of the integral I_11
215 // Last edit: 11-Sep-2013
217 {
218  // Mura (11.28), also applies to external field.
219  return I12;
220 }
221 
222 // Function gives the solution of the integral I_12
223 // Last edit: 11-Sep-2013
224 double eshelbySoluEllipticIntegralsOblateSpheroid::I12(double a1, double a3, double I13, double lambda, bool intpoint)
225 {
226  if(intpoint) // Internal points
227  {
228  // Mura (11.28)
229  return PI / SQR(a1) - I13 / 4.0;
230  }
231  else // External points
232  {
233  double delta_lambda = get_delta_lambda(a1, a3, lambda);
234  // Derived from third line in (12.18) and I11 = I22 = I12
235  return 1.0 / 4.0 * (_4PI_ * SQR(a1) * a3 / (SQR(a1) + lambda) / delta_lambda - I13);
236  }
237 }
238 
239 // Function gives the solution of the integral I_13
240 // Last edit: 11-Sep-2013
241 double eshelbySoluEllipticIntegralsOblateSpheroid::I13( double a1, double a3, double I1, double I3 )
242 {
243  // Mura (11.28), (12.18)
244  return (I1 - I3)/(SQR(a3) - SQR(a1));
245 }
246 
247 // Function gives the solution of the integral I_22
248 // Last edit: 11-Sep-2013
250 {
251  // Mura (11.28), also applies to external field.
252  return I12;
253 }
254 
255 // Function gives the solution of the integral I_23
256 // Last edit: 11-Sep-2013
258 {
259  return I13;
260 }
261 
262 // Function gives the solution of the integral I_33
263 // Last edit: 11-Sep-2013
264 double eshelbySoluEllipticIntegralsOblateSpheroid::I33(double a1, double a3, double I13, double lambda, bool intpoint)
265 {
266  if(intpoint) // Internal points
267  {
268  // Mura (11.28)
269  return 1.0 / 3.0 * (_4PI_ / SQR(a3) - 2.0 * I13);
270  }
271  else // External points
272  {
273  // Mura (12.18)
274  double delta_lambda = get_delta_lambda(a1, a3, lambda);
275  return 1.0 / 3.0 * (_4PI_ * SQR(a1) * a3 / (SQR(a3) + lambda) / delta_lambda - 2.0 * I13);
276  }
277 }
278 
279 // Auxiliary value b, (Mura, p.94)
280 double eshelbySoluEllipticIntegralsOblateSpheroid::get_b(double a1, double a3, double lambda)
281 {
282  return sqrt((SQR(a3) + lambda) / (SQR(a1) + lambda));
283 }
284 
285 // Auxiliary value d, (Mura, p.94)
286 double eshelbySoluEllipticIntegralsOblateSpheroid::get_d(double a1, double a3, double lambda)
287 {
288  return sqrt((SQR(a1) - SQR(a3)) / (SQR(a1) + lambda));
289 }
290 
291 // Auxiliary value Delta_lambda, (Mura, p.93)
292 double eshelbySoluEllipticIntegralsOblateSpheroid::get_delta_lambda(double a1, double a3, double lambda)
293 {
294  return sqrt((SQR(a1) + lambda) * (SQR(a1) + lambda) * (SQR(a3) + lambda)); // Oblate spheroid: a2 == a1
295 }
296 
297 // Lambda computed according to Mura p. 86. The property that a1 == a2 is taken into account to simplify the computation.
298 double eshelbySoluEllipticIntegralsOblateSpheroid::getLambda(const double a[3], double x1, double x2, double x3)
299 {
300  double a1 = a[0];
301  double a3 = a[2];
302 
303  // Coeficients of quadratic equation
304  // a = 1
305  double b = SQR(a1) + SQR(a3) - SQR(x1) - SQR(x2) - SQR(x3);
306  double c = SQR(a1) * SQR(a3) - (SQR(x1) + SQR(x2)) * SQR(a3) - SQR(x3) * SQR(a1);
307 
308  return (-b + sqrt(SQR(b) - 4.0 * c)) / 2.0;
309 }
310 
311 
312 } // end of namespace mumech
313 
314 /*end of file*/
void giveDerivativesOfEllipticIntegrals(Point *point, bool intpoint)
Function gives the values of Ferers-Dyson&#39;s elliptic integral derivatives of the inclusion this->I...
double loc_x[3]
Local coordinates of a point.
Definition: matrix.h:137
double I1(double a1, double a3, double lambda, bool intpoint)
double I13(double a1, double a3, double I1, double I3)
Class legendreIntegrals provides functions calculating values of elliptical integrals.
Class legendreIntegrals.
#define PI
Definition: macros.h:71
const InclusionRecord3D * I
Definition: esei.h:45
static double ellf(double phi, double ak)
Function calculating the Legendre&#39;s integral of the first kind - numerical recepies.
#define NUM_PERTURB
Definition: types.h:732
double I12(double a1, double a3, double I13, double lambda, bool intpoint)
The header file of usefull macros.
double get_b(double a1, double a3, double lambda)
void getPerturbatedLambdas(double *lambdas, const double loc_x[3])
Helper function.
Definition: esei.cpp:51
Collection of the functions of basic manipulations, some of them can be used instead of their counter...
Class eshelbySoluEllipticIntegralsOblateSpheroid.
double ddJij[81]
Second derivatives of elliptic integral Iij.
Definition: matrix.h:145
Single Point data structure - contribution from Single inclusion.
Definition: matrix.h:133
double I3(double a1, double a3, double I1, double lambda, bool intpoint)
double get_d(double a1, double a3, double lambda)
double get_delta_lambda(double a1, double a3, double lambda)
double ndiff_1
derivative step for the first derivations
Definition: inclusion.h:108
Class inclusion contains and handles all inclusion data.
#define SQR(a)
Definition: macros.h:97
double dJi[9]
First derivatives of elliptic integral Ii.
Definition: matrix.h:142
double * a
Inclusion semiaxes&#39; dimensions in global arrangement.
Definition: inclusion.h:76
double ddJi[27]
Second derivatives of elliptic integral Ii.
Definition: matrix.h:144
#define _errorr(_1)
Definition: gelib.h:160
double dJij[27]
First derivatives of elliptic integral Iij.
Definition: matrix.h:143
double getLambda(const double a[3], double x1, double x2, double x3)
Returns lambda for a given point (x1, x2, x3)
double eI(double a[3], double k, double Theta, double mult)
double I33(double a1, double a3, double I13, double lambda, bool intpoint)
#define _4PI_
Definition: types.h:50
void giveEllipticIntegrals(double J[13], double lambda, bool intpoint)
Function gives the values of Ferers-Dyson&#39;s elliptic integrals of the inclusion this->I.