time | calls | line |
---|
| | 1 | function [P, u, v, rho, NodeP, Nodeu, Nodev] =...
|
| | 2 | FluidsSolver2_DO(app, SetupScript, PlotScript)
|
| | 3 | % function [P, u, v, rho, NodeP, Nodeu, Nodev] =...
|
| | 4 | % FluidsSolver2_DO(app, SetupScript, PlotScript)
|
| | 5 | %
|
| | 6 | % Solves the stochastic Navier-Stokes/Stokes equations with Boussinesq buoyancy
|
| | 7 | % approximation by a simple Finite Volume discretization on a uniform Cartesian mesh using
|
| | 8 | % an Incremental Pressure Correction in Rotational Form projection method (by default).
|
| | 9 | % This function uses Dynamically Orthogonal (DO) Equations for uncertainty quantification.
|
| | 10 | % For time marching, a first-order backward difference scheme is used.
|
| | 11 | % LU factorization is used to solve the linear systems. The advection is mexed.
|
| | 12 | %
|
| | 13 | %
|
| | 14 | % INPUTS:
|
| | 15 | %
|
| | 16 | % app: The application data structure of which the fields can also be
|
| | 17 | % added through the SetupScript.
|
| | 18 | % SetupScript: String input of filename used to setup the problem.
|
| | 19 | % PlotScript: String input of filename used to plot specific problem.
|
| | 20 | % Can also be used to save outputs and perform other tasks.
|
| | 21 | % Note: Variables u, v, and P, will be available for plotting.
|
| | 22 | %
|
| | 23 | %
|
| | 24 | % At a minimum, the structure app should contain the following fields:
|
| | 25 | %
|
| | 26 | % app.Nx: Number of interior P cells in x-direction (integer number)
|
| | 27 | % app.Ny: Number of interior P cells in y-direction (integer number)
|
| | 28 | % app.T: Final time
|
| | 29 | % app.dt: Timestep size
|
| | 30 | % app.PlotIntrvl: Number of time steps between two "PlotScript" calls
|
| | 31 | %
|
| | 32 | % Other optional fields of app:
|
| | 33 | %
|
| | 34 | % app.nu: Effective viscosity in x direction
|
| | 35 | % app.nu2: Effective viscosity in y direction
|
| | 36 | % app.kappa: Effective diffusivity of density in x direction
|
| | 37 | % app.kappa2: Effective diffusivity of density in y direction
|
| | 38 | % app.g: Effective gravity acceleration along negative y direction
|
| | 39 | % app.Stokes: If true, this function solves the Stokes equation
|
| | 40 | % app.NonInc: If true, solves the equations using the
|
| | 41 | % non-incremental Projection Method
|
| | 42 | % app.NonRot: If true, solves the equations using the
|
| | 43 | % Incremental Projection method in the non-rotational form
|
| | 44 | % app.Advect: 'TVD' -- Use the Total Variation Diminishing
|
| | 45 | % advection scheme (DEFAULT)
|
| | 46 | % 'QUICK' -- Quadratic Upwind Interpolation scheme for
|
| | 47 | % for Convective Kinetics
|
| | 48 | % 'UW' -- Use the UpWind advection scheme
|
| | 49 | % 'CDS' -- Use the Central Differencing Scheme
|
| | 50 | % app.Fcor: Function that sets the coriolis forces.
|
| | 51 | % Called in the codes as: app.Fcor(time, [X, Y])
|
| | 52 | % app.updateBcs: (Optional) Function that updates the time dependent boundary conditions.
|
| | 53 | %
|
| | 54 | %
|
| | 55 | % This solver needs the following variables correctly created in the SetupScript.
|
| | 56 | %
|
| | 57 | % Nt: Number of timesteps (integer number)
|
| | 58 | % dx: Size of control volume in x-direction
|
| | 59 | % dy: Size of control volume in y-direction
|
| | 60 | % bcsDrho: Density Dirichlet boundary conditions
|
| | 61 | % bcsDq: q (for Projection Method) Dirichlet boundary conditions
|
| | 62 | % bcsDu: U-velocity Dirichlet boundary conditions
|
| | 63 | % bcsDv: V-velocity Dirichlet boundary conditions
|
| | 64 | % bcsNrho: Density Neumann boundary conditions
|
| | 65 | % bcsNq: q (for Projection Method) Neumann boundary conditions
|
| | 66 | % bcsNu: U-velocity Neumann boundary conditions
|
| | 67 | % bcsNv: V-velocity Neumann boundary conditions
|
| | 68 | % NodeP: Pressure node-numbering matrix (see NodePad.m)
|
| | 69 | % Nodeu: U-velocity node-numbering matrix (see NodePad.m)
|
| | 70 | % Nodev: V-velocity node-numbering matrix (see NodePad.m)
|
| | 71 | % idsP: Interior Pressure cell id's (see NodePad.m)
|
| | 72 | % idsu: Interior U-velocity cell id's (see NodePad.m)
|
| | 73 | % idsv: Interior V-velocity cell id's (see NodePad.m)
|
| | 74 | % Fu(t, XY): Forcing function for U-velocity, XY =[XU(idsu), YU(idsu)]
|
| | 75 | % Fv(t, XY): Forcing function for V-velocity, XY =[XV(idsv), YV(idsv)]
|
| | 76 | % XU: Matrix of x-coordinates corresponding to U-velocity CV centers.
|
| | 77 | % XU(idsu) used as 'x' input to Fu. (see meshgrid)
|
| | 78 | % XV: Matrix of x-coordinates corresponding to V-velocity CV centers.
|
| | 79 | % YU(idsu) used as 'y' input to Fv. (see meshgrid)
|
| | 80 | % YU: Matrix of y-coordinates corresponding to U-velocity CV centers.
|
| | 81 | % XV(idsv) used as 'x' input to Fu. (see meshgrid)
|
| | 82 | % YV: Matrix of y-coordinates corresponding to V-velocity CV centers.
|
| | 83 | % YV(idsv) used as 'y' input to Fv. (see meshgrid)
|
| | 84 | % P: Initial Pressure vector. The first #Nbc terms contain
|
| | 85 | % the boundary condition values for q.
|
| | 86 | % u: Initial U-velocity vector. The first #Nbc terms contain
|
| | 87 | % the boundary condition values.
|
| | 88 | % v: Initial V-velocity vector. The first #Nbc terms contain
|
| | 89 | % the boundary condition values.
|
| | 90 | %
|
| | 91 | %
|
| | 92 | % OUTPUTS:
|
| | 93 | %
|
| | 94 | % P: Final Pressure vector, including the boundary conditions for q.
|
| | 95 | % u: Final U-velocity vector, including the boundary conditions.
|
| | 96 | % v: Final V-velocity vector, including the boundary conditions.
|
| | 97 | % rho: Final density vector, including the boundary conditions.
|
| | 98 | % NodeP: Pressure node-numbering matrix (useful for plotting)
|
| | 99 | % Nodeu: U-velocity node-numbering matrix (useful for plotting)
|
| | 100 | % Nodev: V-velocity node-numbering matrix (useful for plotting)
|
| | 101 | %
|
| | 102 | % Uses Matlab functions: symamd, lu
|
| | 103 | % See also: Diffusion_Operator, Grad2D_P, Grad2D_uv
|
| | 104 | %
|
| | 105 | % Date for Last Modification: Jan. 2014 (Last modified by Jing Lin)
|
| | 106 | %
|
| | 107 | % Authors: Matt Ueckermann, Themis Sapsis, Pierre Lermusiaux, Pat Haley
|
| | 108 |
|
| | 109 |
|
| | 110 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
| | 111 |
|
| | 112 | %% Preliminary setup
|
| | 113 |
|
| | 114 | % Run setup script
|
15.41 | 1 | 115 | eval(SetupScript);
|
| | 116 |
|
| | 117 | % Default options related to the solver
|
| 1 | 118 | if ~isfield(app, 'Stokes'), app.Stokes = 0; end;
|
| 1 | 119 | if ~isfield(app, 'NonInc'), app.NonInc = 0; end;
|
| 1 | 120 | if ~isfield(app, 'NonRot'), app.NonRot = 0; end;
|
| | 121 |
|
| | 122 | % Default options related to the tracer equations
|
| 1 | 123 | if ~exist('bcsDrho', 'var'), bcsDrho = zeros(size([bcsDq; bcsNq])); end;
|
| 1 | 124 | if ~exist('bcsOrho', 'var'), bcsOrho = []; end;
|
| 1 | 125 | if ~exist('bcsNrho', 'var'), bcsNrho = []; end;
|
| 1 | 126 | if ~exist('NodeRho', 'var'), NodeRho = NodeP; end;
|
| 1 | 127 | if ~exist('rho', 'var'), rho = zeros(size(P)); end;
|
| 1 | 128 | if ~isfield(app, 'kappa'), app.kappa = 0; end;
|
| 1 | 129 | if ~isfield(app, 'kappa2'), app.kappa2 = app.kappa; end;
|
< 0.01 | 1 | 130 | if ~isfield(app,'g'), app.g = 1; end;
|
| 1 | 131 | if ~isfield(app,'Frho'), app.Frho = @(t, XY, rho) zeros(size(XY, 1), 1); end;
|
| | 132 |
|
| | 133 | % Default options related to advection
|
| 1 | 134 | if ~isfield(app, 'Advect'), app.Advect = 'TVD'; end;
|
| | 135 |
|
| | 136 | % Default options related to diffusion
|
| 1 | 137 | if ~isfield(app, 'nu'), app.nu = 1; end;
|
| 1 | 138 | if ~isfield(app, 'nu2'), app.nu2 = app.nu; end;
|
| | 139 |
|
| | 140 | % Default options related to the Coriolis forces
|
| 1 | 141 | if ~isfield(app,'Fcor'), app.Fcor = @(t, XY) zeros(size(XY, 1), 1); end;
|
| | 142 |
|
| | 143 | % Default options related to open boundary conditions
|
| 1 | 144 | if ~exist('bcsOq','var'), bcsOq = []; end;
|
| 1 | 145 | if ~exist('bcsOu','var'), bcsOu = []; end;
|
| 1 | 146 | if ~exist('bcsOv','var'), bcsOv = []; end;
|
| 1 | 147 | if ~exist('bcsOrho','var'), bcsOrho = []; end;
|
| 1 | 148 | if (~isempty(bcsOu))||(~isempty(bcsOv))||(~isempty(bcsOrho))
|
| | 149 | error('Open boundary conditions can only be set for pressure!');
|
| | 150 | end;
|
| | 151 |
|
| | 152 | % Find number of boundary conditions and number of interior cells
|
| 1 | 153 | Nbcs = length(bcsDq) + length(bcsNq);
|
| 1 | 154 | Num_IntCell_P = max(NodeP(:)) - Nbcs;
|
| 1 | 155 | Num_IntCell_u = max(Nodeu(:)) - Nbcs;
|
| 1 | 156 | Num_IntCell_v = max(Nodev(:)) - Nbcs;
|
| | 157 |
|
| | 158 | % Default options related to DO
|
| 1 | 159 | if ~isfield(app, 'IP'), app.IP = [1, 1, 1]; end;
|
| 1 | 160 | if ~isfield(app, 'S'), app.S = 0; end;
|
| 1 | 161 | if ~exist('Yi', 'var'), Yi = 0; end;
|
| 1 | 162 | if ~isfield(app,'DOAdaptIntrvl')
|
| 1 | 163 | if length(app.S) == 2
|
| | 164 | app.DOAdaptIntrvl = 10;
|
| 1 | 165 | else
|
| 1 | 166 | app.DOAdaptIntrvl = 0;
|
| 1 | 167 | end;
|
| 1 | 168 | end;
|
| 1 | 169 | if ~isfield(app,'DO_cor_iter'), app.DO_cor_iter = 1; end;
|
| | 170 |
|
| | 171 | % Low storage Runge-Kutta coefficients
|
| 1 | 172 | rk4a = [ 0.0,...
|
| | 173 | -567301805773.0 / 1357537059087.0,...
|
| | 174 | -2404267990393.0 / 2016746695238.0,...
|
| | 175 | -3550918686646.0 / 2091501179385.0,...
|
| | 176 | -1275806237668.0 / 842570457699.0];
|
| 1 | 177 | rk4b = [1432997174477.0 / 9575080441755.0,...
|
| | 178 | 5161836677717.0 / 13612068292357.0,...
|
| | 179 | 1720146321549.0 / 2090206949498.0,...
|
| | 180 | 3134564353537.0 / 4481467310338.0,...
|
| | 181 | 2277821191437.0 / 14882151754819.0];
|
| 1 | 182 | rk4c = [ 0.0,...
|
| | 183 | 1432997174477.0 / 9575080441755.0,...
|
| | 184 | 2526269341429.0 / 6820363962896.0,...
|
| | 185 | 2006345519317.0 / 3224310063776.0,...
|
| | 186 | 2802321613138.0 / 2924317926251.0];
|
| | 187 |
|
| | 188 |
|
| | 189 | %% Construct diffusion operator matrices and corresponding RHS vectors
|
| | 190 |
|
0.38 | 1 | 191 | [Dfs_rho, Dfs_bc_rho, Dfs_bc_rhs_rho] = Diffusion_Operator...
|
| | 192 | ('P', NodeRho, bcsDrho, bcsOrho, bcsNrho, dx, dy, app.kappa, app.kappa2);
|
0.29 | 1 | 193 | [Dfs_q, Dfs_bc_q, Dfs_bc_rhs_q] = Diffusion_Operator...
|
| | 194 | ('P', NodeP, bcsDq, bcsOq, bcsNq, dx, dy, 1, 1, true);
|
0.23 | 1 | 195 | [Dfs_u, Dfs_bc_u, Dfs_bc_rhs_u] = Diffusion_Operator...
|
| | 196 | ('u', Nodeu, bcsDu, bcsOu, bcsNu, dx, dy, app.nu, app.nu2);
|
0.20 | 1 | 197 | [Dfs_v, Dfs_bc_v, Dfs_bc_rhs_v] = Diffusion_Operator...
|
| | 198 | ('v', Nodev, bcsDv, bcsOv, bcsNv, dx, dy, app.nu, app.nu2);
|
| | 199 |
|
< 0.01 | 1 | 200 | Dfs_u_TmMch = Dfs_u + (1/app.dt)*speye(size(Dfs_u));
|
| 1 | 201 | Dfs_v_TmMch = Dfs_v + (1/app.dt)*speye(size(Dfs_v));
|
< 0.01 | 1 | 202 | Dfs_rho_TmMch = Dfs_rho + (1/app.dt)*speye(size(Dfs_rho));
|
| | 203 |
|
| | 204 |
|
| | 205 | %% Construct the Coriolis operators
|
| | 206 |
|
| 1 | 207 | if (sum(abs(app.Fcor(0, [XV(idsv) YV(idsv)]))) > 0)
|
| | 208 | [Au2v, Av2u] = CoriolisAVG(app.Nx, app.Ny, Nodeu, Nodev, idsu, idsv, Nbcs);
|
| | 209 | Au2v = spdiags(app.Fcor(0, [XV(idsv) YV(idsv)]), 0, length(idsv), length(idsv))*Au2v;
|
| | 210 | Av2u = spdiags(app.Fcor(0, [XU(idsu) YU(idsu)]), 0, length(idsu), length(idsu))*Av2u;
|
| 1 | 211 | else
|
| 1 | 212 | Au2v = spalloc(length(v) - Nbcs,length(u),0);
|
| 1 | 213 | Av2u = spalloc(length(u) - Nbcs,length(v),0);
|
< 0.01 | 1 | 214 | end
|
| | 215 |
|
| | 216 |
|
| | 217 | %% LU factorization of matrices
|
| | 218 |
|
| | 219 | % First order matrix to give best spartsity pattern
|
0.07 | 1 | 220 | rhoperm = symamd(Dfs_rho_TmMch);
|
0.05 | 1 | 221 | qperm = symamd(Dfs_q);
|
0.05 | 1 | 222 | uperm = symamd(Dfs_u_TmMch);
|
0.05 | 1 | 223 | vperm = symamd(Dfs_v_TmMch);
|
| | 224 |
|
| | 225 | % LU factorization
|
0.56 | 1 | 226 | [Lrho, Urho] = lu(Dfs_rho_TmMch(rhoperm, rhoperm));
|
0.25 | 1 | 227 | [Lq, Uq] = lu(Dfs_q(qperm, qperm));
|
0.45 | 1 | 228 | [Lu, Uu] = lu(Dfs_u_TmMch(uperm, uperm));
|
0.43 | 1 | 229 | [Lv, Uv] = lu(Dfs_v_TmMch(vperm, vperm));
|
| | 230 |
|
| | 231 | % Get interior ids
|
| 1 | 232 | pid = Nbcs+1:length(P);
|
| 1 | 233 | uid = Nbcs+1:length(u);
|
| 1 | 234 | vid = Nbcs+1:length(v);
|
| 1 | 235 | srcid = 2:app.Nx+1;
|
| 1 | 236 | srcTopid = 2:app.Ny;
|
| 1 | 237 | srcBotid = 3:app.Ny+1;
|
| 1 | 238 | bcN_ID_u = [length(bcsDu)+1, Nbcs];
|
| 1 | 239 | bcN_ID_v = [length(bcsDv)+1, Nbcs];
|
| 1 | 240 | NbcsDrho = length(bcsDrho); %Needed for advection
|
| 1 | 241 | NbcsDu = length(bcsDu); %Needed for advection
|
< 0.01 | 1 | 242 | NbcsDv = length(bcsDv); %Needed for advection
|
| | 243 |
|
| | 244 |
|
| | 245 | %% Initialize variables and sizes
|
| | 246 |
|
| 1 | 247 | frho = zeros(length(pid), 1);
|
| 1 | 248 | fu = zeros(length(uid), 1);
|
| 1 | 249 | fv = zeros(length(vid), 1);
|
| | 250 |
|
| 1 | 251 | if (app.S(1) > 0)
|
< 0.01 | 1 | 252 | frhoi = zeros(length(pid), app.S(1));
|
< 0.01 | 1 | 253 | fui = zeros(length(uid), app.S(1));
|
< 0.01 | 1 | 254 | fvi = zeros(length(vid), app.S(1));
|
0.28 | 1 | 255 | frhoij = zeros(length(pid), app.S(1)^2);
|
0.28 | 1 | 256 | fuij = zeros(length(uid), app.S(1)^2);
|
1.54 | 1 | 257 | fvij = zeros(length(vid), app.S(1)^2);
|
| | 258 | else
|
| | 259 | frhoi = 0; fui = 0; fvi = 0; frhoij = 0; fuij= 0; fvij= 0;
|
| | 260 | end;
|
| | 261 |
|
| | 262 | % If stochastic modes were not initialized in setup script, initialize automatically.
|
| 1 | 263 | DOInit;
|
| 1 | 264 | if (~exist('rhoi', 'var'))&&((app.S(1) > 0)||(length(app.S) > 1))
|
| | 265 | rhoi = zeros(length(rho), app.S(1));
|
| | 266 | end;
|
| | 267 |
|
| | 268 |
|
| | 269 | %% Time marching to solve the time-evolving system
|
| | 270 |
|
| 1 | 271 | q = zeros(size(P));
|
< 0.01 | 1 | 272 | CYY = cov(Yi);
|
| 1 | 273 | T = 0; k = 0;
|
1.14 | 1 | 274 | eval(PlotScript);
|
| 1 | 275 | display('Paused at initial condition. Hit any key to continue');
|
| 1 | 276 | pause;
|
| | 277 |
|
| 1 | 278 | if (app.DOAdaptIntrvl > 0), DOAdapt_mex; end;
|
| | 279 |
|
| 1 | 280 | if isfield(app,'k');
|
| | 281 | kstart = app.k + 1;
|
| 1 | 282 | else
|
| 1 | 283 | kstart = 1;
|
| 1 | 284 | end;
|
| | 285 |
|
< 0.01 | 1 | 286 | for k = kstart : Nt
|
| 20 | 287 | T = app.dt*k;
|
0.01 | 20 | 288 | disp([' T=',num2str(T)]);
|
| | 289 |
|
| | 290 | % Need to save old modes to do the projections correctly
|
| 20 | 291 | ui_old = ui;
|
| 20 | 292 | vi_old = vi;
|
| 20 | 293 | rhoi_old = rhoi;
|
| | 294 |
|
| | 295 | % Calculate statistics
|
< 0.01 | 20 | 296 | MY = mean(Yi);
|
| 20 | 297 | for i = 1 : app.S(1)
|
| 800 | 298 | Yi(:,i) = Yi(:,i) - MY(i);
|
| 800 | 299 | end
|
| 20 | 300 | CYY = cov(Yi);
|
0.04 | 20 | 301 | CYY_Inv = pinv(CYY, max(abs(CYY(:)))*sqrt(eps));
|
6.50 | 20 | 302 | MYYY = mom_thrd(Yi);
|
| 20 | 303 | if (app.S(1) > 0), MYYY = reshape(MYYY, app.S(1)^2, app.S(1)); end;
|
| 20 | 304 | if (app.S(1) == 0), CYY = 0; end;
|
| | 305 |
|
| | 306 | % Solve mean field
|
| | 307 |
|
| | 308 | % Calculate pressure gradient
|
0.28 | 20 | 309 | [dpdx, dpdy] = Grad2D_P(P, NodeP, dx, dy, idsu, idsv);
|
| | 310 |
|
| | 311 | % Calculate Boussinesq gravity forcing term.
|
0.19 | 20 | 312 | src = app.g*0.5*(rho(NodeRho(srcTopid, srcid)) + rho(NodeRho(srcBotid, srcid)));
|
< 0.01 | 20 | 313 | src = src(idsv);
|
| | 314 |
|
| | 315 | % Calculate RHS vectors for mean u, v, and rho
|
0.29 | 20 | 316 | [fu, fv] = UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt, ...
|
| | 317 | u, v, u, v, Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
< 0.01 | 20 | 318 | fu = fu + Av2u * v;
|
0.01 | 20 | 319 | fv = fv - Au2v*u - src;
|
0.27 | 20 | 320 | frho = SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt, rho, u, v,...
|
| | 321 | NodeRho, Nodeu, Nodev, idsP, Nbcs, NbcsDrho, NbcsDu, NbcsDv);
|
| | 322 |
|
| | 323 | % Calculate fui and fvi forcings, as well as fuij, and fvij
|
| 20 | 324 | for i = 1 : app.S(1)
|
11.47 | 800 | 325 | [fui(:,i), fvi(:,i)] = UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 326 | ui(:,i), vi(:,i), u, v, Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
| | 327 |
|
| | 328 | % Compute two fluxes of convection by modes for "average TVD"
|
11.14 | 800 | 329 | [tmp, tmp1] = UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 330 | u, v, ui(:,i), vi(:,i), Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
11.19 | 800 | 331 | [tmp2, tmp3] = UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 332 | u, v, -ui(:,i), -vi(:,i), Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
| | 333 |
|
5.06 | 800 | 334 | src = app.g*0.5*(rhoi(NodeRho(srcTopid,srcid),i)+rhoi(NodeRho(srcBotid,srcid),i));
|
0.14 | 800 | 335 | src = src(idsv);
|
2.13 | 800 | 336 | fui(:,i) = fui(:,i) + 0.5*(tmp-tmp2) + Av2u*vi(:,i);
|
2.37 | 800 | 337 | fvi(:,i) = fvi(:,i) + 0.5*(tmp1-tmp3) - Au2v*ui(:,i) - src;
|
| | 338 |
|
34.28 | 800 | 339 | frhoi(:,i) = SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt, rhoi(:,i),...
|
| | 340 | u, v, NodeRho, Nodeu, Nodev, idsP, Nbcs, NbcsDrho, NbcsDu, NbcsDv)...
|
| | 341 | + 0.5 * ( SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt, rho, ui(:,i),...
|
| | 342 | vi(:,i), NodeRho, Nodeu, Nodev, idsP, Nbcs, NbcsDrho, NbcsDu, NbcsDv)...
|
| | 343 | - SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt, rho, -ui(:,i),...
|
| | 344 | -vi(:,i), NodeRho, Nodeu, Nodev, idsP, Nbcs, NbcsDrho, NbcsDu, NbcsDv) );
|
| | 345 |
|
| | 346 | % For stochastic boundary forcing, need to change above two lines
|
0.02 | 800 | 347 | for j = 1 : app.S(1)
|
472.79 | 32000 | 348 | [fuij(:, i + (j - 1) * app.S(1)), fvij(:, i + (j - 1) * app.S(1))] = ...
|
| | 349 | UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 350 | ui(:,i), vi(:,i), ui(:,j), vi(:,j), ...
|
| | 351 | Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
462.88 | 32000 | 352 | [tmp, tmp1] = ...
|
| | 353 | UVadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 354 | ui(:,i), vi(:,i), -ui(:,j), -vi(:,j), ...
|
| | 355 | Nodeu, Nodev, idsu, idsv, Nbcs, NbcsDu, NbcsDv);
|
933.44 | 32000 | 356 | frhoij(:,i+(j-1)*app.S(1)) = ...
|
| | 357 | 0.5 * ( SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 358 | rhoi(:,i), ui(:,j), vi(:,j), NodeRho, Nodeu, Nodev, idsP,...
|
| | 359 | Nbcs, NbcsDrho, NbcsDu, NbcsDv)...
|
| | 360 | - SCAadvect_TVD_mex(app.Nx, app.Ny, dx, dy, app.dt,...
|
| | 361 | rhoi(:,i), -ui(:,j), -vi(:,j), NodeRho, Nodeu, Nodev, idsP,...
|
| | 362 | Nbcs, NbcsDrho, NbcsDu, NbcsDv) );
|
| | 363 |
|
| | 364 | % To be consistent with the notation in the paper, let us take
|
| | 365 | % the negative sign of the above expression:
|
16.01 | 32000 | 366 | frhoij(:, i + (j-1)*app.S(1)) = -frhoij(:, i + (j-1)*app.S(1));
|
11.91 | 32000 | 367 | fuij(:, i + (j-1)*app.S(1)) = 0.5*(tmp - fuij(:, i + (j-1)*app.S(1)));
|
11.79 | 32000 | 368 | fvij(:, i + (j-1)*app.S(1)) = 0.5*(tmp1 - fvij(:, i + (j-1)*app.S(1)));
|
< 0.01 | 32000 | 369 | end;
|
< 0.01 | 800 | 370 | end;
|
| | 371 |
|
| | 372 | % Advance Yi's using RK4
|
| 20 | 373 | if (app.S(1) > 0)
|
0.99 | 20 | 374 | fui_diffusion = fui - Dfs_u * ui(uid, :);
|
0.96 | 20 | 375 | fvi_diffusion = fvi - Dfs_v * vi(vid, :);
|
1.20 | 20 | 376 | frhoi_diffusion = frhoi - Dfs_rho * rhoi(pid, :);
|
| 20 | 377 | end;
|
| 20 | 378 | RHSY = zeros(size(Yi));
|
| 20 | 379 | resYYt = zeros(size(Yi));
|
| 20 | 380 | for iRK = 1 : 5
|
| 100 | 381 | Tlocal = T + app.dt * rk4c(iRK);
|
| | 382 | % Calculate YiYj's
|
| 100 | 383 | for i=1:app.S(1)
|
| 4000 | 384 | for j=1:app.S(1)
|
0.46 | 160000 | 385 | YiYj(:, i + (j - 1)*app.S(1)) = Yi(:, i).*Yi(:, j);
|
0.06 | 160000 | 386 | end;
|
| 4000 | 387 | end;
|
34.56 | 100 | 388 | A1j = (dx*dy) * (app.IP(1)*(fui_diffusion'*ui(uid,:)) ...
|
| | 389 | + app.IP(2)*(fvi_diffusion'*vi(vid, :))...
|
| | 390 | + app.IP(3)*(frhoi_diffusion'* rhoi(pid, :)));
|
1134.42 | 100 | 391 | A2j = (dx*dy) * (app.IP(1)*(fuij'*ui(uid, :)) + ...
|
| | 392 | app.IP(2)*(fvij'*vi(vid, :)) + app.IP(3)*(frhoij'*rhoi(pid, :)));
|
3.66 | 100 | 393 | RHSY = Yi*A1j + (repmat(CYY(:)',[app.MC 1]) - YiYj)*A2j;
|
| | 394 | % RK time stepping
|
0.05 | 100 | 395 | resYYt = resYYt * rk4a(iRK) + app.dt*RHSY;
|
0.02 | 100 | 396 | Yi = Yi + rk4b(iRK) * resYYt;
|
| 100 | 397 | end;
|
| | 398 |
|
| | 399 | % Advance mean fields
|
5.74 | 20 | 400 | RHSq = (1/app.dt)*rho(pid) + frho - frhoij*CYY(:) + Dfs_bc_rhs_rho;
|
5.30 | 20 | 401 | RHSu = (1/app.dt)*u(uid) + fu - fuij*CYY(:) + Dfs_bc_rhs_u - dpdx + ...
|
| | 402 | Fu(T,[XU(idsu) YU(idsu)]);
|
5.22 | 20 | 403 | RHSv = (1/app.dt)*v(vid) + fv - fvij*CYY(:) + Dfs_bc_rhs_v - dpdy +...
|
| | 404 | Fv(T,[XV(idsv) YV(idsv)]);
|
| | 405 |
|
0.34 | 20 | 406 | rho(pid(rhoperm)) = Urho \ (Lrho \ RHSq(rhoperm));
|
0.25 | 20 | 407 | u(uid(uperm)) = Uu \ (Lu \ RHSu(uperm));
|
0.24 | 20 | 408 | v(vid(vperm)) = Uv \ (Lv \ RHSv(vperm));
|
| | 409 |
|
51.49 | 20 | 410 | frhoijmyyy = frhoij*MYYY;
|
14.27 | 20 | 411 | fuijmyyy = fuij*MYYY;
|
14.12 | 20 | 412 | fvijmyyy = fvij*MYYY;
|
| | 413 |
|
| | 414 | % Advance ui's, vi's, and rhoi's
|
| 20 | 415 | for i = 1 : app.S(1)
|
6.61 | 800 | 416 | f1rho = frhoi(:,i) - frhoijmyyy*CYY_Inv(:,i);
|
6.12 | 800 | 417 | f1u = fui(:,i) - fuijmyyy*CYY_Inv(:,i);
|
5.91 | 800 | 418 | f1v = fvi(:,i) - fvijmyyy*CYY_Inv(:,i);
|
1.69 | 800 | 419 | f2rho = f1rho - Dfs_rho*rhoi(pid,i);
|
1.55 | 800 | 420 | f2u = f1u - Dfs_u*ui(uid,i);
|
1.85 | 800 | 421 | f2v = f1v - Dfs_v*vi(vid,i);
|
| | 422 |
|
| | 423 | %Calculate inner product terms <ffiUj> -- there has to be app.S of them
|
41.42 | 800 | 424 | InProdi = (dx*dy) * (app.IP(1)*(f2u'* ui_old(uid,:)) + ...
|
| | 425 | app.IP(2)*(f2v'*vi_old(vid,:)) + app.IP(3)*(f2rho'*rhoi_old(pid,:)))';
|
| | 426 |
|
| | 427 | %We're going to treat the Laplacian for THIS mode implicitly.
|
| | 428 | %but the inner product treats the Laplcian EXplicitly
|
12.68 | 800 | 429 | [dpdx, dpdy] = Grad2D_P(Pi(:,i),NodeP,dx,dy,idsu,idsv);
|
13.66 | 800 | 430 | RHSu = (1/app.dt)*ui(uid,i) + f1u - dpdx - ui_old(uid,:)*InProdi;
|
| | 431 |
|
| | 432 | %NOTE! I am assuming that ui's are zero on the boundary. To
|
| | 433 | %introduce stochastic boundary forcings, add to the above line.
|
12.94 | 800 | 434 | RHSv = (1/app.dt)*vi(vid,i) + f1v - dpdy - vi_old(vid,:)*InProdi;
|
| | 435 |
|
| | 436 | %NOTE! I am assuming that vi's are zero on the boundary. To
|
| | 437 | %introduce stochastic boundary forcings, add to the above line.
|
9.97 | 800 | 438 | ui(uid(uperm),i) = Uu \ (Lu \ RHSu(uperm));
|
10.11 | 800 | 439 | vi(vid(vperm),i) = Uv \ (Lv \ RHSv(vperm));
|
| | 440 |
|
| | 441 | %And now the tracers
|
13.88 | 800 | 442 | RHSq = (1/app.dt)*rhoi(pid,i) + f1rho - rhoi_old(pid,:)*InProdi;
|
13.50 | 800 | 443 | rhoi(pid(rhoperm),i) = Urho \ (Lrho \ RHSq(rhoperm));
|
0.02 | 800 | 444 | end;
|
| | 445 |
|
| | 446 | % Calculate RHS vector for P
|
0.69 | 20 | 447 | [dudx, dvdy] = Grad2D_uv(u, v, Nodeu, Nodev, idsP, dx, dy, bcN_ID_u, bcN_ID_v);
|
< 0.01 | 20 | 448 | RHSq = Dfs_bc_rhs_q - (1/app.dt)*(dudx + dvdy);
|
1.03 | 20 | 449 | q(pid(qperm)) = Uq \ (Lq \ RHSq(qperm));
|
| | 450 |
|
| | 451 | % Correct Velocity
|
0.30 | 20 | 452 | [dqdx, dqdy] = Grad2D_P(q, NodeP, dx, dy, idsu, idsv);
|
0.05 | 20 | 453 | u(uid) = u(uid) - app.dt*dqdx;
|
0.02 | 20 | 454 | v(vid) = v(vid) - app.dt*dqdy;
|
| | 455 |
|
| | 456 | % Correct pressure
|
| 20 | 457 | if ~app.NonInc
|
0.03 | 20 | 458 | P(pid) = P(pid) + q(pid);
|
| 20 | 459 | if ~app.NonRot
|
0.01 | 20 | 460 | P(pid) = P(pid) - (app.nu*dudx + app.nu2*dvdy);
|
0.76 | 20 | 461 | [dudx, dvdy] =...
|
| | 462 | Grad2D_uv(u, v, Nodeu, Nodev, idsP, dx, dy, bcN_ID_u, bcN_ID_v);
|
0.03 | 20 | 463 | P(pid) = P(pid) + (app.nu*dudx + app.nu2*dvdy);
|
| 20 | 464 | end;
|
| 20 | 465 | end;
|
| | 466 |
|
| | 467 | % Remove the mean of the pressure (determined up to a constant)
|
< 0.01 | 20 | 468 | P(pid) = P(pid) - mean(P(pid));
|
| | 469 |
|
| | 470 | % Correct pressure for ui, vi's
|
| 20 | 471 | for i = 1:app.S(1)
|
| | 472 | % Calculate RHS vector for P
|
28.55 | 800 | 473 | [dudx, dvdy] =...
|
| | 474 | Grad2D_uv(ui(:,i), vi(:,i), Nodeu, Nodev, idsP, dx, dy, bcN_ID_u, bcN_ID_v);
|
0.97 | 800 | 475 | RHSq = Dfs_bc_rhs_q - (1/app.dt)*(dudx + dvdy);
|
40.21 | 800 | 476 | q(pid(qperm)) = Uq \ (Lq \ RHSq(qperm));
|
| | 477 |
|
| | 478 | % Correct Velocity
|
12.64 | 800 | 479 | [dqdx, dqdy] = Grad2D_P(q, NodeP, dx, dy, idsu, idsv);
|
1.04 | 800 | 480 | ui(uid,i) = ui(uid,i) - app.dt*dqdx;
|
1.09 | 800 | 481 | vi(vid,i) = vi(vid,i) - app.dt*dqdy;
|
| | 482 |
|
| | 483 | % Correct pressure
|
0.02 | 800 | 484 | if ~app.NonInc
|
1.51 | 800 | 485 | Pi(pid,i) = Pi(pid,i) + q(pid);
|
0.02 | 800 | 486 | if ~app.NonRot
|
1.31 | 800 | 487 | Pi(pid,i) = Pi(pid,i) - (app.nu*dudx + app.nu2*dvdy);
|
28.53 | 800 | 488 | [dudx, dvdy] = Grad2D_uv(ui(:,i), vi(:,i),...
|
| | 489 | Nodeu, Nodev, idsP, dx, dy, bcN_ID_u, bcN_ID_v);
|
1.27 | 800 | 490 | Pi(pid,i) = Pi(pid,i) + (app.nu*dudx + app.nu2*dvdy);
|
| 800 | 491 | end;
|
| 800 | 492 | end;
|
| | 493 |
|
| | 494 | % Remove the mean of the pressure (determined up to a constant)
|
1.26 | 800 | 495 | Pi(pid,i) = Pi(pid,i) - mean(Pi(pid,i));
|
0.01 | 800 | 496 | end;
|
| | 497 |
|
| | 498 | % CORRECT DO CONDITION FOR IMPLICIT TERMS
|
| 20 | 499 | for iter = 1 : app.DO_cor_iter
|
| | 500 | % Calculate the correction for each ui, vi, and rhoi
|
| | 501 | % use fui, fvi, and frhoi to save some memory
|
| 20 | 502 | for i = 1:app.S
|
2.68 | 800 | 503 | f2rho = -Dfs_rho * rhoi_old(pid, i);
|
2.79 | 800 | 504 | f2u = -Dfs_u * ui_old(uid, i);
|
2.48 | 800 | 505 | f2v = -Dfs_v * vi_old(vid, i);
|
| | 506 | %Calculate inner product terms <ffiUj> -- there has to be app.S of them
|
41.81 | 800 | 507 | InProdi = (app.IP(1) * (f2u' * ui_old(uid, :)) + ...
|
| | 508 | app.IP(2) * (f2v' * vi_old(vid, :)) + ...
|
| | 509 | app.IP(3) * (f2rho' * rhoi_old(pid, :)))' * (dx * dy);
|
12.31 | 800 | 510 | fui(:, i) = ui_old(uid, :) * InProdi;
|
12.18 | 800 | 511 | fvi(:, i) = vi_old(vid, :) * InProdi;
|
12.84 | 800 | 512 | frhoi(:, i) = rhoi_old(pid, :) * InProdi;
|
| | 513 |
|
| | 514 | % Now repeat at the new time-level
|
2.83 | 800 | 515 | f2rho = -Dfs_rho * rhoi(pid, i);
|
2.74 | 800 | 516 | f2u = -Dfs_u * ui(uid, i);
|
2.52 | 800 | 517 | f2v = -Dfs_v * vi(vid, i);
|
| | 518 | % Calculate inner product terms <ffiUj> -- there has to be app.S of them
|
41.86 | 800 | 519 | InProdi = (app.IP(1) * (f2u' * ui(uid, :)) + ...
|
| | 520 | app.IP(2) * (f2v' * vi(vid, :)) + ...
|
| | 521 | app.IP(3) * (f2rho' * rhoi(pid, :)))' * (dx * dy);
|
12.58 | 800 | 522 | fui(:, i) = fui(:, i) - ui(uid, :) * InProdi;
|
12.26 | 800 | 523 | fvi(:, i) = fvi(:, i) - vi(vid, :) * InProdi;
|
12.98 | 800 | 524 | frhoi(:, i) = frhoi(:, i) - rhoi(pid, :) * InProdi;
|
| 800 | 525 | end;
|
| | 526 |
|
| | 527 | % Now do the corrections
|
| 20 | 528 | for i = 1:app.S
|
1.20 | 800 | 529 | ui(uid, i) = ui(uid, i) + app.dt * fui(:, i);
|
1.09 | 800 | 530 | vi(vid, i) = vi(vid, i) + app.dt * fvi(:, i);
|
1.17 | 800 | 531 | rhoi(pid, i) = rhoi(pid, i) + app.dt * frhoi(:, i);
|
< 0.01 | 800 | 532 | end;
|
| | 533 | %Record old basis for next iteration
|
| 20 | 534 | ui_old = ui; vi_old = vi; rhoi_old = rhoi;
|
| 20 | 535 | end;
|
| | 536 |
|
32.43 | 20 | 537 | [Yi, ui, vi, Pi, rhoi] = DOorthnorm(app, dx, dy, Yi, ui, uid, vi, vid, Pi, pid, rhoi);
|
| | 538 |
|
| | 539 | %Adapt stochastic dimension if required
|
| 20 | 540 | if ~mod(k, app.DOAdaptIntrvl), DOAdapt_mex; end;
|
| | 541 |
|
| | 542 | %Plot solution
|
31.37 | 20 | 543 | if ~mod(k,app.PlotIntrvl), eval(PlotScript); end;
|
| 20 | 544 | end;
|
| | 545 |
|
| | 546 | %% Clean up any temporary files
|
| 1 | 547 | if exist('existbasis','var')
|
| | 548 | delete([d0,sprintf('/Save/DOAdaptSave/Basis/orth_basis%0.3d.mat',existbasis)]);
|
| | 549 | end
|