src/barvortex.cpp
author Alexey Ozeritsky <aozeritsky@gmail.com>
Fri Jun 11 21:50:18 2010 +0400 (20 months ago)
changeset 142 2aa3b89e9ccc
parent 1177ede4761bf23
child 151bcd55cafff19
permissions -rw-r--r--
fix
     1 /* Copyright (c) 2010 Alexey Ozeritsky
     2  * All rights reserved.
     3  *
     4  * Redistribution and use in source and binary forms, with or without
     5  * modification, are permitted provided that the following conditions
     6  * are met:
     7  * 1. Redistributions of source code must retain the above copyright
     8  *    notice, this list of conditions and the following disclaimer.
     9  * 2. Redistributions in binary form must reproduce the above copyright
    10  *    notice, this list of conditions and the following disclaimer in the
    11  *    documentation and/or other materials provided with the distribution.
    12  * 3. The name of the author may not be used to endorse or promote products
    13  *    derived from this software without specific prior written permission
    14  *
    15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    25  */
    26 
    27 #include <math.h>
    28 #include <string.h>
    29 
    30 #include "barvortex.h"
    31 #include "linal.h"
    32 
    33 using namespace std;
    34 using namespace linal;
    35 
    36 SphereBarvortex::SphereBarvortex (const SphereBarvortex::Conf & conf) : SphereNorm(conf.nlat, conf.nlon),
    37 		conf (conf), op (conf.nlat, conf.nlon, 0), lapl(op), jac (op),
    38 		lh (conf.nlat * conf.nlon)
    39 {
    40 	long nlat = conf.nlat;
    41 	long nlon = conf.nlon;
    42 	double dlat = M_PI / (nlat-1);
    43 	double dlon = 2. * M_PI /nlon;
    44 
    45 
    46 	for (int i = 0; i < nlat; ++i)
    47 	{
    48 		double phi    = -0.5 * M_PI + i * dlat;
    49 		for (int j = 0; j < nlon; ++j)
    50 		{
    51 			double lambda = j * dlon;
    52 			if (conf.cor) {
    53 				lh[i * nlon + j] = conf.cor(phi, lambda, 0, &conf);
    54 			} else if (conf.cor2) {
    55 				lh[i * nlon + j] = conf.cor2[i * nlon + j];
    56 			}
    57 		}
    58 	}
    59 }
    60 
    61 SphereBarvortex::~SphereBarvortex()
    62 {
    63 }
    64 
    65 void SphereBarvortex::S_step (double * out, const double * u, double t)
    66 {
    67 	long nlat    = conf.nlat;
    68 	long nlon    = conf.nlon;
    69 	long n       = conf.nlat * conf.nlon;
    70 	double dlat = M_PI / (nlat - 1);
    71 	double dlon = 2. * M_PI / nlon;
    72 	double tau   = conf.tau;
    73 	double theta = conf.theta;
    74 	double mu    = conf.mu;
    75 	double sigma = conf.sigma;
    76 	double k1    = conf.k1;
    77 	double k2    = conf.k2;
    78 	double nr, nr0 = norm(u);
    79 
    80 	array_t w (n);  // w = L(u)
    81 	array_t dw (n); // dw = L(w) = LL(u)
    82 
    83 	// next
    84 	array_t u_n (n);
    85 	array_t w_n (n);
    86 	array_t u_n1 (n);
    87 
    88 	// jac
    89 	array_t jac0(n);
    90 
    91 	// tmp
    92 	array_t tmp1(n);
    93 	array_t tmp2(n);
    94 
    95 	//
    96 	array_t FC (n);
    97 	array_t F (n);
    98 
    99 	// генерируем правую часть
   100 	// w/dt + mu (1-theta) L w - \sigma(1-theta) w -
   101 	// - k1 J(0.5(u+u), 0.5(w+w)) - k2 J(0.5(u+u), l + h) + f(x, y)
   102 
   103 	// w = L (u)
   104 	lapl.calc (&w[0], &u[0]);
   105 	// dw = L (w)
   106 	lapl.calc (&dw[0], &w[0]);
   107 
   108 	// w/dt + mu (1-theta) L w
   109 	vec_sum1 (&FC[0], &w[0], &dw[0], 1.0 / tau,
   110 	          mu * (1.0 - theta), n);
   111 	// w/dt + mu (1-theta) L w - \sigma (1-theta) w
   112 	vec_sum1 (&FC[0], &FC[0], &w[0], 1.0,
   113 	          -sigma * (1.0 - theta), n);
   114 
   115 	for (int i = 0; i < nlat; ++i)
   116 	{
   117 		double phi    = -0.5 * M_PI + i * dlat;
   118 		for (int j = 0; j < nlon; ++j)
   119 		{
   120 			double lambda = j * dlon;
   121 			if (conf.rp)
   122 			{
   123 				FC[i * nlon + j] += conf.rp (phi, lambda, t, &conf);
   124 			} else if (conf.rp2) {
   125 				FC[i * nlon + j] += conf.rp2[i * nlon + j];
   126 			}
   127 		}
   128 	}
   129 
   130 	memcpy(&u_n[0], &u[0], n * sizeof(double));
   131 	memcpy(&w_n[0], &w[0], n * sizeof(double));
   132 
   133 	// в FC содержится правая часть, которая не меняется при итерациях!
   134 
   135 	for (int it = 0; it < 1000; ++it) {
   136 		// k1 J(0.5(u+u), 0.5(w+w)) + k2 J(0.5(u+u), l + h)   =
   137 		// = J(0.5 (u+u), 0.5 k1 (w+w)) + J(0.5 (u+u), k2 (l + h)) =
   138 		// = J(0.5 (u+u), 0.5 k1 (w+w) + k2 (l + h))
   139 		vec_sum1(&tmp1[0], &w_n[0], &w[0], k1 * theta,
   140 				k1 * (1.0 - theta), n);
   141 		vec_sum1(&tmp1[0], &tmp1[0], &lh[0], 1.0, k2, n);
   142 		// 0.5(u+u)
   143 		vec_sum1(&tmp2[0], &u_n[0], &u[0], theta,
   144 				1.0 - theta, n);
   145 		// - k1 J(0.5(u+u), 0.5(w+w)) - k2 J(0.5(u+u), l + h)
   146 		jac.calc(&jac0[0], &tmp2[0], &tmp1[0]);
   147 		vec_sum1(&F[0], &FC[0], &jac0[0], 1.0, -1.0, n);
   148 		lapl.solve(&w_n[0], &F[0], -theta * mu, 1.0 / tau + theta * sigma);
   149 		lapl.solve(&u_n1[0], &w_n[0]);
   150 
   151 		nr = dist(&u_n1[0], &u_n[0]);
   152 		u_n1.swap(u_n);
   153 		if (nr / nr0 < 1e-14 || isnan(nr)) {
   154 			break;
   155 		}
   156 	}
   157 
   158 	memcpy(out, &u_n[0], n * sizeof(double));
   159 }
   160 
   161 void SphereBarvortex::L_step(double *u1, const double *u, const double * z)
   162 {
   163 	long nlat    = conf.nlat;
   164 	long nlon    = conf.nlon;
   165 	long n       = conf.nlat * conf.nlon;
   166 	double theta = conf.theta;
   167 	double mu    = conf.mu;
   168 	double sigma = conf.sigma;
   169 	double tau   = conf.tau;
   170 	double k1    = conf.k1;
   171 	double k2    = conf.k2;
   172 	double nr, nr0 = norm(u);
   173 
   174 	array_t tmp1(n);
   175 	array_t tmp2(n);
   176 
   177 	array_t dz(n);
   178 	array_t dw(n);
   179 	array_t w(n);
   180 
   181 	// next
   182 	array_t u_n (n);
   183 	array_t w_n (n);
   184 	array_t u_n1 (n);
   185 
   186 	// jac
   187 	array_t jac0(n);
   188 	array_t jac1(n);
   189 	array_t jac2(n);
   190 
   191 	// rp
   192 	array_t FC(n);
   193 	array_t F(n);
   194 
   195 	// dz = L(z)
   196 	lapl.calc(&dz[0], z);
   197 	// w = L(u)
   198 	lapl.calc(&w[0], u);
   199 	// dw = L(w)
   200 	lapl.calc(&dw[0], &w[0]);
   201 
   202 	// w/dt + mu (1-theta) L w
   203 	vec_sum1 (&FC[0], &w[0], &dw[0], 1.0 / tau,
   204 	          mu * (1.0 - theta), n);
   205 	// w/dt + mu (1-theta) L w - \sigma (1-theta) w
   206 	vec_sum1 (&FC[0], &FC[0], &w[0], 1.0,
   207 	          -sigma * (1.0 - theta), n);
   208 
   209 	memcpy(&u_n[0], &u[0], n * sizeof(double));
   210 	memcpy(&w_n[0], &w[0], n * sizeof(double));
   211 
   212 	// в FC содержится правая часть, которая не меняется при итерациях!
   213 
   214 	for (int it = 0; it < 1000; ++it) {
   215 		// k1 J(0.5(u+u), dz) + k1 J(z, 0.5(w+w)) + k2 J(0.5(u+u), l + h)
   216 
   217 		vec_sum1(&tmp1[0], &w_n[0], &w[0], theta,
   218 				(1.0 - theta), n);
   219 		vec_sum1(&tmp2[0], &u_n[0], &u[0], theta,
   220 				(1.0 - theta), n);
   221 
   222 		// J(0.5(u+u), dz)
   223 		jac.calc(&jac0[0], &tmp2[0],  &dz[0]);
   224 		// J(z, 0.5(w+w))
   225 		jac.calc(&jac1[0], &z[0],   &tmp1[0]);
   226 		// J(0.5(u+u), l + h)
   227 		jac.calc(&jac2[0], &tmp2[0], &lh[0]);
   228 
   229 		vec_sum1(&jac0[0], &jac0[0], &jac1[0], k1,  k1, n);
   230 		vec_sum1(&jac0[0], &jac0[0], &jac2[0], 1.0, k2, n);
   231 
   232 		vec_sum1(&F[0], &FC[0], &jac0[0], 1.0, -1.0, n);
   233 	
   234 		lapl.solve(&w_n[0], &F[0], -theta * mu, 1.0 / tau + theta * sigma);
   235 		lapl.solve(&u_n1[0], &w_n[0]);
   236 
   237 		nr = dist(&u_n1[0], &u_n[0]);
   238 		u_n1.swap(u_n);
   239 		if (nr / nr0 < 1e-14 || isnan(nr)) {
   240 			break;
   241 		}
   242 	}
   243 
   244 	memcpy(u1, &u_n[0], n * sizeof(double));
   245 }
   246 
   247 void SphereBarvortex::LT_step(double *v1, const double *v, const double * z)
   248 {
   249 	long nlat    = conf.nlat;
   250 	long nlon    = conf.nlon;
   251 	long n       = conf.nlat * conf.nlon;
   252 	double theta = conf.theta;
   253 	double mu    = conf.mu;
   254 	double sigma = conf.sigma;
   255 	double tau   = conf.tau;
   256 
   257 	array_t z_lapl(n);
   258 
   259 	array_t pt1 (n); //лаплас, умноженный на коэф
   260 	array_t pt2 (n); //лаплас в квадрате, умноженный на коэф
   261 	array_t pt3 (n); //якобиан, умноженный на коэф
   262 
   263 	lapl.calc(&z_lapl[0], z);
   264 
   265 	lapl.solve(v1, v);
   266 	lapl.solve(v1, v1, - theta * mu, 1.0 / tau + theta * sigma);
   267 
   268 	lapl.calc(&pt1[0], v1);
   269 	vec_mult_scalar(&pt1[0], &pt1[0], 1.0 / tau - (1. - theta) * sigma, n);
   270 
   271 	lapl.calc(&pt2[0], v1);
   272 	lapl.calc(&pt2[0], &pt2[0]);
   273 
   274 	vec_mult_scalar(&pt2[0], &pt2[0], (1. - theta) * mu, n);
   275 
   276 	array_t tmp(n);
   277 	array_t p_lapl(n);
   278 	jac.calc_t(&tmp[0], v1, &lh[0]);
   279 	jac.calc_t(&p_lapl[0], z, v1);
   280 	lapl.calc(&p_lapl[0], &p_lapl[0]);
   281 	jac.calc_t(&pt3[0], v1, &z_lapl[0]);
   282 	vec_sum(&pt3[0], &pt3[0], &p_lapl[0], n);
   283 	vec_sum(&pt3[0], &pt3[0], &tmp[0], n);
   284 	
   285 	//vector_mult_scalar(&pt3[0], &pt3[0], -conf->rho, nn); //TODO: k1, k2
   286 
   287 	memset(v1, 0, n * sizeof(double));
   288 	vec_sum(v1, v1, &pt1[0], n);
   289 	vec_sum(v1, v1, &pt2[0], n);
   290 	vec_sum(v1, v1, &pt3[0], n);
   291 }
   292 
   293 void SphereBarvortex::L_1_step(double *u1, const double *u, const double * z)
   294 {
   295 	long nlat    = conf.nlat;
   296 	long nlon    = conf.nlon;
   297 	long n       = conf.nlat * conf.nlon;
   298 	double theta = conf.theta;
   299 	double mu    = conf.mu;
   300 	double sigma = conf.sigma;
   301 	double tau   = conf.tau;
   302 
   303 	array_t z_lapl(n);
   304 
   305 	array_t tmp (n);
   306 	array_t pt1 (n); //лаплас, умноженный на коэф
   307 	array_t pt2 (n); //лаплас в квадрате, умноженный на коэф
   308 	array_t pt3 (n); //якобиан, умноженный на коэф
   309 
   310 	lapl.calc(&z_lapl[0], z);
   311 	lapl.calc(&pt1[0], u); //первая часть - лаплас, умноженный на коэф,
   312 
   313 	jac.calc(&pt3[0], &u[0], &lh[0]);
   314 	jac.calc(&tmp[0], z, &pt1[0]);        vec_sum(&pt3[0], &pt3[0], &tmp[0], n);
   315 	jac.calc(&tmp[0], &u[0], &z_lapl[0]); vec_sum(&pt3[0], &pt3[0], &tmp[0], n);
   316 	//vec_mult_scalar(&pt3[0], &pt3[0], conf->rho, n); // TODO: k1, k2
   317 
   318 	lapl.calc(&pt2[0], &pt1[0]);
   319 	vec_mult_scalar(&pt2[0], &pt2[0], ( - theta) * mu, n);
   320 
   321 	vec_mult_scalar(&pt1[0], &pt1[0], 1 / tau + theta * sigma, n);
   322 
   323 	memset(u1, 0, n * sizeof(double));
   324 	vec_sum(u1, u1, &pt1[0], n);
   325 	vec_sum(u1, u1, &pt2[0], n);
   326 	vec_sum(u1, u1, &pt3[0], n);
   327 
   328 	lapl.solve(u1, u1, (1.0 - theta) * mu, 1 / tau - (1.0 - theta) * sigma);
   329 	lapl.solve(u1, u1);
   330 }
   331 
   332 void SphereBarvortex::p2u(double * u, const double * p)
   333 {
   334 	memcpy(u, p, conf.nlat * conf.nlon * sizeof(double));
   335 }
   336 
   337 void SphereBarvortex::u2p(double * p, const double * u)
   338 {
   339 	memcpy(p, u, conf.nlat * conf.nlon * sizeof(double));
   340 }