⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 find_ti.c

📁 计算一般形式弹性张量最优化TI近似的C程序 Computing the optimal TI approximation of a general elastic tensor
💻 C
字号:
/* * Copyright (c) 2005 by the Society of Exploration Geophysicists. * For more information, go to http://software.seg.org/2005/0001 . * You must read and accept usage terms at: * http://software.seg.org/disclaimer.txt before use. * * Revision history: * Original SEG version by Joe Dellinger, BP EPTG, July 2005. *//* * Given a set of elastic constants, the routine "ti_distance" finds the * distance between that set of elastic constants and the nearest * TI medium that has a Z axis of symmetry. * * We want to find the nearest TI medium regardless of the direction of the * symmetry axis. This subroutine scans over a hemisphere of possible symmetry * axis directions, finds the trial symmetry axis direction that produced * the minimum distance, and then refines the search in that vicinity until * it converges to the optimal answer. * * On input: * 	FLT_DBL * cc *		A 6x6 array of Voigt-notation elastic stiffness constants. * * On output: *      FLT_DBL * theta_best, FLT_DBL * phi_best * *		The axi-symmetry direction of the nearest TI approximation. *		   phi and theta are defined as follows: * 		   phi=0 is the +Z axis. * 		   phi=90 theta=0 is the +X axis. * 		   phi=90 theta=90 is the +Y axis. * * Return value: *	The distance between the nearest transversely isotropic medium *	and the input medium, in absolute units (not normalized). */#include <math.h>#include "cmat.h"/* * How much the search grid is reduced in scale after each successive level * of refinement is complete. */#define SUBDIVIDE	4/* * Initial search every 5 degrees */#define DEG_INC		5./* * END_RES sets at what grid-interval scale we stop refining * and declare victory. */#ifdef DOUBLE_PRECISION/* FLT_DBL is "double" */#define END_RES		(1.e-9)#else/* FLT_DBL is "float" */#define END_RES		(1.e-6)#endifFLT_DBLfind_ti (FLT_DBL * cc, FLT_DBL * theta_best, FLT_DBL * phi_best){int             ii, jj, kk;FLT_DBL         ccrot[6 * 6];FLT_DBL         ccti[6 * 6];FLT_DBL         rmat[9];FLT_DBL         vec[3];FLT_DBL         dist;FLT_DBL         theta, phi, dist_best;FLT_DBL         phi_min, phi_max, phi_inc;FLT_DBL         theta_min, theta_max, theta_inc;FLT_DBL         v0[3], v1[3], v2[3], vv[3];/* * Begin the first symmetry-axis scan, spanning a hemisphere. * (By symmetry, the other hemisphere is equivalent, so a search over * a hemisphere is sufficient.) *//* * Search in latitude from pole to equator. Proceed in increments of * 5 (DEG_INC) degrees. */    phi_min = 0.;    phi_max = 90.01;    phi_inc = DEG_INC;/* At each latitude, search all 360 degrees of longitude. */    theta_min = 0.;    theta_max = 360.;/* * Keep track of the best so far. The norm must be non-negative, so * a norm of -1 indicates that we haven't got any value yet. */    dist_best = -1.;/* Loop to scan over latitude */    for (phi = phi_min; phi < phi_max; phi += phi_inc)    {/* * Calculate a longitude increment that has the same size as the * latitude increment. Add a small amount of fuzz to prevent the * calculation from going singular at the pole. */	theta_inc = phi_inc / sin ((fabs (phi) + .01) * DEGTORAD);/* Loop to scan over longitude */	for (theta = theta_min; theta < theta_max; theta += theta_inc)	{	    /*	     * rmat is the rotation matrix that rotates the current trial	     * symmetry axis, as defined by theta and phi, to the +Z axis.	     */	    make_rotation_matrix (theta, phi, 0., rmat);	    /* Rotate the elastic constants using rmat */	    rotate_tensor (ccrot, cc, rmat);	    /*	     * Find the distance of the rotated constants from VTI:	     * transversely isotropic with a vertical (+Z) symmetry axis.	     */	    dist = ti_distance (ccti, ccrot);	    /*	     * Is it better than the best we have found so far, or is it the	     * first time through the loop?	     */	    if (dist < dist_best || dist_best < 0.)	    {		dist_best = dist;		*phi_best = phi;		*theta_best = theta;	    }	}    }/* * We now have an approximate global answer. * Now progressively refine the search grid around the best point * we found in the previous global search. Keep looping, subdividing * the search grid by a factor of SUBDIVIDE each time, until the * resolution is smaller than END_RES, which defines the minimal * acceptable resolution. */    while (phi_inc > END_RES)    {	/*	 * Calculate the "current best" symmetry axis vector.	 */	/*	 * rmat is the rotation matrix that takes the +Z axis back to this	 * symmetry axis candidate. This is the inverse of what we needed	 * before; hence the minus signs on phi and theta.	 */	make_rotation_matrix (0., -(*phi_best), -(*theta_best), rmat);	/* Here is the +Z axis */	vec[0] = 0.;	vec[1] = 0.;	vec[2] = 1.;	/* Apply the rotation. */	matrix_times_vector (v0, rmat, vec);	/* v0 is now the "current best" symmetry-axis vector */	/*	 * Now construct two vectors perpendicular to the current best	 * symmetry axis. We will use these to construct a small 2D grid on	 * the surface of the sphere, with the grid centered on the best	 * symmetry-axis candidate found so far.	 */	/* Rotate the +X vector */	vec[0] = 1.;	vec[1] = 0.;	vec[2] = 0.;	matrix_times_vector (v1, rmat, vec);	/* Rotate the +Y vector */	vec[0] = 0.;	vec[1] = 1.;	vec[2] = 0.;	matrix_times_vector (v2, rmat, vec);	/*	 * Do a search over this small 2D grid. Keep track of the best so	 * far. A negative distance means we don't have an answer yet.	 */	dist_best = -1.;	/*	 * Loop over a (4*SUBDIVIDE + 1)^2 grid centered on the current	 * optimal point. The grid spacing for this search is phi_inc /	 * SUBDIVIDE, where phi_inc was the grid spacing of the previous	 * search. We make the search grid twice as big in each direction as	 * we would have to to search the entire grid cell area from the	 * previous search, so that we avoid any problems that might be	 * caused by the optimal value lying near the edge of our search	 * grid.	 */	/* The loop over basis vector v1 */	for (ii = -2 * SUBDIVIDE; ii <= 2 * SUBDIVIDE; ii++)	    /* The loop over basis vector v2 */	    for (jj = -2 * SUBDIVIDE; jj <= 2 * SUBDIVIDE; jj++)	    {		/*		 * Calculate the search vector's X, Y, and Z components. v0		 * is the center of the grid; v1 and v2 are the two		 * orthogonal basis vectors used to perturb v0.		 */		for (kk = 0; kk < 3; kk++)		{		    vv[kk] = v0[kk] +		     tan (phi_inc * DEGTORAD) *		     ((FLT_DBL) ii / (FLT_DBL) SUBDIVIDE) * v1[kk] +		     tan (phi_inc * DEGTORAD) *		     ((FLT_DBL) jj / (FLT_DBL) SUBDIVIDE) * v2[kk];		}		/*		 * Convert the direction vector vv to spherical coordinates.		 * This also normalizes it back to being on the unit sphere.		 */		vector_to_angles (vv, &phi, &theta);		/*		 * We now have a current trial symmetry direction given by		 * phi and theta. Find the corresponding rotation matrix, and		 * apply it to the input elastic stiffness constants to		 * rotate that trial symmetry axis to the +Z direction.		 */		make_rotation_matrix (theta, phi, 0., rmat);		rotate_tensor (ccrot, cc, rmat);		/* Find the distance from VTI */		dist = ti_distance (ccti, ccrot);		/* Keep track of the best candidate found so far */		if (dist < dist_best || dist_best < 0.)		{		    dist_best = dist;		    *phi_best = phi;		    *theta_best = theta;		}	    }	/*	 * We now have a new best candidate. Refine the grid and keep going	 * until it's fine enough.	 */	phi_inc /= (FLT_DBL) SUBDIVIDE;    }    /* theta_best and phi_best are returned set. */    return dist_best;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -