ODT
Loading...
Searching...
No Matches
micromixer.cc
Go to the documentation of this file.
1
6#include "micromixer.h"
7#include "domain.h"
8#include <cmath>
9#include <algorithm>
10#include <iostream>
11#include <numeric> //accumulate
12
13#include "interp_linear.h"
14
16
20 cvode = new cvodeDriver();
21 nsteps = 0;
22}
23
25
30void micromixer::init(domain *p_domn) {
31 domn = p_domn;
32
33 bool LincludeRhsMix = (domn->pram->Lsolver=="SEMI-IMPLICIT") ? true : false;
34 cvode->init(domn, LincludeRhsMix);
35}
36
38
41void micromixer::advanceOdt(const double p_tstart, const double p_tend, const int iLevel) {
42
43 tstart = p_tstart;
44 tend = p_tend;
45
47 if(domn->pram->LdoDL) do_DL("init");
48
49 for(time=tstart; time<tend; time+=dt, nsteps++) {
50
52 setNominalStepSize(); // resets LforceSetNominalStepSize
54 if(domn->pram->Lsolver=="EXPLICIT")
56 else if(domn->pram->Lsolver=="SEMI-IMPLICIT")
58 else if(domn->pram->Lsolver=="STRANG")
60
62
63 }
64
65 if(domn->pram->LdoDL) do_DL("calc a");
66
67}
69
77
79
86
87 if (domn->pram->Lspatial) {
88 double velMin = *min_element(domn->uvel->d.begin(), domn->uvel->d.end());
89 if (velMin <= 0.0) {
90 cout << "\nError micromixer::setNominalStepSize: velMin = " << velMin << ": neg or 0" << endl;
91 exit(0);
92 }
93 }
94
96
97 double coef = 0.0;
98 double dmb;
99 for (int i=0; i < domn->ngrd; i++) {
100 dmb = domn->dvisc->d.at(i) / domn->rho->d.at(i) / dx.at(i) / dx.at(i);
101 if (domn->pram->Lspatial)
102 dmb /= domn->uvel->d.at(i);
103 if (dmb > coef)
104 coef = dmb;
105 }
106 dtStepNominal = domn->pram->diffCFL * 0.5 / coef;
107
109}
110
112
119
121
122 if (time+dt > domn->io->dumpTimes.at(domn->io->iNextDumpTime)) {
124 domn->io->LdoDump = true;
125 }
126
127 if (time + dt > tend) {
128 dt = (tend - time)*(1.0+1.0E-8);
129 domn->io->LdoDump = false;
130 }
131}
132
134
138
139 setGridDxcDx();
140 setGf();
141 if(domn->pram->LdoDL) do_DL("set DL_1");
142
144
146 if(domn->pram->Lspatial) transform(oldrho_or_rhov.begin(), oldrho_or_rhov.end(), domn->uvel->d.begin(), oldrho_or_rhov.begin(), multiplies<double>());
147
148 for(int k=0; k<domn->v.size(); k++)
149 if(domn->v.at(k)->L_transported) {
150 domn->v.at(k)->getRhsMix(gf, dxc);
151 domn->v.at(k)->getRhsSrc();
152 }
153
154 for(int k=0; k<domn->v.size(); k++)
155 if(domn->v.at(k)->L_transported)
156 for(int i=0; i < domn->ngrd; i++)
157 domn->v.at(k)->d.at(i) = domn->v.at(k)->d.at(i) + dt*( domn->v.at(k)->rhsMix.at(i) + domn->v.at(k)->rhsSrc.at(i));
158
159 updateGrid(); // update cell sizes due to rho or rho*v variations (continuity)
160
161 if(domn->pram->LdoDL) do_DL("set DL_2");
162
163 domn->mesher->enforceDomainSize(); // chop the domain
164
165}
166
168
177
178 if(domn->pram->Lsolver!="SEMI-IMPLICIT")
179 return;
180
181 setGridDxcDx();
182 setGf();
185 if(domn->pram->Lspatial) transform(oldrho_or_rhov.begin(), oldrho_or_rhov.end(), domn->uvel->d.begin(), oldrho_or_rhov.begin(), multiplies<double>());
186 if(domn->pram->LdoDL) do_DL("set DL_1");
187
188 //--------------- Set the explicit (mixing) terms
189
190 for(int k=0; k<domn->v.size(); k++)
191 if(domn->v.at(k)->L_transported)
192 domn->v.at(k)->getRhsMix(gf, dxc);
193
194 //--------------- Perform the implicit integration on each cell
195
196 for(int i=0; i<domn->ngrd; i++)
198
199 //---------------
200
201 updateGrid(); // update cell sizes due to density variations (continuity)
202
203 if(domn->pram->LdoDL) do_DL("set DL_2");
204
205 domn->mesher->enforceDomainSize(); // chop the domain
206
207}
208
210
219
220 if(domn->pram->Lsolver!="STRANG")
221 return;
222
223 //--------------- First step: phi_1 = phi_0 + 0.5*dt*D(phi_0)
224
225 setGridDxcDx();
226 setGf();
229 if(domn->pram->Lspatial) transform(oldrho_or_rhov.begin(), oldrho_or_rhov.end(), domn->uvel->d.begin(), oldrho_or_rhov.begin(), multiplies<double>());
230
231 for(int k=0; k<domn->v.size(); k++)
232 if(domn->v.at(k)->L_transported)
233 domn->v.at(k)->getRhsMix(gf, dxc);
234
235 for(int k=0; k<domn->v.size(); k++)
236 if(domn->v.at(k)->L_transported)
237 for(int i=0; i < domn->ngrd; i++)
238 domn->v.at(k)->d.at(i) = domn->v.at(k)->d.at(i) + 0.5*dt*domn->v.at(k)->rhsMix.at(i);
239
240 updateGrid(); // update cell sizes due to density variations (continuity)
241
242 //--------------- Second step: phi_2 = phi_1 + dt*S(phi_2)
243 // (actually: dphi/dt = S(phi), with initial condition phi=phi_1. Implicit.)
244
245 setGridDxcDx();
246 //not needed: setGf();
249 if(domn->pram->Lspatial) transform(oldrho_or_rhov.begin(), oldrho_or_rhov.end(), domn->uvel->d.begin(), oldrho_or_rhov.begin(), multiplies<double>());
250
251 for(int k=0; k<domn->v.size(); k++)
252 if(domn->v.at(k)->L_transported)
253 domn->v.at(k)->getRhsSrc();
254
255 for(int i=0; i<domn->ngrd; i++)
257
258 updateGrid(); // update cell sizes due to density variations (continuity)
259
260 //--------------- Third step: phi_3 = phi_2 + 0.5*dt*D(phi_2)
261
262 setGridDxcDx();
263 setGf();
266 if(domn->pram->Lspatial) transform(oldrho_or_rhov.begin(), oldrho_or_rhov.end(), domn->uvel->d.begin(), oldrho_or_rhov.begin(), multiplies<double>());
267
268 for(int k=0; k<domn->v.size(); k++)
269 if(domn->v.at(k)->L_transported)
270 domn->v.at(k)->getRhsMix(gf, dxc);
271
272 for(int k=0; k<domn->v.size(); k++)
273 if(domn->v.at(k)->L_transported)
274 for(int i=0; i < domn->ngrd; i++)
275 domn->v.at(k)->d.at(i) = domn->v.at(k)->d.at(i) + 0.5*dt*domn->v.at(k)->rhsMix.at(i);
276
277 updateGrid(); // update cell sizes due to density variations (continuity)
278
279 //-------------------------
280
281 domn->mesher->enforceDomainSize(); // chop the domain (for strang, just at the final step)
282
283}
284
286
290
291 gf.resize(domn->ngrdf, 0.0);
292
293 for (int i=1, im=0; i<domn->ngrd; i++, im++) // interior
294 gf.at(i) = 2.0 / (dx.at(im) + dx.at(i));
295
296 gf.at(0) = 2.0 / dx.at(0); // lo boundary
297 gf.at(domn->ngrd) = 2.0 / dx.at(domn->ngrd - 1); // hi boundary
298 if (domn->pram->bcType == "PERIODIC") { // periodic
299 gf.at(0) = 2.0 / (dx.at(0) + dx.at(domn->ngrd - 1));
300 gf.at(domn->ngrd) = gf.at(0);
301 }
302
303}
304
306
310
311 //-------------- return for fixed grid cases
312
313 if((domn->pram->bcType=="WALL" && (domn->pram->vBClo==0 || domn->pram->vBChi==0)))
314 return;
315
316 //-------------- handle wall suction/blowing case
317
318 if(domn->pram->bcType=="WALL" && (domn->pram->vBClo !=0 || domn->pram->vBChi != 0)){
319
320 //---------- move all faces over (assuming vBClo > 0)
321
322 if(domn->pram->vBClo <=0) {
323 cout << "\nError micromixer::updateGrid: vBClo is <= 0.0 for suction/blowing case." << endl;
324 exit(0);
325 }
326
327 double dx = domn->pram->vBClo * dt;
328 for(int i=0; i<domn->ngrdf; i++)
329 domn->posf->d[i] += dx;
330
331 //---------- insert a cell at the beginning of domain
332
333 for(int k=0; k < domn->v.size(); k++)
334 domn->v[k]->d.insert(domn->v[k]->d.begin(), domn->domc->inlet_cell_dv_props[k]);
335 domn->pos->d[0] = 0.5*(domn->posf->d[0] + domn->posf->d[1] );
336 domn->ngrd++;
337 domn->ngrdf++;
338
339 domn->mesher->merge2cells(0, true);
340
341 if((domn->posf->d[1]-domn->posf->d[0]) > 2.0*(domn->posf->d[2]-domn->posf->d[1])){
342 vector<double> faces{domn->posf->d[0], 0.5*(domn->posf->d[0]+domn->posf->d[1]), domn->posf->d[1]};
343 domn->mesher->splitCell(0,1,faces);
344 }
345
346 //---------- at the end of domain split cell and delete the overhang
347
348 domn->mesher->enforceDomainSize(); // chop the domain (for strang, just at the final step)
349
350 LforceSetNominalStepSize = true; // we changed the grid, so indicate to recompute nominal timestep size
351
352 }
353
354 //-------------- general variable density/outflow case
355
356 else {
357
358 domn->rho->setVar();
359
360 vector<double> dxc2(domn->ngrd);
361 for(int i=0; i<domn->ngrd; i++)
362 dxc2[i] = dxc.at(i)*(oldrho_or_rhov.at(i)/domn->rho->d.at(i));
363 if(domn->pram->Lspatial)
364 for(int i=0; i<domn->ngrd; i++)
365 dxc2[i] /= domn->uvel->d.at(i);
366
367 //-------------
368
369 domn->mesher->setGridFromDxc(dxc2);
370 }
371
372
373}
374
376
382
383 if (domn->pram->Lspatial && *min_element(dx.begin(), dx.end()) < 0.9*domn->pram->dxmin) {
384#ifndef SILENT
385 *domn->io->ostrm << endl << "#------- ADAPTING DURING DIFFUSION" << " " << domn->ngrd;
386#endif
387 domn->mesher->adaptGrid(0, domn->ngrd-1);
388 return true;
389 }
390 return false;
391}
392
394
398void micromixer::do_DL(string doWhat) {
399
400 if(!domn->pram->LdoDL)
401 return;
402
403 //--------------------------------------------------
404 if(doWhat == "init") {
405
406 uDL_1 = vector<double>(domn->ngrd, 0.0);
407 uDL_2 = vector<double>(domn->ngrd, 0.0);
408 xDL_1 = domn->pos->d;
409 xDL_2 = domn->pos->d;
410 posDL_old = domn->pos->d;
411 domn->aDL->d = vector<double>(domn->ngrd, 0.0);
412 }
413 //--------------------------------------------------
414 else if(doWhat == "set DL_1") {
415
416 xDL_1 = xDL_2;
417 uDL_1 = uDL_2;
418 posDL_old = domn->pos->d;
419
420 }
421 //--------------------------------------------------
422 else if(doWhat == "set DL_2") {
423
424 xDL_2.resize(domn->ngrd);
425 uDL_2.resize(domn->ngrd);
426
427 for(int i=0; i<domn->ngrd; i++) {
428 uDL_2.at(i) = (domn->pos->d[i] - posDL_old.at(i)) / (domn->pram->Lspatial ? dt/domn->uvel->d[i] : dt);
429 xDL_2.at(i) = 0.5*(posDL_old.at(i) + domn->pos->d[i]);
430 }
431 }
432 //--------------------------------------------------
433 else if(doWhat == "calc a") {
434
435 vector<double> dmb;
436
437 dmb = uDL_1;
438 Linear_interp Linterp(xDL_1, dmb);
439 uDL_1.resize(domn->ngrd);
440 for(int i=0; i<domn->ngrd; i++)
441 uDL_1.at(i)= Linterp.interp(domn->pos->d[i]);
442
443 dmb = uDL_2;
444 Linterp = Linear_interp(xDL_2, dmb);
445 uDL_2.resize(domn->ngrd);
446 for(int i=0; i<domn->ngrd; i++)
447 uDL_2.at(i)= Linterp.interp(domn->pos->d[i]);
448
449 for(int i=0; i<domn->ngrd; i++)
450 domn->aDL->d.at(i) = (uDL_2.at(i) - uDL_1.at(i)) / (domn->pram->Lspatial ? dt/domn->uvel->d[i] : dt);
451 }
452}
453
455
462
463
464#include <iomanip>
466
467 setGridDxcDx();
468 double mom = 0.0;
469
470 for(int i=0; i<domn->ngrd; i++)
471 mom += domn->rho->d[i] * domn->uvel->d[i] * (domn->uvel->d[i]-0.0) * dxc[i];
472
473 cout << scientific;
474 cout << setprecision(13);
475 cout << endl << "check: " << io << " " << mom;
476}
477
double interp(double x)
void init(domain *p_domn, const bool p_LincludeRhsMix)
void integrateCell(int p_iC, double tres)
int ngrd
number of grid cells
Definition domain.h:42
domaincase * domc
domaincase class: set specific vars...
Definition domain.h:84
dv * uvel
Definition domain.h:51
dv * posf
access as: posf->d[i], or posf->var_name, etc.
Definition domain.h:48
dv * aDL
Definition domain.h:62
dv * pos
pointers to gas properties
Definition domain.h:47
int ngrdf
number of grid cell faces = ngrd+1
Definition domain.h:43
meshManager * mesher
pointer to mesh manager object
Definition domain.h:78
inputoutput * io
pointer to input/output object
Definition domain.h:72
dv * dvisc
Definition domain.h:50
vector< dv * > v
All domain variables are stored in here.
Definition domain.h:45
param * pram
pointer to the parameters object
Definition domain.h:73
dv * rho
Definition domain.h:49
vector< double > inlet_cell_dv_props
list of all dv properties for inserted inlet cell for channel suction/blowing case
Definition domaincase.h:30
virtual void setCaseSpecificVars()
Definition domaincase.h:35
vector< double > d
the data
Definition dv.h:30
virtual void setVar(const int ipt=-1)
Definition dv.h:44
int iNextDumpTime
index of next dump time
Definition inputoutput.h:50
bool LdoDump
flag for whether we are dumping a file
Definition inputoutput.h:51
ostream * ostrm
Runtime: points to cout or to a file.
Definition inputoutput.h:33
void dumpDomainIfNeeded()
calls outputProperties for dumpTimes
vector< double > dumpTimes
vector of dump times
Definition inputoutput.h:49
void setGridDx(const domain *line, vector< double > &dx)
void setGridFromDxc(const vector< double > &dxc2)
void merge2cells(const int imrg, const bool LconstVolume=false)
void splitCell(const int isplt, const int nsplt, const vector< double > &cellFaces)
void setGridDxc(const domain *line, vector< double > &dxc, double C)
void adaptGrid(int iLower, int iUpper)
void enforceDomainSize()
vector< double > xDL_2
for DL instability: = "new" cell center positions
Definition micromixer.h:47
virtual void advanceOdt(const double p_tstart, const double p_tend, const int iLevel=-1)
Definition micromixer.cc:41
void advanceOdtSingleStep_SemiImplicit()
vector< double > uDL_2
for DL instability: new velocity
Definition micromixer.h:45
double dtStepNominal
nominal step size
Definition micromixer.h:35
vector< double > dx
abs(\Delta(x))
Definition micromixer.h:39
vector< double > xDL_1
for DL instability: = "old" cell center positions
Definition micromixer.h:46
void advanceOdtSingleStep_StrangSplit()
vector< double > gf
grid factor for derivatives: (df/dx) = gf * (f - f)
Definition micromixer.h:40
bool LforceSetNominalStepSize
used in updateGrid when splitting cells to indicate to reset timestep size later
Definition micromixer.h:76
void check_balance(int io)
virtual void setGridDxcDx()
sets the dxc array
Definition micromixer.cc:71
vector< double > dxc
abs(\Delta(x^c))
Definition micromixer.h:38
void init(domain *p_domn)
Definition micromixer.cc:30
double tend
Definition micromixer.h:34
vector< double > posDL_old
for DL instability: = "new" cell center positions
Definition micromixer.h:48
double dt
actual step size (shortened based on output or tend)
Definition micromixer.h:36
void updateGrid()
enforce the continuity condition: (e.g., rho*dx = const).
virtual bool adaptGridIfNeeded()
expansion or contraction --> adapt
int nsteps
total number of timesteps taken during simulation
Definition micromixer.h:52
vector< double > uDL_1
for DL instability: old velocity
Definition micromixer.h:44
domain * domn
pointer to domain object
Definition micromixer.h:29
cvodeDriver * cvode
pointer to cvode driver object for implicit ODE integration (stiff)
Definition micromixer.h:30
virtual void setGf()
sets the gf array
virtual void set_oldrho_or_rhov()
record old rho (or rho*u) for continuity
void advanceOdtSingleStep_Explicit()
void setStepSize()
set a local dt for interruptions (dump or tend)
void do_DL(string doWhat)
double tstart
Definition micromixer.h:32
double time
current time
Definition micromixer.h:33
virtual void setNominalStepSize()
sets a nominal dt for the whole period
Definition micromixer.cc:85
vector< double > oldrho_or_rhov
store the old density for continuity
Definition micromixer.h:50
int cCoord
1 = planar, 2 = cylindrical, 3 = spherical
Definition param.h:68
double diffCFL
multiplies min diffusion timestep
Definition param.h:49
double dxmin
min grid spacing: = dxmin / domain length
Definition param.h:72
double vBChi
Dirichlet velocity boundary condition.
Definition param.h:97
bool Lspatial
spatial formulation if true
Definition param.h:62
double vBClo
Dirichlet velocity boundary condition.
Definition param.h:96
string Lsolver
EXPLICIT, SEMI-IMPLICIT, or STRANG.
Definition param.h:60
bool LdoDL
flag to do the DL energy from the DL instability
Definition param.h:54
string bcType
OUTFLOW, PERIODIC, WALL, WALL_OUT.
Definition param.h:67
Header file for class domain.
Header file for class micromixer.