1 #include "finitevolume1d.h" 2 #include <petscdmda.h> 3 #include <petscdraw.h> 4 #include <petsc/private/tsimpl.h> 5 6 #include <petsc/private/kernels/blockinvert.h> /* For the Kernel_*_gets_* stuff for BAIJ */ 7 const char *FVBCTypes[] = {"PERIODIC","OUTFLOW","INFLOW","FVBCType","FVBC_",0}; 8 9 static inline PetscReal Sgn(PetscReal a) { return (a<0) ? -1 : 1; } 10 static inline PetscReal Abs(PetscReal a) { return (a<0) ? 0 : a; } 11 static inline PetscReal Sqr(PetscReal a) { return a*a; } 12 13 PETSC_UNUSED static inline PetscReal MinAbs(PetscReal a,PetscReal b) { return (PetscAbs(a) < PetscAbs(b)) ? a : b; } 14 static inline PetscReal MinMod2(PetscReal a,PetscReal b) { return (a*b<0) ? 0 : Sgn(a)*PetscMin(PetscAbs(a),PetscAbs(b)); } 15 static inline PetscReal MaxMod2(PetscReal a,PetscReal b) { return (a*b<0) ? 0 : Sgn(a)*PetscMax(PetscAbs(a),PetscAbs(b)); } 16 static inline PetscReal MinMod3(PetscReal a,PetscReal b,PetscReal c) {return (a*b<0 || a*c<0) ? 0 : Sgn(a)*PetscMin(PetscAbs(a),PetscMin(PetscAbs(b),PetscAbs(c))); } 17 18 /* ----------------------- Lots of limiters, these could go in a separate library ------------------------- */ 19 void Limit_Upwind(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 20 { 21 PetscInt i; 22 for (i=0; i<info->m; i++) lmt[i] = 0; 23 } 24 void Limit_LaxWendroff(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 25 { 26 PetscInt i; 27 for (i=0; i<info->m; i++) lmt[i] = jR[i]; 28 } 29 void Limit_BeamWarming(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 30 { 31 PetscInt i; 32 for (i=0; i<info->m; i++) lmt[i] = jL[i]; 33 } 34 void Limit_Fromm(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 35 { 36 PetscInt i; 37 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i]); 38 } 39 void Limit_Minmod(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 40 { 41 PetscInt i; 42 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i]); 43 } 44 void Limit_Superbee(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 45 { 46 PetscInt i; 47 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i])); 48 } 49 void Limit_MC(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 50 { 51 PetscInt i; 52 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i]); 53 } 54 void Limit_VanLeer(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 55 { /* phi = (t + abs(t)) / (1 + abs(t)) */ 56 PetscInt i; 57 for (i=0; i<info->m; i++) lmt[i] = (jL[i]*Abs(jR[i])+Abs(jL[i])*jR[i])/(Abs(jL[i])+Abs(jR[i])+1e-15); 58 } 59 void Limit_VanAlbada(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) /* differentiable */ 60 { /* phi = (t + t^2) / (1 + t^2) */ 61 PetscInt i; 62 for (i=0; i<info->m; i++) lmt[i] = (jL[i]*Sqr(jR[i])+Sqr(jL[i])*jR[i])/(Sqr(jL[i])+Sqr(jR[i])+1e-15); 63 } 64 void Limit_VanAlbadaTVD(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 65 { /* phi = (t + t^2) / (1 + t^2) */ 66 PetscInt i; 67 for (i=0; i<info->m; i++) lmt[i] = (jL[i]*jR[i]<0) ? 0 : (jL[i]*Sqr(jR[i])+Sqr(jL[i])*jR[i])/(Sqr(jL[i])+Sqr(jR[i])+1e-15); 68 } 69 void Limit_Koren(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) /* differentiable */ 70 { /* phi = (t + 2*t^2) / (2 - t + 2*t^2) */ 71 PetscInt i; 72 for (i=0; i<info->m; i++) lmt[i] = ((jL[i]*Sqr(jR[i])+2*Sqr(jL[i])*jR[i])/(2*Sqr(jL[i])-jL[i]*jR[i]+2*Sqr(jR[i])+1e-15)); 73 } 74 void Limit_KorenSym(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) /* differentiable */ 75 { /* Symmetric version of above */ 76 PetscInt i; 77 for (i=0; i<info->m; i++) lmt[i] = (1.5*(jL[i]*Sqr(jR[i])+Sqr(jL[i])*jR[i])/(2*Sqr(jL[i])-jL[i]*jR[i]+2*Sqr(jR[i])+1e-15)); 78 } 79 void Limit_Koren3(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 80 { /* Eq 11 of Cada-Torrilhon 2009 */ 81 PetscInt i; 82 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i]); 83 } 84 static PetscReal CadaTorrilhonPhiHatR_Eq13(PetscReal L,PetscReal R) 85 { 86 return PetscMax(0,PetscMin((L+2*R)/3,PetscMax(-0.5*L,PetscMin(2*L,PetscMin((L+2*R)/3,1.6*R))))); 87 } 88 void Limit_CadaTorrilhon2(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 89 { /* Cada-Torrilhon 2009, Eq 13 */ 90 PetscInt i; 91 for (i=0; i<info->m; i++) lmt[i] = CadaTorrilhonPhiHatR_Eq13(jL[i],jR[i]); 92 } 93 void Limit_CadaTorrilhon3R(PetscReal r,LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 94 { /* Cada-Torrilhon 2009, Eq 22 */ 95 /* They recommend 0.001 < r < 1, but larger values are more accurate in smooth regions */ 96 const PetscReal eps = 1e-7,hx = info->hx; 97 PetscInt i; 98 for (i=0; i<info->m; i++) { 99 const PetscReal eta = (Sqr(jL[i])+Sqr(jR[i]))/Sqr(r*hx); 100 lmt[i] = ((eta < 1-eps) ? (jL[i]+2*jR[i])/3 : ((eta>1+eps) ? CadaTorrilhonPhiHatR_Eq13(jL[i],jR[i]) : 0.5*((1-(eta-1)/eps)*(jL[i]+2*jR[i])/3+(1+(eta+1)/eps)*CadaTorrilhonPhiHatR_Eq13(jL[i],jR[i])))); 101 } 102 } 103 void Limit_CadaTorrilhon3R0p1(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 104 { 105 Limit_CadaTorrilhon3R(0.1,info,jL,jR,lmt); 106 } 107 void Limit_CadaTorrilhon3R1(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 108 { 109 Limit_CadaTorrilhon3R(1,info,jL,jR,lmt); 110 } 111 void Limit_CadaTorrilhon3R10(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 112 { 113 Limit_CadaTorrilhon3R(10,info,jL,jR,lmt); 114 } 115 void Limit_CadaTorrilhon3R100(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,PetscScalar *lmt) 116 { 117 Limit_CadaTorrilhon3R(100,info,jL,jR,lmt); 118 } 119 120 /* ----------------------- Limiters for split systems ------------------------- */ 121 122 void Limit2_Upwind(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 123 { 124 PetscInt i; 125 for (i=0; i<info->m; i++) lmt[i] = 0; 126 } 127 void Limit2_LaxWendroff(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 128 { 129 PetscInt i; 130 if (n < sf-1) { /* slow components */ 131 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxs; 132 } else if (n == sf-1) { /* slow component which is next to fast components */ 133 for (i=0; i<info->m; i++) lmt[i] = jR[i]/(info->hxs/2.0+info->hxf/2.0); 134 } else if (n == sf) { /* fast component which is next to slow components */ 135 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxf; 136 } else if (n > sf && n < fs-1) { /* fast components */ 137 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxf; 138 } else if (n == fs-1) { /* fast component next to slow components */ 139 for (i=0; i<info->m; i++) lmt[i] = jR[i]/(info->hxf/2.0+info->hxs/2.0); 140 } else if (n == fs) { /* slow component next to fast components */ 141 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxs; 142 } else { /* slow components */ 143 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxs; 144 } 145 } 146 void Limit2_BeamWarming(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 147 { 148 PetscInt i; 149 if (n < sf-1) { 150 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxs; 151 } else if (n == sf-1) { 152 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxs; 153 } else if (n == sf) { 154 for (i=0; i<info->m; i++) lmt[i] = jL[i]/(info->hxs/2.0+info->hxf/2.0); 155 } else if (n > sf && n < fs-1) { 156 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxf; 157 } else if (n == fs-1) { 158 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxf; 159 } else if (n == fs) { 160 for (i=0; i<info->m; i++) lmt[i] = jL[i]/(info->hxf/2.0+info->hxs/2.0); 161 } else { 162 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxs; 163 } 164 } 165 void Limit2_Fromm(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 166 { 167 PetscInt i; 168 if (n < sf-1) { 169 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxs; 170 } else if (n == sf-1) { 171 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxs+jR[i]/(info->hxs/2.0+info->hxf/2.0)); 172 } else if (n == sf) { 173 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxs/2.0+info->hxf/2.0)+jR[i]/info->hxf); 174 } else if (n > sf && n < fs-1) { 175 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxf; 176 } else if (n == fs-1) { 177 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxf+jR[i]/(info->hxf/2.0+info->hxs/2.0)); 178 } else if (n == fs) { 179 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxf/2.0+info->hxs/2.0)+jR[i]/info->hxs); 180 } else { 181 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxs; 182 } 183 } 184 void Limit2_Minmod(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 185 { 186 PetscInt i; 187 if (n < sf-1) { 188 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i])/info->hxs; 189 } else if (n == sf-1) { 190 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxs,jR[i]/(info->hxs/2.0+info->hxf/2.0)); 191 } else if (n == sf) { 192 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxs/2.0+info->hxf/2.0),jR[i]/info->hxf); 193 } else if (n > sf && n < fs-1) { 194 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i])/info->hxf; 195 } else if (n == fs-1) { 196 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxf,jR[i]/(info->hxf/2.0+info->hxs/2.0)); 197 } else if (n == fs) { 198 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxf/2.0+info->hxs/2.0),jR[i]/info->hxs); 199 } else { 200 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i])/info->hxs; 201 } 202 } 203 void Limit2_Superbee(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 204 { 205 PetscInt i; 206 if (n < sf-1) { 207 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxs; 208 } else if (n == sf-1) { 209 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/info->hxs,2*jR[i]/(info->hxs/2.0+info->hxf/2.0)),MinMod2(2*jL[i]/info->hxs,jR[i]/(info->hxs/2.0+info->hxf/2.0))); 210 } else if (n == sf) { 211 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/(info->hxs/2.0+info->hxf/2.0),2*jR[i]/info->hxf),MinMod2(2*jL[i]/(info->hxs/2.0+info->hxf/2.0),jR[i]/info->hxf)); 212 } else if (n > sf && n < fs-1) { 213 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxf; 214 } else if (n == fs-1) { 215 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/info->hxf,2*jR[i]/(info->hxf/2.0+info->hxs/2.0)),MinMod2(2*jL[i]/info->hxf,jR[i]/(info->hxf/2.0+info->hxs/2.0))); 216 } else if (n == fs) { 217 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/(info->hxf/2.0+info->hxs/2.0),2*jR[i]/info->hxs),MinMod2(2*jL[i]/(info->hxf/2.0+info->hxs/2.0),jR[i]/info->hxs)); 218 } else { 219 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxs; 220 } 221 } 222 void Limit2_MC(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 223 { 224 PetscInt i; 225 if (n < sf-1) { 226 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxs; 227 } else if (n == sf-1) { 228 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxs,0.5*(jL[i]/info->hxs+jR[i]/(info->hxf/2.0+info->hxs/2.0)),2*jR[i]/(info->hxf/2.0+info->hxs/2.0)); 229 } else if (n == sf) { 230 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxs/2.0+info->hxf/2.0),0.5*(jL[i]/(info->hxs/2.0+info->hxf/2.0)+jR[i]/info->hxf),2*jR[i]/info->hxf); 231 } else if (n > sf && n < fs-1) { 232 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxf; 233 } else if (n == fs-1) { 234 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxf,0.5*(jL[i]/info->hxf+jR[i]/(info->hxf/2.0+info->hxs/2.0)),2*jR[i]/(info->hxf/2.0+info->hxs/2.0)); 235 } else if (n == fs) { 236 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxf/2.0+info->hxs/2.0),0.5*(jL[i]/(info->hxf/2.0+info->hxs/2.0)+jR[i]/info->hxs),2*jR[i]/info->hxs); 237 } else { 238 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxs; 239 } 240 } 241 void Limit2_Koren3(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sf,const PetscInt fs,PetscInt n,PetscScalar *lmt) 242 { /* Eq 11 of Cada-Torrilhon 2009 */ 243 PetscInt i; 244 if (n < sf-1) { 245 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxs; 246 } else if (n == sf-1) { 247 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxs,(jL[i]/info->hxs+2*jR[i]/(info->hxf/2.0+info->hxs/2.0))/3,2*jR[i]/(info->hxf/2.0+info->hxs/2.0)); 248 } else if (n == sf) { 249 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxs/2.0+info->hxf/2.0),(jL[i]/(info->hxs/2.0+info->hxf/2.0)+2*jR[i]/info->hxf)/3,2*jR[i]/info->hxf); 250 } else if (n > sf && n < fs-1) { 251 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxf; 252 } else if (n == fs-1) { 253 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxf,(jL[i]/info->hxf+2*jR[i]/(info->hxf/2.0+info->hxs/2.0))/3,2*jR[i]/(info->hxf/2.0+info->hxs/2.0)); 254 } else if (n == fs) { 255 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxf/2.0+info->hxs/2.0),(jL[i]/(info->hxf/2.0+info->hxs/2.0)+2*jR[i]/info->hxs)/3,2*jR[i]/info->hxs); 256 } else { 257 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxs; 258 } 259 } 260 261 /* ---- Three-way splitting ---- */ 262 void Limit3_Upwind(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 263 { 264 PetscInt i; 265 for (i=0; i<info->m; i++) lmt[i] = 0; 266 } 267 void Limit3_LaxWendroff(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 268 { 269 PetscInt i; 270 if (n < sm-1 || n > ms) { /* slow components */ 271 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxs; 272 } else if (n == sm-1 || n == ms-1) { /* slow component which is next to medium components */ 273 for (i=0; i<info->m; i++) lmt[i] = jR[i]/(info->hxs/2.0+info->hxm/2.0); 274 } else if (n < mf-1 || n > fm) { /* medium components */ 275 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxm; 276 } else if (n == mf-1 || n == fm) { /* medium component next to fast components */ 277 for (i=0; i<info->m; i++) lmt[i] = jR[i]/(info->hxm/2.0+info->hxf/2.0); 278 } else { /* fast components */ 279 for (i=0; i<info->m; i++) lmt[i] = jR[i]/info->hxf; 280 } 281 } 282 void Limit3_BeamWarming(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 283 { 284 PetscInt i; 285 if (n < sm || n > ms) { 286 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxs; 287 } else if (n == sm || n == ms) { 288 for (i=0; i<info->m; i++) lmt[i] = jL[i]/(info->hxs/2.0+info->hxf/2.0); 289 }else if (n < mf || n > fm) { 290 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxm; 291 } else if (n == mf || n == fm) { 292 for (i=0; i<info->m; i++) lmt[i] = jL[i]/(info->hxm/2.0+info->hxf/2.0); 293 } else { 294 for (i=0; i<info->m; i++) lmt[i] = jL[i]/info->hxf; 295 } 296 } 297 void Limit3_Fromm(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 298 { 299 PetscInt i; 300 if (n < sm-1 || n > ms) { 301 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxs; 302 } else if (n == sm-1) { 303 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxs+jR[i]/(info->hxs/2.0+info->hxf/2.0)); 304 } else if (n == sm) { 305 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxs/2.0+info->hxm/2.0)+jR[i]/info->hxm); 306 } else if (n == ms-1) { 307 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxm+jR[i]/(info->hxs/2.0+info->hxf/2.0)); 308 } else if (n == ms) { 309 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxm/2.0+info->hxs/2.0)+jR[i]/info->hxs); 310 } else if (n < mf-1 || n > fm) { 311 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxm; 312 } else if (n == mf-1) { 313 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxm+jR[i]/(info->hxm/2.0+info->hxf/2.0)); 314 } else if (n == mf) { 315 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxm/2.0+info->hxf/2.0)+jR[i]/info->hxf); 316 } else if (n == fm-1) { 317 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/info->hxf+jR[i]/(info->hxf/2.0+info->hxm/2.0)); 318 } else if (n == fm) { 319 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]/(info->hxf/2.0+info->hxm/2.0)+jR[i]/info->hxm); 320 } else { 321 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxf; 322 } 323 } 324 void Limit3_Minmod(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 325 { 326 PetscInt i; 327 if (n < sm-1 || n > ms) { 328 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i])/info->hxs; 329 } else if (n == sm-1) { 330 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxs,jR[i]/(info->hxs/2.0+info->hxf/2.0)); 331 } else if (n == sm) { 332 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxs/2.0+info->hxf/2.0),jR[i]/info->hxf); 333 } else if (n == ms-1) { 334 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxm,jR[i]/(info->hxm/2.0+info->hxs/2.0)); 335 } else if (n == ms) { 336 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxm/2.0+info->hxs/2.0),jR[i]/info->hxs); 337 } else if (n < mf-1 || n > fm) { 338 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i],jR[i])/info->hxm; 339 } else if (n == mf-1) { 340 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxm,jR[i]/(info->hxm/2.0+info->hxf/2.0)); 341 } else if (n == mf) { 342 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxm/2.0+info->hxf/2.0),jR[i]/info->hxf); 343 } else if (n == fm-1) { 344 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/info->hxf,jR[i]/(info->hxf/2.0+info->hxm/2.0)); 345 } else if (n == fm) { 346 for (i=0; i<info->m; i++) lmt[i] = MinMod2(jL[i]/(info->hxf/2.0+info->hxm/2.0),jR[i]/info->hxm); 347 } else { 348 for (i=0; i<info->m; i++) lmt[i] = 0.5*(jL[i]+jR[i])/info->hxf; 349 } 350 } 351 void Limit3_Superbee(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 352 { 353 PetscInt i; 354 if (n < sm-1 || n > ms) { 355 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxs; 356 } else if (n == sm-1) { 357 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/info->hxs,2*jR[i]/(info->hxs/2.0+info->hxm/2.0)),MinMod2(2*jL[i]/info->hxs,jR[i]/(info->hxs/2.0+info->hxm/2.0))); 358 } else if (n == sm) { 359 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/(info->hxs/2.0+info->hxm/2.0),2*jR[i]/info->hxm),MinMod2(2*jL[i]/(info->hxs/2.0+info->hxm/2.0),jR[i]/info->hxm)); 360 } else if (n == ms-1) { 361 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/info->hxm,2*jR[i]/(info->hxm/2.0+info->hxs/2.0)),MinMod2(2*jL[i]/info->hxm,jR[i]/(info->hxm/2.0+info->hxs/2.0))); 362 } else if (n == ms) { 363 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/(info->hxm/2.0+info->hxs/2.0),2*jR[i]/info->hxs),MinMod2(2*jL[i]/(info->hxm/2.0+info->hxs/2.0),jR[i]/info->hxs)); 364 } else if (n < mf-1 || n > fm) { 365 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxm; 366 } else if (n == mf-1) { 367 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/info->hxm,2*jR[i]/(info->hxm/2.0+info->hxf/2.0)),MinMod2(2*jL[i]/info->hxm,jR[i]/(info->hxm/2.0+info->hxf/2.0))); 368 } else if (n == mf) { 369 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i]/(info->hxm/2.0+info->hxf/2.0),2*jR[i]/info->hxf),MinMod2(2*jL[i]/(info->hxm/2.0+info->hxf/2.0),jR[i]/info->hxf)); 370 } else if (n == fm-1) { 371 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/info->hxf,2*jR[i]/(info->hxf/2.0+info->hxm/2.0)),MinMod2(2*jL[i]/info->hxf,jR[i]/(info->hxf/2.0+info->hxm/2.0))); 372 } else if (n == fm) { 373 for (i=0; i<info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i]/(info->hxf/2.0+info->hxm/2.0),2*jR[i]/info->hxm),MinMod2(2*jL[i]/(info->hxf/2.0+info->hxm/2.0),jR[i]/info->hxm)); 374 } else { 375 for (i=0; i<info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i],2*jR[i]),MinMod2(2*jL[i],jR[i]))/info->hxf; 376 } 377 } 378 void Limit3_MC(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 379 { 380 PetscInt i; 381 if (n < sm-1 || n > ms) { 382 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxs; 383 } else if (n == sm-1) { 384 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxs,0.5*(jL[i]/info->hxs+jR[i]/(info->hxs/2.0+info->hxm/2.0)),2*jR[i]/(info->hxs/2.0+info->hxm/2.0)); 385 } else if (n == sm) { 386 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxs/2.0+info->hxm/2.0),0.5*(jL[i]/(info->hxs/2.0+info->hxm/2.0)+jR[i]/info->hxm),2*jR[i]/info->hxm); 387 } else if (n == ms-1) { 388 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxm,0.5*(jL[i]/info->hxm+jR[i]/(info->hxm/2.0+info->hxs/2.0)),2*jR[i]/(info->hxm/2.0+info->hxs/2.0)); 389 } else if (n == ms) { 390 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxm/2.0+info->hxs/2.0),0.5*(jL[i]/(info->hxm/2.0+info->hxs/2.0)+jR[i]/info->hxs),2*jR[i]/info->hxs); 391 } else if (n < mf-1 || n > fm) { 392 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxm; 393 } else if (n == mf-1) { 394 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxm,0.5*(jL[i]/info->hxm+jR[i]/(info->hxm/2.0+info->hxf/2.0)),2*jR[i]/(info->hxm/2.0+info->hxf/2.0)); 395 } else if (n == mf) { 396 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxm/2.0+info->hxf/2.0),0.5*(jL[i]/(info->hxm/2.0+info->hxf/2.0)+jR[i]/info->hxf),2*jR[i]/info->hxf); 397 } else if (n == fm-1) { 398 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxf,0.5*(jL[i]/info->hxf+jR[i]/(info->hxf/2.0+info->hxm/2.0)),2*jR[i]/(info->hxf/2.0+info->hxm/2.0)); 399 } else if (n == fm) { 400 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxf/2.0+info->hxm/2.0),0.5*(jL[i]/(info->hxf/2.0+info->hxm/2.0)+jR[i]/info->hxm),2*jR[i]/info->hxm); 401 } else { 402 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],0.5*(jL[i]+jR[i]),2*jR[i])/info->hxf; 403 } 404 } 405 void Limit3_Koren3(LimitInfo info,const PetscScalar *jL,const PetscScalar *jR,const PetscInt sm,const PetscInt mf,const PetscInt fm,const PetscInt ms,PetscInt n,PetscScalar *lmt) 406 { /* Eq 11 of Cada-Torrilhon 2009 */ 407 PetscInt i; 408 if (n < sm-1 || n > ms) { 409 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxs; 410 } else if (n == sm-1) { 411 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxs,(jL[i]/info->hxs+2*jR[i]/(info->hxm/2.0+info->hxs/2.0))/3,2*jR[i]/(info->hxm/2.0+info->hxs/2.0)); 412 } else if (n == sm) { 413 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxs/2.0+info->hxm/2.0),(jL[i]/(info->hxs/2.0+info->hxm/2.0)+2*jR[i]/info->hxm)/3,2*jR[i]/info->hxm); 414 } else if (n == ms-1) { 415 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxm,(jL[i]/info->hxm+2*jR[i]/(info->hxm/2.0+info->hxs/2.0))/3,2*jR[i]/(info->hxm/2.0+info->hxs/2.0)); 416 } else if (n == ms) { 417 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxm/2.0+info->hxs/2.0),(jL[i]/(info->hxm/2.0+info->hxs/2.0)+2*jR[i]/info->hxs)/3,2*jR[i]/info->hxs); 418 } else if (n < mf-1 || n > fm) { 419 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxm; 420 } else if (n == mf-1) { 421 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxm,(jL[i]/info->hxm+2*jR[i]/(info->hxm/2.0+info->hxf/2.0))/3,2*jR[i]/(info->hxm/2.0+info->hxf/2.0)); 422 } else if (n == mf) { 423 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxm/2.0+info->hxf/2.0),(jL[i]/(info->hxm/2.0+info->hxf/2.0)+2*jR[i]/info->hxf)/3,2*jR[i]/info->hxf); 424 } else if (n == fm-1) { 425 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/info->hxf,(jL[i]/info->hxf+2*jR[i]/(info->hxf/2.0+info->hxm/2.0))/3,2*jR[i]/(info->hxf/2.0+info->hxm/2.0)); 426 } else if (n == fm) { 427 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i]/(info->hxf/2.0+info->hxm/2.0),(jL[i]/(info->hxf/2.0+info->hxm/2.0)+2*jR[i]/info->hxm)/3,2*jR[i]/info->hxm); 428 } else { 429 for (i=0; i<info->m; i++) lmt[i] = MinMod3(2*jL[i],(jL[i]+2*jR[i])/3,2*jR[i])/info->hxs; 430 } 431 } 432 433 PetscErrorCode RiemannListAdd(PetscFunctionList *flist,const char *name,RiemannFunction rsolve) 434 { 435 PetscErrorCode ierr; 436 437 PetscFunctionBeginUser; 438 ierr = PetscFunctionListAdd(flist,name,rsolve);CHKERRQ(ierr); 439 PetscFunctionReturn(0); 440 } 441 442 PetscErrorCode RiemannListFind(PetscFunctionList flist,const char *name,RiemannFunction *rsolve) 443 { 444 PetscErrorCode ierr; 445 446 PetscFunctionBeginUser; 447 ierr = PetscFunctionListFind(flist,name,rsolve);CHKERRQ(ierr); 448 PetscAssertFalse(!*rsolve,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Riemann solver \"%s\" could not be found",name); 449 PetscFunctionReturn(0); 450 } 451 452 PetscErrorCode ReconstructListAdd(PetscFunctionList *flist,const char *name,ReconstructFunction r) 453 { 454 PetscErrorCode ierr; 455 456 PetscFunctionBeginUser; 457 ierr = PetscFunctionListAdd(flist,name,r);CHKERRQ(ierr); 458 PetscFunctionReturn(0); 459 } 460 461 PetscErrorCode ReconstructListFind(PetscFunctionList flist,const char *name,ReconstructFunction *r) 462 { 463 PetscErrorCode ierr; 464 465 PetscFunctionBeginUser; 466 ierr = PetscFunctionListFind(flist,name,r);CHKERRQ(ierr); 467 PetscAssertFalse(!*r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Reconstruction \"%s\" could not be found",name); 468 PetscFunctionReturn(0); 469 } 470 471 PetscErrorCode RiemannListAdd_2WaySplit(PetscFunctionList *flist,const char *name,RiemannFunction_2WaySplit rsolve) 472 { 473 PetscErrorCode ierr; 474 475 PetscFunctionBeginUser; 476 ierr = PetscFunctionListAdd(flist,name,rsolve);CHKERRQ(ierr); 477 PetscFunctionReturn(0); 478 } 479 480 PetscErrorCode RiemannListFind_2WaySplit(PetscFunctionList flist,const char *name,RiemannFunction_2WaySplit *rsolve) 481 { 482 PetscErrorCode ierr; 483 484 PetscFunctionBeginUser; 485 ierr = PetscFunctionListFind(flist,name,rsolve);CHKERRQ(ierr); 486 PetscAssertFalse(!*rsolve,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Riemann solver \"%s\" could not be found",name); 487 PetscFunctionReturn(0); 488 } 489 490 PetscErrorCode ReconstructListAdd_2WaySplit(PetscFunctionList *flist,const char *name,ReconstructFunction_2WaySplit r) 491 { 492 PetscErrorCode ierr; 493 494 PetscFunctionBeginUser; 495 ierr = PetscFunctionListAdd(flist,name,r);CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498 499 PetscErrorCode ReconstructListFind_2WaySplit(PetscFunctionList flist,const char *name,ReconstructFunction_2WaySplit *r) 500 { 501 PetscErrorCode ierr; 502 503 PetscFunctionBeginUser; 504 ierr = PetscFunctionListFind(flist,name,r);CHKERRQ(ierr); 505 PetscAssertFalse(!*r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Reconstruction \"%s\" could not be found",name); 506 PetscFunctionReturn(0); 507 } 508 509 /* --------------------------------- Physics ------- */ 510 PetscErrorCode PhysicsDestroy_SimpleFree(void *vctx) 511 { 512 PetscErrorCode ierr; 513 514 PetscFunctionBeginUser; 515 ierr = PetscFree(vctx);CHKERRQ(ierr); 516 PetscFunctionReturn(0); 517 } 518 519 /* --------------------------------- Finite Volume Solver --------------- */ 520 PetscErrorCode FVRHSFunction(TS ts,PetscReal time,Vec X,Vec F,void *vctx) 521 { 522 FVCtx *ctx = (FVCtx*)vctx; 523 PetscErrorCode ierr; 524 PetscInt i,j,k,Mx,dof,xs,xm; 525 PetscReal hx,cfl_idt = 0; 526 PetscScalar *x,*f,*slope; 527 Vec Xloc; 528 DM da; 529 530 PetscFunctionBeginUser; 531 ierr = TSGetDM(ts,&da);CHKERRQ(ierr); 532 ierr = DMGetLocalVector(da,&Xloc);CHKERRQ(ierr); /* Xloc contains ghost points */ 533 ierr = DMDAGetInfo(da,0, &Mx,0,0, 0,0,0, &dof,0,0,0,0,0);CHKERRQ(ierr); /* Mx is the number of center points */ 534 hx = (ctx->xmax-ctx->xmin)/Mx; 535 ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); /* X is solution vector which does not contain ghost points */ 536 ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 537 ierr = VecZeroEntries(F);CHKERRQ(ierr); /* F is the right hand side function corresponds to center points */ 538 ierr = DMDAVecGetArray(da,Xloc,&x);CHKERRQ(ierr); 539 ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr); 540 ierr = DMDAGetArray(da,PETSC_TRUE,&slope);CHKERRQ(ierr); /* contains ghost points */ 541 ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); 542 543 if (ctx->bctype == FVBC_OUTFLOW) { 544 for (i=xs-2; i<0; i++) { 545 for (j=0; j<dof; j++) x[i*dof+j] = x[j]; 546 } 547 for (i=Mx; i<xs+xm+2; i++) { 548 for (j=0; j<dof; j++) x[i*dof+j] = x[(xs+xm-1)*dof+j]; 549 } 550 } 551 552 for (i=xs-1; i<xs+xm+1; i++) { 553 struct _LimitInfo info; 554 PetscScalar *cjmpL,*cjmpR; 555 /* Determine the right eigenvectors R, where A = R \Lambda R^{-1} */ 556 ierr = (*ctx->physics.characteristic)(ctx->physics.user,dof,&x[i*dof],ctx->R,ctx->Rinv,ctx->speeds,ctx->xmin+hx*i);CHKERRQ(ierr); 557 /* Evaluate jumps across interfaces (i-1, i) and (i, i+1), put in characteristic basis */ 558 ierr = PetscArrayzero(ctx->cjmpLR,2*dof);CHKERRQ(ierr); 559 cjmpL = &ctx->cjmpLR[0]; 560 cjmpR = &ctx->cjmpLR[dof]; 561 for (j=0; j<dof; j++) { 562 PetscScalar jmpL,jmpR; 563 jmpL = x[(i+0)*dof+j]-x[(i-1)*dof+j]; 564 jmpR = x[(i+1)*dof+j]-x[(i+0)*dof+j]; 565 for (k=0; k<dof; k++) { 566 cjmpL[k] += ctx->Rinv[k+j*dof]*jmpL; 567 cjmpR[k] += ctx->Rinv[k+j*dof]*jmpR; 568 } 569 } 570 /* Apply limiter to the left and right characteristic jumps */ 571 info.m = dof; 572 info.hx = hx; 573 (*ctx->limit)(&info,cjmpL,cjmpR,ctx->cslope); 574 for (j=0; j<dof; j++) ctx->cslope[j] /= hx; /* rescale to a slope */ 575 for (j=0; j<dof; j++) { 576 PetscScalar tmp = 0; 577 for (k=0; k<dof; k++) tmp += ctx->R[j+k*dof]*ctx->cslope[k]; 578 slope[i*dof+j] = tmp; 579 } 580 } 581 582 for (i=xs; i<xs+xm+1; i++) { 583 PetscReal maxspeed; 584 PetscScalar *uL,*uR; 585 uL = &ctx->uLR[0]; 586 uR = &ctx->uLR[dof]; 587 for (j=0; j<dof; j++) { 588 uL[j] = x[(i-1)*dof+j]+slope[(i-1)*dof+j]*hx/2; 589 uR[j] = x[(i-0)*dof+j]-slope[(i-0)*dof+j]*hx/2; 590 } 591 ierr = (*ctx->physics.riemann)(ctx->physics.user,dof,uL,uR,ctx->flux,&maxspeed,ctx->xmin+hx*i,ctx->xmin,ctx->xmax);CHKERRQ(ierr); 592 cfl_idt = PetscMax(cfl_idt,PetscAbsScalar(maxspeed/hx)); /* Max allowable value of 1/Delta t */ 593 if (i > xs) { 594 for (j=0; j<dof; j++) f[(i-1)*dof+j] -= ctx->flux[j]/hx; 595 } 596 if (i < xs+xm) { 597 for (j=0; j<dof; j++) f[i*dof+j] += ctx->flux[j]/hx; 598 } 599 } 600 ierr = DMDAVecRestoreArray(da,Xloc,&x);CHKERRQ(ierr); 601 ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr); 602 ierr = DMDARestoreArray(da,PETSC_TRUE,&slope);CHKERRQ(ierr); 603 ierr = DMRestoreLocalVector(da,&Xloc);CHKERRQ(ierr); 604 ierr = MPI_Allreduce(&cfl_idt,&ctx->cfl_idt,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)da));CHKERRMPI(ierr); 605 if (0) { 606 /* We need to a way to inform the TS of a CFL constraint, this is a debugging fragment */ 607 PetscReal dt,tnow; 608 ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 609 ierr = TSGetTime(ts,&tnow);CHKERRQ(ierr); 610 if (dt > 0.5/ctx->cfl_idt) { 611 if (1) { 612 ierr = PetscPrintf(ctx->comm,"Stability constraint exceeded at t=%g, dt %g > %g\n",(double)tnow,(double)dt,(double)(0.5/ctx->cfl_idt));CHKERRQ(ierr); 613 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Stability constraint exceeded, %g > %g",(double)dt,(double)(ctx->cfl/ctx->cfl_idt)); 614 } 615 } 616 PetscFunctionReturn(0); 617 } 618 619 PetscErrorCode FVSample(FVCtx *ctx,DM da,PetscReal time,Vec U) 620 { 621 PetscErrorCode ierr; 622 PetscScalar *u,*uj; 623 PetscInt i,j,k,dof,xs,xm,Mx; 624 625 PetscFunctionBeginUser; 626 PetscAssertFalse(!ctx->physics.sample,PETSC_COMM_SELF,PETSC_ERR_SUP,"Physics has not provided a sampling function"); 627 ierr = DMDAGetInfo(da,0, &Mx,0,0, 0,0,0, &dof,0,0,0,0,0);CHKERRQ(ierr); 628 ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); 629 ierr = DMDAVecGetArray(da,U,&u);CHKERRQ(ierr); 630 ierr = PetscMalloc1(dof,&uj);CHKERRQ(ierr); 631 for (i=xs; i<xs+xm; i++) { 632 const PetscReal h = (ctx->xmax-ctx->xmin)/Mx,xi = ctx->xmin+h/2+i*h; 633 const PetscInt N = 200; 634 /* Integrate over cell i using trapezoid rule with N points. */ 635 for (k=0; k<dof; k++) u[i*dof+k] = 0; 636 for (j=0; j<N+1; j++) { 637 PetscScalar xj = xi+h*(j-N/2)/(PetscReal)N; 638 ierr = (*ctx->physics.sample)(ctx->physics.user,ctx->initial,ctx->bctype,ctx->xmin,ctx->xmax,time,xj,uj);CHKERRQ(ierr); 639 for (k=0; k<dof; k++) u[i*dof+k] += ((j==0 || j==N) ? 0.5 : 1.0)*uj[k]/N; 640 } 641 } 642 ierr = DMDAVecRestoreArray(da,U,&u);CHKERRQ(ierr); 643 ierr = PetscFree(uj);CHKERRQ(ierr); 644 PetscFunctionReturn(0); 645 } 646 647 PetscErrorCode SolutionStatsView(DM da,Vec X,PetscViewer viewer) 648 { 649 PetscErrorCode ierr; 650 PetscReal xmin,xmax; 651 PetscScalar sum,tvsum,tvgsum; 652 const PetscScalar *x; 653 PetscInt imin,imax,Mx,i,j,xs,xm,dof; 654 Vec Xloc; 655 PetscBool iascii; 656 657 PetscFunctionBeginUser; 658 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 659 if (iascii) { 660 /* PETSc lacks a function to compute total variation norm (difficult in multiple dimensions), we do it here */ 661 ierr = DMGetLocalVector(da,&Xloc);CHKERRQ(ierr); 662 ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 663 ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,Xloc);CHKERRQ(ierr); 664 ierr = DMDAVecGetArrayRead(da,Xloc,(void*)&x);CHKERRQ(ierr); 665 ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); 666 ierr = DMDAGetInfo(da,0, &Mx,0,0, 0,0,0, &dof,0,0,0,0,0);CHKERRQ(ierr); 667 tvsum = 0; 668 for (i=xs; i<xs+xm; i++) { 669 for (j=0; j<dof; j++) tvsum += PetscAbsScalar(x[i*dof+j]-x[(i-1)*dof+j]); 670 } 671 ierr = MPI_Allreduce(&tvsum,&tvgsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)da));CHKERRMPI(ierr); 672 ierr = DMDAVecRestoreArrayRead(da,Xloc,(void*)&x);CHKERRQ(ierr); 673 ierr = DMRestoreLocalVector(da,&Xloc);CHKERRQ(ierr); 674 ierr = VecMin(X,&imin,&xmin);CHKERRQ(ierr); 675 ierr = VecMax(X,&imax,&xmax);CHKERRQ(ierr); 676 ierr = VecSum(X,&sum);CHKERRQ(ierr); 677 ierr = PetscViewerASCIIPrintf(viewer,"Solution range [%8.5f,%8.5f] with minimum at %D, mean %8.5f, ||x||_TV %8.5f\n",(double)xmin,(double)xmax,imin,(double)(sum/Mx),(double)(tvgsum/Mx));CHKERRQ(ierr); 678 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type not supported"); 679 PetscFunctionReturn(0); 680 } 681