src/test_baroclin.cpp
author Alexey Ozeritsky <aozeritsky@gmail.com>
Fri Jun 11 21:50:18 2010 +0400 (20 months ago)
changeset 142 2aa3b89e9ccc
parent 127d68dc631b821
child 14942826300de6f
permissions -rwxr-xr-x
fix
     1 /**/
     2 
     3 #include <string>
     4 #include <vector>
     5 #include <math.h>
     6 
     7 #include "baroclin.h"
     8 #include "linal.h"
     9 
    10 using namespace std;
    11 using namespace linal;
    12 
    13 double u1_t (double x, double y, double t)
    14 {
    15 	return x*sin(y+t)*ipow(cos(x),4);
    16 }
    17 
    18 double u2_t (double x, double y, double t)
    19 {
    20 	return x*cos(y+t)*ipow(cos(x),4);
    21 }
    22 
    23 double rp_f1(double x, double y, double t, const SphereBaroclin::Conf * conf)
    24 {
    25 	double sigma = conf->sigma;
    26 	double mu    = conf->mu;
    27 	double sigma1= conf->sigma;
    28 	double mu1   = conf->mu;
    29 	double alpha = conf->alpha;
    30 	
    31 	return -45*mu*sin(y+t)*x-(9./2.)*sigma*
    32 		ipow(cos(x),3)*sin(y+t)*sin(x)+(9./2.)*sigma*
    33 		ipow(cos(x),3)*sin(x)*cos(y+t)-10*sigma*
    34 		ipow(cos(x),4)*x*sin(y+t)+10*sigma*
    35 		ipow(cos(x),4)*x*cos(y+t)+(15./2.)*sigma*
    36 		ipow(cos(x),2)*x*sin(y+t)-(15./2.)*sigma*
    37 		ipow(cos(x),2)*x*cos(y+t)-360*mu*sin(y+t)*sin(x)*
    38 		ipow(cos(x),3)+147*mu*sin(y+t)*sin(x)*cos(x)-400*mu*sin(y+t)*x*
    39 		ipow(cos(x),4)+390*mu*sin(y+t)*x*
    40 		ipow(cos(x),2)-20*x*cos(y+t)*
    41 		ipow(cos(x),4)-9*cos(y+t)*
    42 		ipow(cos(x),3)*sin(x)+15*x*cos(y+t)*
    43 		ipow(cos(x),2);
    44 }
    45 
    46 double rp_g1(double x, double y, double t, const SphereBaroclin::Conf * conf)
    47 {
    48 	double sigma = conf->sigma;
    49 	double mu    = conf->mu;
    50 	double sigma1= conf->sigma;
    51 	double mu1   = conf->mu;
    52 	double alpha = conf->alpha;
    53 
    54 	double alpha2 = alpha * alpha;
    55 	double r = 20*x*sin(y+t)*
    56 		ipow(cos(x),4)+9*sin(y+t)*
    57 		ipow(cos(x),3)*sin(x)-15*x*sin(y+t)*
    58 		ipow(cos(x),2)+390*mu*cos(y+t)*x*
    59 		ipow(cos(x),2)-10*sigma*
    60 		ipow(cos(x),4)*x*cos(y+t)-(9./2.)*sigma*
    61 		ipow(cos(x),3)*sin(y+t)*sin(x)-alpha2*
    62 		ipow(cos(x),7)*x-45*mu*cos(y+t)*x+18*
    63 		ipow(cos(x),6)*
    64 		ipow(cos(y+t),2)*sin(x)-9*
    65 		ipow(cos(x),6)*sin(x)+9*x*
    66 		ipow(cos(x),5)-(9./2.)*sigma*
    67 		ipow(cos(x),3)*sin(x)*cos(y+t)-30*x*x*
    68 		ipow(cos(x),4)*sin(x)-18*x*
    69 		ipow(cos(x),5)*
    70 		ipow(cos(y+t),2)+alpha2*
    71 		ipow(cos(x),4)*x*sin(y+t)+(15./2.)*sigma*
    72 		ipow(cos(x),2)*x*sin(y+t)+(15./2.)*sigma*
    73 		ipow(cos(x),2)*x*cos(y+t)-400*mu*cos(y+t)*x*
    74 		ipow(cos(x),4)+147*mu*cos(y+t)*sin(x)*cos(x)+60*x*x*
    75 		ipow(cos(x),4)*
    76 		ipow(cos(y+t),2)*sin(x)-360*mu*cos(y+t)*sin(x)*
    77 		ipow(cos(x),3)-10*sigma*
    78 		ipow(cos(x),4)*x*sin(y+t)+4*alpha2*
    79 		ipow(cos(x),6)*x*x*sin(x)-9*alpha2*
    80 		ipow(cos(x),3)*mu1*cos(y+t)*sin(x)-20*alpha2*
    81 		ipow(cos(x),4)*mu1*cos(y+t)*x+15*alpha2*
    82 		ipow(cos(x),2)*mu1*cos(y+t)*x-alpha2*
    83 		ipow(cos(x),4)*sigma1*x*cos(y+t);
    84 	r /= alpha2;
    85 	return r;
    86 }
    87 
    88 double rp_f2(double x, double y, double t, const SphereBaroclin::Conf * conf)
    89 {
    90 	double sigma = conf->sigma;
    91 	double mu    = conf->mu;
    92 	double sigma1= conf->sigma;
    93 	double mu1   = conf->mu;
    94 	double alpha = conf->alpha;
    95 
    96 	return -9*cos(y+t)*
    97 		ipow(cos(x),3)*sin(x)-20*x*cos(y+t)*
    98 		ipow(cos(x),4)+15*x*cos(y+t)*
    99 		ipow(cos(x),2)-(9./2.)*sigma*
   100 		ipow(cos(x),3)*sin(y+t)*sin(x)+(9./2.)*sigma*
   101 		ipow(cos(x),3)*sin(x)*cos(y+t)-10*sigma*
   102 		ipow(cos(x),4)*x*sin(y+t)+10*sigma*
   103 		ipow(cos(x),4)*x*cos(y+t)+(15./2.)*sigma*
   104 		ipow(cos(x),2)*x*sin(y+t)-(15./2.)*sigma*
   105 		ipow(cos(x),2)*x*cos(y+t)-360*mu*sin(y+t)*sin(x)*
   106 		ipow(cos(x),3)+147*mu*sin(y+t)*sin(x)*cos(x)-400*mu*sin(y+t)*x*
   107 		ipow(cos(x),4)+390*mu*sin(y+t)*x*
   108 		ipow(cos(x),2)-45*mu*sin(y+t)*x;
   109 }
   110 
   111 double rp_g2(double x, double y, double t, SphereBaroclin::Conf * conf)
   112 {
   113 	double sigma = conf->sigma;
   114 	double mu    = conf->mu;
   115 	double sigma1= conf->sigma;
   116 	double mu1   = conf->mu;
   117 	double alpha = conf->alpha;
   118 
   119 	return -15*x*sin(y+t)*
   120 		ipow(cos(x),2)+20*x*sin(y+t)*
   121 		ipow(cos(x),4)+9*sin(y+t)*
   122 		ipow(cos(x),3)*sin(x)-(9./2.)*sigma*
   123 		ipow(cos(x),3)*sin(x)*cos(y+t)-10*sigma*
   124 		ipow(cos(x),4)*x*sin(y+t)-10*sigma*
   125 		ipow(cos(x),4)*x*cos(y+t)-(9./2.)*sigma*
   126 		ipow(cos(x),3)*sin(y+t)*sin(x)+(15./2.)*sigma*
   127 		ipow(cos(x),2)*x*sin(y+t)+(15./2.)*sigma*
   128 		ipow(cos(x),2)*x*cos(y+t)-360*mu*cos(y+t)*sin(x)*
   129 		ipow(cos(x),3)+147*mu*cos(y+t)*sin(x)*cos(x)-400*mu*cos(y+t)*x*
   130 		ipow(cos(x),4)+390*mu*cos(y+t)*x*
   131 		ipow(cos(x),2)-45*mu*cos(y+t)*x;
   132 }
   133 
   134 double rp1(double phi, double lambda, SphereBaroclin::Conf * conf)
   135 {
   136 	double omg = 2.*M_PI/24./60./60.; // ?
   137 	double T0  = 1./omg;
   138 	double R   = 6.371e+6;
   139 	double c   = T0*T0/R/R;
   140 	double x   = phi;
   141 
   142 	double pt1 = -0.5 * (sin(x)*M_PI*x-2*sin(x)*x*x);
   143 	if (fabs(pt1) > 1e-14) {
   144 		pt1 /= cos(x);
   145 	}
   146 
   147 	double pt2 = -0.5*(-M_PI+4*x);
   148 	return -T0/R * 16.0 / M_PI / M_PI * 30.0 * (pt1 + pt2);
   149 }
   150 
   151 double rp2(double phi, double lambda, SphereBaroclin::Conf * conf)
   152 {
   153 	double omg = 2.*M_PI/24./60./60.; // ?
   154 	double T0  = 1./omg;
   155 	double R   = 6.371e+6;
   156 	double c   = T0*T0/R/R;
   157 	double x   = phi;
   158 
   159 	double pt1 = -0.5 * (sin(x)*M_PI*x-2*sin(x)*x*x);
   160 	if (fabs(pt1) > 1e-14) {
   161 		pt1 /= cos(x);
   162 	}
   163 
   164 	double pt2 = -0.5*(-M_PI+4*x);
   165 	return -T0/R * 16.0 / M_PI / M_PI * 30.0 * (pt1 + pt2);
   166 }
   167 
   168 double cor(double phi, double lambda, double, const SphereBaroclin::Conf * conf)
   169 {
   170 	return 2.*sin(phi) +  // l
   171 		0.5 * cos(2*lambda)*sin(2*phi)*sin(2*phi); //h
   172 }
   173 
   174 double zero_cor(double phi, double lambda, double, const SphereBaroclin::Conf * conf)
   175 {
   176 	return 0;
   177 }
   178 
   179 double u0(double phi, double lambda)
   180 {
   181 	double omg = 2.*M_PI/24./60./60.; // ?
   182 	double T0  = 1./omg;
   183 	double R   = 6.371e+6;
   184 
   185 	return -T0/R * 16.0 / M_PI / M_PI * 30.0 * 
   186 		(M_PI/4 * phi * phi - phi * phi * phi / 3);
   187 }
   188 
   189 #define  pOff(i, j) ( i ) * conf.nlon + ( j )
   190 
   191 template < typename T >
   192 void proj(double * u, SphereBaroclin & bv, SphereBaroclin::Conf & conf, T rp, double t)
   193 {
   194 	double dlat = M_PI / (conf.nlat - 1);
   195 	double dlon = 2. * M_PI / conf.nlon;
   196 
   197 	for (int i = 0; i < conf.nlat; ++i) {
   198 		double phi    = -0.5 * M_PI + i * dlat;
   199 		for (int j = 0; j < conf.nlon; ++j) {
   200 			double lambda = j * dlon;
   201 			u[pOff(i, j)] = rp(phi, lambda, t);
   202 		}
   203 	}
   204 }
   205 
   206 void test_barvortex()
   207 {
   208 	SphereBaroclin::Conf conf;
   209 	double R   = 6.371e+6;
   210 	double H   = 5000;
   211 	double omg = 2.*M_PI/24./60./60.; // ?
   212 	double T0  = 1./omg;
   213 	conf.k1    = 1.0;
   214 	conf.k2    = 1.0;
   215 	conf.tau   = 0.0001;
   216 	conf.sigma = 1.14e-2;
   217 	conf.mu    = 6.77e-5;
   218 
   219 	conf.sigma1= conf.sigma;
   220 	conf.mu1   = conf.mu;
   221 
   222 	conf.nlat  = 19;
   223 	conf.nlon  = 36;
   224 	conf.theta = 0.5;
   225 
   226 	conf.alpha  = 1.0;
   227 	conf.rp1    = rp_f1;
   228 	conf.rp2    = rp_g1;
   229 
   230 //	conf.alpha  = 0.0;
   231 //	conf.rp1    = rp_f2;
   232 //	conf.rp2    = rp_g2;
   233 
   234 	conf.cor    = zero_cor;
   235 
   236 	int n = conf.nlat * conf.nlon;
   237 
   238 	double t = 0;
   239 	double T = 30 * 2.0 * M_PI;;
   240 	double nr1;
   241 	double nr2;
   242 	int i = 0;
   243 
   244 	SphereBaroclin bv(conf);
   245 	vector < double > u1(n);
   246 	vector < double > u2(n);
   247 	vector < double > u11(n);
   248 	vector < double > u21(n);
   249 	vector < double > u1r(n);
   250 	vector < double > u2r(n);
   251 
   252 	fprintf(stderr, "#mesh_w:%d\n", conf.nlon);
   253 	fprintf(stderr, "#mesh_h:%d\n", conf.nlat);
   254 	fprintf(stderr, "#tau:%.16lf\n", conf.tau);
   255 	fprintf(stderr, "#sigma:%.16lf\n", conf.sigma);
   256 	fprintf(stderr, "#mu:%.16lf\n", conf.mu);
   257 	fprintf(stderr, "#sigma1:%.16lf\n", conf.sigma1);
   258 	fprintf(stderr, "#mu1:%.16lf\n", conf.mu1);
   259 	fprintf(stderr, "#alpha:%.16lf\n", conf.alpha);
   260 	fprintf(stderr, "#k1:%.16lf\n", conf.k1);
   261 	fprintf(stderr, "#k2:%.16lf\n", conf.k2);
   262 	fprintf(stderr, "#theta:%.16lf\n", conf.theta);
   263 	fprintf(stderr, "#rp:kornev1\n");
   264 	fprintf(stderr, "#coriolis:kornev1\n");
   265 	fprintf(stderr, "#initial:kornev1\n");
   266 	fprintf(stderr, "#build:$Id$\n");
   267 
   268 	proj(&u1[0], bv, conf, u1_t, 0);
   269 	proj(&u2[0], bv, conf, u2_t, 0);
   270 
   271 	while (t < T) {
   272 		bv.S_step(&u11[0], &u21[0], &u1[0], &u2[0], t);
   273 		t += conf.tau;
   274 
   275 		proj(&u1r[0], bv, conf, u1_t, t);
   276 		proj(&u2r[0], bv, conf, u2_t, t);
   277 
   278 		nr1 = bv.dist(&u11[0], &u1r[0]);
   279 		nr2 = bv.dist(&u21[0], &u2r[0]);
   280 		fprintf(stderr, "t=%le; nr=%le; nr=%le; min=%le; max=%le;\n", 
   281 				t, nr1, nr2, 
   282 				vec_find_min(&u11[0], n),
   283 				vec_find_max(&u11[0], n));
   284 
   285 		if (isnan(nr1) || isnan(nr2)) {
   286 			return;
   287 		}
   288 
   289 		u11.swap(u1);
   290 		u21.swap(u2);
   291 		i ++;
   292 	}
   293 }
   294 
   295 int main(int argc, char ** argv)
   296 {
   297 	fprintf(stderr, "#cmd:");
   298 	for (int i = 0; i < argc; ++i) {
   299 		fprintf(stderr, "%s ", argv[i]);
   300 	}
   301 	fprintf(stderr, "\n");
   302 	//set_fpe_except();
   303 	test_barvortex();
   304 }
   305