src/test_barvortex.cpp
author Alexey Ozeritsky <aozeritsky@gmail.com>
Fri Jun 11 21:50:18 2010 +0400 (20 months ago)
changeset 142 2aa3b89e9ccc
parent 125091a7a41f2ba
child 152c5e600a9bcd9
permissions -rw-r--r--
fix
     1 #include <math.h>
     2 #include <stdlib.h>
     3 #include <stdio.h>
     4 
     5 #include <vector>
     6 
     7 #include "barvortex.h"
     8 #include "grad.h"
     9 #include "vorticity.h"
    10 #include "statistics.h"
    11 #include "linal.h"
    12 
    13 #ifdef max
    14 #undef max
    15 #endif
    16 
    17 #ifdef WIN32
    18 #define snprintf _snprintf
    19 #endif
    20 
    21 using namespace std;
    22 using namespace linal;
    23 
    24 static inline double max (double a, double b)
    25 {
    26 	return (a > b) ? a : b;
    27 }
    28 
    29 double ans (double x, double y, double t)
    30 {
    31 	return x*sin (y + t) *ipow (cos (x), 4);
    32 }
    33 
    34 double zero_coriolis (double phi, double lambda, double t, const SphereBarvortex::Conf * conf)
    35 {
    36 	return 0.0;
    37 }
    38 
    39 double f (double x, double y, double t, const SphereBarvortex::Conf * conf)
    40 {
    41 	double mu    = conf->mu;
    42 	double sigma = conf->sigma;
    43 	return 390*mu*sin(y+t)*x*ipow(cos(x),2)
    44 		+147*mu*sin(y+t)*sin(x)*cos(x)-
    45 		400*mu*sin(y+t)*x*
    46 		ipow(cos(x),4)-360*mu*sin(y+t)*
    47 		sin(x)*ipow(cos(x),3)-20*sigma*sin(y+t)*
    48 		ipow(cos(x),4)*x+15*sigma*sin(y+t)*
    49 		ipow(cos(x),2)*x-9*sigma*sin(y+t)*
    50 		ipow(cos(x),3)*sin(x)+30*cos(y+t)*
    51 		ipow(cos(x),4)*sin(y+t)*x*x*sin(x)+9*cos(y+t)*
    52 		ipow(cos(x),6)*sin(y+t)*sin(x)-45*mu*sin(y+t)*x-
    53 		9*cos(y+t)*ipow(cos(x),5)*sin(y+t)*x-20*x*cos(y+t)*
    54 		ipow(cos(x),4)-9*cos(y+t)*
    55 		ipow(cos(x),3)*sin(x)+15*x*cos(y+t)*
    56 		ipow(cos(x),2);
    57 }
    58 
    59 void solve()
    60 {
    61 	long nlat = 19;
    62 	long nlon = 36;
    63 
    64 	SphereBarvortex::Conf conf;
    65 	conf.nlat     = nlat;
    66 	conf.nlon     = nlon;
    67 	conf.mu       = 8e-5;
    68 	conf.sigma    = 1.6e-2;
    69 	conf.tau      = 0.001;
    70 	conf.theta    = 0.5;
    71 	conf.k1       = 1.0;
    72 	conf.k2       = 1.0;
    73 	conf.rp       = f;
    74 	conf.cor      = zero_coriolis;
    75 
    76 	double dlat = M_PI / (nlat - 1);
    77 	double dlon = 2. * M_PI / nlon;
    78 	double t = 0;
    79 
    80 	int i, j, it = 0;
    81 
    82 	vector < double > u (nlat * nlon);
    83 	vector < double > v (nlat * nlon);
    84 	vector < double > r (nlat * nlon);
    85 
    86 	SphereBarvortex bv (conf);
    87 
    88 	double nev1 = 0;
    89 
    90 	for (i = 0; i < nlat; ++i)
    91 	{
    92 		for (j = 0; j < nlon; ++j)
    93 		{
    94 			double phi    = -0.5 * M_PI + i * dlat;
    95 			double lambda = j * dlon;
    96 
    97 			r[i * nlon + j] = ans (phi, lambda, t);
    98 		}
    99 	}
   100 
   101 	while (true)
   102 	{
   103 		bv.S_step (&u[0], &r[0], t);
   104 		t += conf.tau;
   105 
   106 		if (it % 100 == 0)
   107 		{
   108 			nev1 = 0.0;
   109 			for (i = 0; i < nlat; ++i)
   110 			{
   111 				for (j = 0; j < nlon; ++j)
   112 				{
   113 					double phi    = -0.5 * M_PI + i * dlat;
   114 					double lambda = j * dlon;
   115 
   116 					v[i * nlon + j] = ans (phi, lambda, t);
   117 					//fprintf(stderr, "%.16lf %.16lf \n", u[i * nlon + j], v[i * nlon + j]);
   118 				}
   119 			}
   120 
   121 			nev1 = bv.dist(&u[0], &v[0]);
   122 
   123 			fprintf (stderr, "time=%lf nev1=%.16le \n", t, nev1);
   124 		}
   125 		r.swap(u);
   126 
   127 		it += 1;
   128 	}
   129 }
   130 
   131 inline double sign(double k)
   132 {
   133 	if (k > 0) {
   134 		return 1.0;
   135 	} else {
   136 		return -1.0;
   137 	}
   138 }
   139 
   140 double test_coriolis (double phi, double lambda)
   141 {
   142 	return 2 * sin(phi) + 0.5 * cos(2 * lambda) * sign(2 * phi) * ipow(sin(2 * phi), 2);
   143 }
   144 
   145 void output_psi(const char * prefix, const char * suffix,
   146 				const double * psi, long nlat, long nlon,
   147 				double U0, double PSI0,
   148 				SphereGrad & grad)
   149 {
   150 	vector < double > u (nlat * nlon);
   151 	vector < double > v (nlat * nlon);
   152 	vector < double > Psi (nlat * nlon);
   153 
   154 	grad.calc(&u[0], &v[0], &psi[0]);
   155 
   156 	vec_mult_scalar(&u[0], &u[0], -1.0, nlat * nlon);
   157 
   158 	char ubuf[1024]; char vbuf[1024]; char psibuf[1024];
   159 	char Ubuf[1024]; char Vbuf[1024]; char Psibuf[1024];
   160 
   161 	snprintf(ubuf, 1024,   "out/%snorm_u%s.txt", prefix, suffix);
   162 	snprintf(vbuf, 1024,   "out/%snorm_v%s.txt", prefix, suffix);
   163 	snprintf(psibuf, 1024, "out/%snorm_psi%s.txt", prefix, suffix);
   164 
   165 	snprintf(Ubuf, 1024,   "out/%sorig_u%s.txt", prefix, suffix);
   166 	snprintf(Vbuf, 1024,   "out/%sorig_v%s.txt", prefix, suffix);
   167 	snprintf(Psibuf, 1024, "out/%sorig_psi%s.txt", prefix, suffix);
   168 
   169 	mat_print(ubuf,   &u[0], nlat, nlon, "%23.16lf ");
   170 	mat_print(vbuf,   &v[0], nlat, nlon, "%23.16lf ");
   171 	mat_print(psibuf, &psi[0], nlat, nlon, "%23.16lf ");
   172 
   173 	vec_mult_scalar(&u[0], &u[0], U0, nlon * nlat);
   174 	vec_mult_scalar(&v[0], &v[0], U0, nlon * nlat);
   175 	vec_mult_scalar(&Psi[0],  &psi[0],  PSI0, nlon * nlat);
   176 
   177 	mat_print(Ubuf,   &u[0], nlat, nlon, "%23.16le ");
   178 	mat_print(Vbuf,   &v[0], nlat, nlon, "%23.16le ");
   179 	mat_print(Psibuf, &Psi[0], nlat, nlon, "%23.16le ");
   180 }
   181 
   182 void run_test(const char * srtm)
   183 {
   184 	long nlat = 5 * 19;
   185 	long nlon = 5 * 36;
   186 
   187 	SphereBarvortex::Conf conf;
   188 	conf.nlat     = nlat;
   189 	conf.nlon     = nlon;
   190 	conf.mu       = 1.5e-5;
   191 	conf.sigma    = 1.14e-2;
   192 	int part_of_the_day = 48;
   193 	conf.tau      = 2 * M_PI / (double) part_of_the_day;
   194 	conf.theta    = 0.5;
   195 	conf.k1       = 1.0;
   196 	conf.k2       = 1.0;
   197 	conf.rp       = 0;
   198 	conf.cor      = 0;//test_coriolis;
   199 
   200 	double dlat = M_PI / (nlat - 1);
   201 	double dlon = 2. * M_PI / nlon;
   202 	double t = 0;
   203 	double T = 2 * M_PI * 1000.0;
   204 
   205 	int i, j, it = 0;
   206 
   207 	vector < double > u (nlat * nlon);
   208 	vector < double > v (nlat * nlon);
   209 
   210 	vector < double > r (nlat * nlon);
   211 	vector < double > f (nlat * nlon);
   212 	vector < double > cor(nlat * nlon);
   213 	vector < double > rel(nlat * nlon);
   214 
   215 	double nr = 0;
   216 	double omg = 2.*M_PI/24./60./60.; // ?
   217 	double TE  = 1./omg;
   218 	double RE  = 6.371e+6;
   219 	double PSI0 = RE * RE / TE;
   220 	double U0  = 6.371e+6/TE;
   221 	const char * fn = srtm ? srtm : "";
   222 
   223 	if (fn) {
   224 		FILE * f = fopen(fn, "rb");
   225 		if (f) {
   226 			size_t size = nlat * nlon * sizeof(double);
   227 			if (fread(&rel[0], 1, size, f) != size) {
   228 				fprintf(stderr, "bad relief file format ! \n");
   229 			}
   230 		} else {
   231 			fprintf(stderr, "relief file not found ! \n");
   232 		}
   233 		fclose(f);
   234 	}
   235 
   236 	double rel_max = 0.0;
   237 	for (i = 0; i < nlat * nlon; ++i) {
   238 		if (rel_max < rel[i]) rel_max = rel[i];
   239 		//if (rel_max < fabs(rel[i])) rel_max = fabs(rel[i]);
   240 	}
   241 
   242 	for (i = 0; i < nlat; ++i)
   243 	{
   244 		for (j = 0; j < nlon; ++j)
   245 		{
   246 			double phi    = -0.5 * M_PI + i * dlat;
   247 			double lambda = j * dlon;
   248 
   249 			//double ff = -(M_PI / 4 * ipow(phi, 2) - fabs(ipow(phi, 3)) / 3.0) * 16.0 / M_PI / M_PI * 3.0 / U0;
   250 			//r[i * nlon + j] = (phi > 0) ? ff : -ff;
   251 			if (phi > 0) {
   252 				u[i * nlon + j] = (phi * (M_PI / 2. - phi) * 16 / M_PI / M_PI * 30.0 / U0);
   253 			} else {
   254 				u[i * nlon + j] = (-phi * (M_PI / 2. + phi) * 16 / M_PI / M_PI * 30.0 / U0);
   255 			}
   256 			v[i * nlon + j] = 0;
   257 			//cor[i * nlon + j] = conf.coriolis(phi, lambda);
   258 
   259 			//cor[i * nlon + j] = 1000 * rel[i * nlon + j] / rel_max + 2 * sin(phi);
   260 			//
   261 
   262 		//	rel[i * nlon + j] = 0.5 * sign(phi) * cos(2 * lambda) * ipow(sin(2 * phi), 2);
   263 
   264 			if (rel[i * nlon + j] > 0) {
   265 				rel[i * nlon + j] = 1.0 * rel[i * nlon + j] / rel_max;
   266 			} else {
   267 				rel[i * nlon + j] = 0.0;
   268 			}
   269 			cor[i * nlon + j] = rel[i * nlon + j] + 2 * sin(phi);
   270 		}
   271 	}
   272 
   273 	SphereOperator op(nlat, nlon, 0);
   274 	SphereLaplace lapl(op);
   275 	SphereGrad grad(op);
   276 	SphereVorticity vor(op);
   277 
   278 	vor.calc(&f[0], &u[0], &v[0]);
   279 	vor.test();
   280 	vec_mult_scalar(&f[0], &f[0], -1.0, nlat * nlon);
   281 #if 0
   282 	for (i = 0; i < nlat; ++i)
   283 	{
   284 		for (j = 0; j < nlon; ++j)
   285 		{
   286 			double phi    = -0.5 * M_PI + i * dlat;
   287 			if (phi < 0) {
   288 				f[i * nlon + j] *= -1.0;
   289 			}
   290 		}
   291 	}
   292 #endif
   293 	lapl.solve(&r[0], &f[0]);
   294 	vec_mult_scalar(&f[0], &f[0], conf.sigma, nlat * nlon);
   295 
   296 	conf.rp2  = &f[0];
   297 	conf.cor2 = &cor[0];
   298 
   299 	SphereBarvortex bv (conf);
   300 
   301 	Variance < double > var(u.size());
   302 
   303 	mat_print("out/cor.txt", &cor[0], nlat, nlon, "%23.16lf ");
   304 	mat_print("out/rel.txt", &rel[0], nlat, nlon, "%23.16lf ");
   305 	mat_print("out/rp.txt", &f[0], nlat, nlon, "%23.16lf ");
   306 	mat_print("out/u0.txt", &u[0], nlat, nlon, "%23.16lf ");
   307 	mat_print("out/v0.txt", &v[0], nlat, nlon, "%23.16lf ");
   308 
   309 	//exit(1);
   310 
   311 	while (t < T)
   312 	{
   313 		if (it % part_of_the_day == 0) {
   314 			char buf[1024];
   315 			nr = bv.norm(&r[0]);
   316 			if (isnan(nr)) break;
   317 			fprintf(stderr, "nr=%.16lf, t=%.16lf of %.16lf\n", nr, t, T);
   318 			snprintf(buf, 1024, "_%06d", it);
   319 			output_psi("", buf, &r[0], nlat, nlon, U0, PSI0, grad);
   320 
   321 			vector < double > m = var.m_current();
   322 			vector < double > d = var.current();
   323 
   324 			output_psi("m_", "", &m[0], nlat, nlon, U0, PSI0, grad);
   325 			output_psi("d_", "", &d[0], nlat, nlon, U0, PSI0, grad);
   326 		}
   327 
   328 		bv.S_step (&u[0], &r[0], t);
   329 		t += conf.tau;
   330 
   331 		var.accumulate(u);
   332 
   333 		r.swap(u);
   334 
   335 		it += 1;
   336 	}
   337 
   338 	if (!isnan(nr)) {
   339 		vector < double > m = var.m_current();
   340 		vector < double > d = var.current();
   341 
   342 		output_psi("m_", "", &m[0], nlat, nlon, U0, PSI0, grad);
   343 		output_psi("d_", "", &d[0], nlat, nlon, U0, PSI0, grad);
   344 	}
   345 }
   346 
   347 
   348 int main (int argc, char * argv[])
   349 {
   350 	//solve();
   351 
   352 	// exe [relief in binary format!]
   353 	run_test(argv[1]);
   354 }
   355