BISICLES AMR ice sheet model  0.9
FASIceSolverI.H
Go to the documentation of this file.
1 #ifdef CH_LANG_CC
2 /*
3 * _______ __
4 * / ___/ / ___ __ _ / / ___
5 * / /__/ _ \/ _ \/ V \/ _ \/ _ \
6 * \___/_//_/\___/_/_/_/_.__/\___/
7 * Please refer to Copyright.txt, in Chombo's root directory.
8 */
9 #endif
10 
11 #include "FASIceSolver.H"
12 #include "ParmParse.H"
13 //#include "QuadCFInterp.H"
14 #include "CornerCopier.H"
15 #include "CoarseAverage.H"
16 #include "CoarseAverageFace.H"
17 #include "ExtrapBCF_F.H"
18 #include "IceConstants.H"
19 //#include "AMRIO.H"
20 #include "NamespaceHeader.H"
21 
22 static bool s_always_recompute_mu = false; // this does help convergance but it is much slower
23 
25 
29  const DisjointBoxLayout &a_grid,
30  const ConstitutiveRelation* a_constRelPtr,
31  const BasalFrictionRelation* a_basalFrictionRelPtr,
32  IceThicknessIBC* a_bc
33  ) :
34  AMRFAS_LDFOp( a_o, a_grid ),
35  m_constThetaVal(238.15), // use isothermal ice temp from Pattyn(2003)
36  m_vtopSafety(VTOP_DEFAULT_SAFETY),
37  m_constRelPtr(a_constRelPtr),
38  m_basalFrictionRelPtr(a_basalFrictionRelPtr),
39  m_VTO(0),
40  m_bc(a_bc)
41 {
42  // beta only has one component...
43  m_Beta = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>(a_grid,
44  1,
45  IntVect::Zero));
46  m_Beta0 = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>(a_grid,
47  1,
48  IntVect::Zero));
49 }
50 
51 // ---------------------------------------------------------
52 // CFInterp - default C-F interp
53 // ---------------------------------------------------------
54 void
55 FASIceViscouseTensorOp::CFInterp( LevelData<FArrayBox>& a_phi,
56  const LevelData<FArrayBox>& a_phiCoarse )
57 {
58  m_VTO->cfinterp( a_phi, a_phiCoarse );
59 }
60 
61 // ---------------------------------------------------------
62 // applyLevel - apply operator on one level - do BC's but no exchange or C-F
63 // ---------------------------------------------------------
64 void
65 FASIceViscouseTensorOp::applyLevel( LevelData<FArrayBox>& a_lhs,
66  const LevelData<FArrayBox>& a_phi )
67 {
68  CH_TIME("FASIceViscouseTensorOp::applyLevel");
69 
70  // this is only called from base class apply()
72  {
73  LevelData<FArrayBox>& phi = (LevelData<FArrayBox>&)a_phi; // need to force
74 
75  computeMu( phi, 0, 0 ); // lets do this a lot for now
76  // trick to get VTO to recompute D^-1 (m_relaxCoef)
77  m_VTO->setAlphaAndBeta( m_VTO->getAlpha(), m_VTO->getBeta() );
78  // this is used for G-S and Rich
79  scale( m_VTO->m_relaxCoef, m_smoothing_damping_factor );
80  }
81 
82  // this applies BCs
83  m_VTO->applyOp( a_lhs, a_phi, true ); // homogenous ?
84 }
85 
86 // ---------------------------------------------------------
87 // levelGSRB
88 // ---------------------------------------------------------
89 void
90 FASIceViscouseTensorOp::levelGSRB( RefCountedPtr<LevelData<FArrayBox> > a_phi,
91  const RefCountedPtr<LevelData<FArrayBox> > a_rhs
92  )
93 {
94  CH_TIME("FASIceViscouseTensorOp::levelGSRB");
95 
97  {
98  LevelData<FArrayBox>& phi = *a_phi;
99 
100  computeMu( phi, 0, 0 ); // lets do this a lot for now
101  // trick to get VTO to recompute D^-1 (m_relaxCoef)
102  m_VTO->setAlphaAndBeta( m_VTO->getAlpha(), m_VTO->getBeta() );
103  scale( m_VTO->m_relaxCoef, m_smoothing_damping_factor );
104  }
105 
106  m_VTO->relax( *a_phi, *a_rhs, 1 );
107 }
108 
109 // ---------------------------------------------------------
110 // levelRich
111 // ---------------------------------------------------------
112 void
113 FASIceViscouseTensorOp::levelRich( RefCountedPtr<LevelData<FArrayBox> > a_phi,
114  const RefCountedPtr<LevelData<FArrayBox> > a_rhs
115  )
116 {
117  CH_TIME("FASIceViscouseTensorOp::levelRich");
118 
119  CH_assert(a_phi->isDefined());
120  CH_assert(a_rhs->isDefined());
121  CH_assert(a_phi->ghostVect() >= IntVect::Unit);
122  CH_assert(a_phi->nComp() == a_rhs->nComp());
123 
124  {
125  Real omega = 1.0; // this is folded into m_VTO->m_relaxCoef
126  LevelData<FArrayBox> tmp;
127  create( tmp, *a_rhs );
128 
129  // apply has BCs, exchange and C-F interp done before (eg, in compute state)
130  apply( tmp, *a_phi, 0, false ); // applies BCs, calls applyLevel, exchange done above
131 
132  // x = x + omega D^-1 (b - Ax) ; D == alaph - 2*beta*Dim/h^2
133  axby( tmp, tmp, *a_rhs, -1.0, 1.0 ); // (b - Ax)
134 
135  mult( tmp, m_VTO->m_relaxCoef ); // D^-1(b - Ax)
136 
137  axby( *a_phi, *a_phi, tmp, 1.0, omega ); // X = X + omega D^-1 (b - Ax)
138  }
139 }
140 
141 // ---------------------------------------------------------
142 void
143 FASIceViscouseTensorOp::restrictState( RefCountedPtr<AMRFASOp<LevelData<FArrayBox> > > a_fOp, // fine op
144  Copier &a_copier ) // copier from buffer to real distribution
145 {
146  CH_TIME("FASIceViscouseTensorOp::restrictState");
147  const FASIceViscouseTensorOp * const fop = dynamic_cast<FASIceViscouseTensorOp*>( &(*a_fOp) );
148  CH_assert(fop);
149  int nRef = fop->refToCoarser();
150 
151  // average material parameters to coarser (this)
152  m_time = fop->m_time; // this just gets passed up
153  m_coordSys = RefCountedPtr<LevelSigmaCS>(new LevelSigmaCS( m_grid,
154  m_dx,
155  *fop->m_coordSys,
156  nRef
157  ));
158  const LevelData<FluxBox> &f_faceA = *fop->m_faceA;
159  const DisjointBoxLayout& fdbl = fop->m_grid;
160  CH_assert( fdbl.coarsenable(nRef) );
161  const int aNC = fop->m_faceA->nComp();
162  if( !m_faceA )
163  {
164  m_faceA = RefCountedPtr<LevelData<FluxBox> >(new LevelData<FluxBox>( m_grid,
165  aNC,
166  IntVect::Unit) );
167  // zero out because averageToCoarse does not fill everything?
168  DataIterator dit = m_faceA->dataIterator();
169  for (dit.begin(); dit.ok(); ++dit)
170  {
171  (*m_faceA)[dit].setVal(0.);
172  }
173  }
174 
175  // restrict stuff that was copied in solver: m_faceA, m_Beta, m_Beta0
176  CoarseAverageFace face_crs( fdbl, aNC, nRef );
177  face_crs.averageToCoarse( *m_faceA, f_faceA );
178 
179  // restrict m_Beta, m_Beta0
180  {
181  const LevelData<FArrayBox> &f_beta = *fop->m_Beta, &f_beta0 = *fop->m_Beta0;
182  LevelData<FArrayBox> crs_beta, &c_beta = *m_Beta, &c_beta0 = *m_Beta0;
183 
184  DisjointBoxLayout dblCoarsenedFine;
185  coarsen( dblCoarsenedFine, f_beta.disjointBoxLayout(), nRef );
186  crs_beta.define( dblCoarsenedFine, f_beta.nComp(), f_beta.ghostVect() );
187  fop->AMRRestrict( c_beta, f_beta, crs_beta, a_copier );
188  fop->AMRRestrict( c_beta0, f_beta0, crs_beta, a_copier );
189  }
190 
191 }
192 
193 // ---------------------------------------------------------
194 bool
195 FASIceViscouseTensorOp::computeState( RefCountedPtr<LevelData<FArrayBox> > a_phi,
196  const RefCountedPtr<LevelData<FArrayBox> > a_CrsPhi,
197  const RefCountedPtr<LevelData<FArrayBox> > a_FinePhi
198  )
199 {
200  CH_TIME("FASIceViscouseTensorOp::recomputeState");
201  if( !s_always_recompute_mu )
202  {
203  computeMu( *a_phi, a_CrsPhi, a_FinePhi );
204  // trick to get VTO to recompute D^-1 (m_relaxCoef)
205  m_VTO->setAlphaAndBeta( m_VTO->getAlpha(), m_VTO->getBeta() );
206  // this is used for G-S and Rich
207  scale( m_VTO->m_relaxCoef, m_smoothing_damping_factor );
208  return true;
209  }
210  else return false;
211 }
212 
213 
214 // ---------------------------------------------------------
215 void
216 FASIceViscouseTensorOp::reflux( const LevelData<FArrayBox>& a_phiFine,
217  const LevelData<FArrayBox>& a_phi,
218  LevelData<FArrayBox>& a_residual,
219  AMRFASOp<LevelData<FArrayBox> >* a_finerOp )
220 {
221  CH_TIME("FASIceViscouseTensorOp::reflux");
222  const FASIceViscouseTensorOp * const fop = dynamic_cast<FASIceViscouseTensorOp*>( a_finerOp );
223  CH_assert(fop);
224 
225  // this constructs a LevelFluxRegister each time - yikes
226  m_VTO->reflux( a_phiFine,
227  a_phi,
228  a_residual,
229  fop->m_VTO );
230 }
231 
232 
234 
239  BasalFrictionRelation*a_basalFrictionRelPtr,
240  IceThicknessIBC* a_bc
241  ) :
242  AMRFAS_LDFOpFactory( 1, 2 ),
243  m_constRelPtr(a_constRelPtr),
244  m_basalFrictionRelPtr(a_basalFrictionRelPtr),
245  m_VTOFactory(0), // do not like weak constructors so need to wait on this (need a factory factory)
246  m_bc(a_bc) // , m_sizeA(a_sizeA)
247 {
248  AMRFASOpFactory<LevelData<FArrayBox> >::define( a_bc->velocitySolveBC() ); // base class define
249 }
250 
251 // ---------------------------------------------------------
252 // AMR Factory define
253 // - override base define
254 //
255 RefCountedPtr<AMRFASOp<LevelData<FArrayBox> > >
256 FASIceViscouseTensorOpFactory::AMRNewOp( int a_ilev, const DisjointBoxLayout& a_grid, bool a_isSR_dummy )
257 {
258  RefCountedPtr<FASIceViscouseTensorOp> newOp =
259  RefCountedPtr<FASIceViscouseTensorOp>( new FASIceViscouseTensorOp( 2,
260  a_grid,
263  m_bc
264  ) );
265 
266  // this defines the newOp's base class stuff
267  AMRFAS_LDFOpFactory::AMRNewOp( a_ilev, newOp, false );
268 
269  // define the VTO part
270  CH_assert(newOp->m_VTO == NULL);
271  CH_assert(m_VTOFactory != NULL);
272  newOp->m_VTO = m_VTOFactory->AMRnewOp( m_domains[a_ilev] ); // base factory will search for index
273 
274  return newOp;
275 }
276 
278 
281 //
282 // main define method - start of define. pure virtual from Ice base class so need this.
283 //
284 void
285 FASIceSolver::define( const ProblemDomain& a_coarseDomain,
286  ConstitutiveRelation* a_constRelPtr,
287  BasalFrictionRelation* a_basalFrictionRelPtr,
288  const Vector<DisjointBoxLayout>& a_vectGrids,
289  const Vector<int>& a_vectRefRatio,
290  const RealVect& a_dxCrse,
291  IceThicknessIBC* a_bc,
292  int a_numLevels
293  )
294 {
295  CH_TIME("FASIceSolver::define");
296 
297  // define factory -- this can be called oftan and refCounted pointers take care of it
298  // CH_assert(m_opFactoryPtr == NULL);
299 
300  // I don't have all the levels yet, so defer complete define
301  m_opFactoryPtr = RefCountedPtr<FASIceViscouseTensorOpFactory>
302  (new FASIceViscouseTensorOpFactory( a_constRelPtr, a_basalFrictionRelPtr, a_bc ) );
303 
304  // define base solver class, makes coarse levels as needed, calls FASIceViscouseTensorOpFactory::define
305  AMRFAS<LevelData<FArrayBox> >::define( a_coarseDomain,
306  a_dxCrse,
307  a_vectGrids,
308  a_vectRefRatio,
309  *m_opFactoryPtr,
310  0,
311  a_numLevels
312  );
313 }
314 
315 // ---------------------------------------------------------
316 // AMR Factory define
317 // - override base define
318 //
319 void FASIceViscouseTensorOpFactory::define( const ProblemDomain& a_coarseDomain,
320  const RealVect& a_crsDx,
321  const Vector<DisjointBoxLayout>& a_grids,
322  const Vector<int>& a_refRatios,
323  int a_nSRGrids
324  )
325 {
326  CH_TIME("FASIceViscouseTensorOpFactory::define");
327 
328  // call base implimentation
329  AMRFASOpFactory<LevelData<FArrayBox> >::define( a_coarseDomain,
330  a_crsDx,
331  a_grids,
332  a_refRatios,
333  a_nSRGrids
334  );
335 
336  // set alpha & beta here
337  const Real alpha = -1.0; // sort of wrong signs, but that's what B does
338  const Real beta = 1.0;
339 
340  int num_levels = a_grids.size();
341  Vector<RefCountedPtr<LevelData<FluxBox> > > eta(num_levels);
342  Vector<RefCountedPtr<LevelData<FluxBox> > > lambda(num_levels);
343  Vector<RefCountedPtr<LevelData<FArrayBox> > > c(num_levels);
344 
345  for (int i = 0; i < num_levels; i++)
346  {
347  eta[i] = RefCountedPtr<LevelData<FluxBox> >(new LevelData<FluxBox>( a_grids[i],
348  1,
349  IntVect::Zero));
350 
351  lambda[i] = RefCountedPtr<LevelData<FluxBox> >(new LevelData<FluxBox>( a_grids[i],
352  1,
353  IntVect::Zero));
354 
355  c[i] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>( a_grids[i],
356  1,
357  IntVect::Zero));
358 
359  // this is used to get relaxation values too early so needs to be set to avoid assert failures!
360  DataIterator dit = c[i]->dataIterator();
361  for (dit.begin(); dit.ok(); ++dit)
362  {
363  (*c[i])[dit].setVal(1.0);
364  (*lambda[i])[dit].setVal(1.0);
365  (*eta[i])[dit].setVal(1.0);
366  }
367  }
368  // complete define for VTO factory
369  CH_assert(m_VTOFactory == NULL);
370  BCFunction bc = m_bc->velocitySolveBC();
371 
372  m_VTOFactory = new ViscousTensorOpFactory( a_grids,
373  eta,
374  lambda,
375  c,
376  alpha,
377  beta,
378  a_refRatios,
379  a_coarseDomain,
380  a_crsDx[0],
381  bc
382  );
383 }
384 
386 
388 int
389 FASIceSolver::solve( Vector<LevelData<FArrayBox>* >& a_horizontalVel,
390  Vector<LevelData<FArrayBox>* >& a_calvedIce,
391  Vector<LevelData<FArrayBox>* >& a_addedIce,
392  Vector<LevelData<FArrayBox>* >& a_removedIce,
393  Real& a_initialResidualNorm,
394  Real& a_finalResidualNorm,
395  const Real a_convergenceMetric,
396  const Vector<LevelData<FArrayBox>* >& a_rhs,
397  const Vector<LevelData<FArrayBox>* >& a_beta, // Basal C (a_beta)
398  const Vector<LevelData<FArrayBox>* >& a_beta0, // not used
399  const Vector<LevelData<FArrayBox>* >& a_A,
400  const Vector<LevelData<FluxBox>* >& a_muCoef, // not used, this is computed
401  Vector<RefCountedPtr<LevelSigmaCS > >& a_coordSys,
402  Real a_time,
403  int a_lbase,
404  int a_maxLevel
405  )
406 {
407  CH_TIME("FASIceSolver::solve");
408 
409  // copy data into ops, acting like a factory ...
410  FASIceViscouseTensorOp *crs_op = 0, *op;
411  for (int lev = 0; lev < a_maxLevel + 1; ++lev, crs_op = op )
412  {
413  op = dynamic_cast<FASIceViscouseTensorOp*>( &(*getOp(lev)) );
414  CH_assert(op);
415 
416  if( !op->m_faceA )
417  {
418  op->m_faceA = RefCountedPtr<LevelData<FluxBox> >(new LevelData<FluxBox>( op->m_grid,
419  a_A[lev]->nComp(),
420  IntVect::Zero) );
421  }
422  //
423  LevelData<FArrayBox>& argA = *a_A[lev];
424  CellToEdge( argA, *op->m_faceA );
425 
426  // copy beta into local storage computed for coarse grids in callback in solver
427  LevelData<FArrayBox>& localBeta = *op->m_Beta;
428  LevelData<FArrayBox>& argBeta = *a_beta[lev];
429  LevelData<FArrayBox>& localBeta0 = *op->m_Beta0;
430  LevelData<FArrayBox>& argBeta0 = *a_beta0[lev];
431  CH_assert(localBeta.nComp() == argBeta.nComp());
432 
433  DataIterator dit = localBeta.dataIterator();
434  for (dit.begin(); dit.ok(); ++dit)
435  {
436  localBeta[dit].copy(argBeta[dit]);
437  localBeta0[dit].copy(argBeta0[dit]);
438  }
439 
440  // cache args
441  op->m_time = a_time;
442  op->m_coordSys = a_coordSys[lev];
443  }
444  // solver will copy internal levels
445 
446  // solver wants RefCountedPtr, allocate and copy in, and strips out extra levels
447  Vector<RefCountedPtr<LevelData<FArrayBox> > > phi(a_maxLevel + 1);
448  Vector<RefCountedPtr<LevelData<FArrayBox> > > rhs(a_maxLevel + 1);
449  for (int lev = 0; lev < a_maxLevel + 1; ++lev)
450  {
451  phi[lev] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>);
452  rhs[lev] = RefCountedPtr<LevelData<FArrayBox> >(new LevelData<FArrayBox>);
453 
454  op = dynamic_cast<FASIceViscouseTensorOp*>( &(*getOp(lev)) );
455  CH_assert(op);
456 
457  phi[lev]->define( op->m_grid, a_horizontalVel[0]->nComp(), a_horizontalVel[0]->ghostVect() );
458  op->assignLocal( *phi[lev], *a_horizontalVel[lev] );
459  rhs[lev]->define( op->m_grid, a_rhs[0]->nComp(), IntVect::Zero );
460  op->assignLocal( *rhs[lev], *a_rhs[lev] );
461  }
462 
463  // solve -- should we zero out vel?
464  int returnCode;
465  a_finalResidualNorm = AMRFAS<LevelData<FArrayBox> >::solve( phi, rhs, &returnCode );
466 
467  a_initialResidualNorm = 1.0; // don't have
468 
469  // copy out
470  for (int lev = 0; lev < a_maxLevel + 1; ++lev)
471  {
472  op = dynamic_cast<FASIceViscouseTensorOp*>( &(*getOp(lev)) );
473  CH_assert(op);
474  op->assignLocal( *a_horizontalVel[lev], *phi[lev] );
475  }
476 
477  if( !m_avoid_norms && m_plot_residual )
478  {
479 #ifdef CH_USE_HDF5
480  string fname = "residualFAS.";
481  char suffix[30];
482  sprintf(suffix, "%dd.hdf5",SpaceDim);
483  fname += suffix;
484 
485  Vector<string> varNames(SpaceDim);
486  varNames[0] = "residual-x";
487  varNames[1] = "residual-y";
488 
489  Real bogusVal = 1.0;
490  // writes all grids
491  if( 0 )
492  {
493  op = dynamic_cast<FASIceViscouseTensorOp*>( &(*getOp(a_maxLevel)) );
494  Real n1 = op->norm( *phi[a_maxLevel], 0, 0);
495  Real n2 = op->norm( *phi[a_maxLevel], 0, 1);
496  pout() << "FASIceSolver::solve plot residual " << m_residual.size() << " levels, |phi_x|= " << setprecision(15) << n1 << " |phi_y|= " << n2 << endl;
497  }
498 
499  Vector<LevelData<FArrayBox>*> res( m_residual.size() );
500  for (int lev = 0; lev < m_residual.size() ; ++lev)
501  {
502  res[lev] = &(*m_temp[lev]); // residual happens to be in m_temp
503  }
504 
505  WriteAMRHierarchyHDF5(fname,
506  m_opFactoryPtr->m_grids,
507  res,
508  varNames,
509  m_op[0]->m_domain.domainBox(),
510  m_op[0]->dx(),
511  bogusVal,
512  bogusVal,
513  m_opFactoryPtr->m_refRatios,
514  m_residual.size());
515 #endif // end if HDF5
516  }
517 
518  return returnCode;
519 }
520 
521 // isothermal version -- for the ViscousTensorOp, lambda = 2*mu
522 //
523 // side effect: does exchange on a_horizontalVel (otherwise it should be const)
524 //
525 void
526 FASIceViscouseTensorOp::computeMu( LevelData<FArrayBox>& a_horizontalVel,
527  const LevelData<FArrayBox>* a_crsVel,
528  const LevelData<FArrayBox>* a_fineVel
529  )
530 {
531  const DisjointBoxLayout& levelGrids = m_grid;
532  const LevelSigmaCS& levelCS = *m_coordSys;
533  LevelData<FArrayBox>& levelVel = a_horizontalVel;
534  LevelData<FluxBox>& levelMu = *m_VTO->getEta();
535  LevelData<FluxBox>& levelLambda = *m_VTO->getLambda();
536  const LevelData<FluxBox>&levelA = *m_faceA;
537  const LevelData<FArrayBox>& levelBeta = *m_Beta;
538  const LevelData<FArrayBox>& levelBeta0 = *m_Beta0;
539  LevelData<FArrayBox>& levelC = *m_VTO->getACoef(); // not intuitive: VTO acoef == solver C
540 
541  if (a_fineVel)
542  {
543  CoarseAverage averager(a_fineVel->getBoxes(),
544  levelGrids,
545  a_fineVel->nComp(),
546  refToFiner());
547 
548  averager.averageToCoarse(levelVel, *a_fineVel);
549  }
550 
551  levelVel.exchange( m_exchangeCopier );
552 
553  // first set BC's on vel
554  m_bc->velocityGhostBC( levelVel,
555  levelCS,
556  m_domain,
557  m_time);
558 
559  //slc : qcfi.coarseFineInterp fills the edges of lev > 0 cells
560  //but not the corners. We need them filled to compute the
561  //rate-of-strain invariant, so here is a bodge for now
562  DataIterator dit = levelGrids.dataIterator();
563  // if (SpaceDim == 2)
564  // {
565  // for (dit.begin(); dit.ok(); ++dit)
566  // {
567  // Box sbox = levelVel[dit].box();
568  // sbox.grow(-1);
569  // FORT_EXTRAPCORNER2D(CHF_FRA(levelVel[dit]),
570  // CHF_BOX(sbox));
571  // }
572  // }
573 
574  // actually need to use a cornerCopier, too ... really ??
575  // CornerCopier cornerCopier(levelGrids, levelGrids,
576  // m_domain,levelVel.ghostVect(),
577  // true);
578  // levelVel.exchange(cornerCopier);
579 
580  m_constRelPtr->computeFaceMu( levelMu,
581  levelVel,
582  a_crsVel,
583  refToCoarser(),
584  levelA,
585  levelCS,
586  m_domain,
587  IntVect::Zero);
588 
589  // now multiply by ice thickness H
590  const LevelData<FluxBox>& faceH = levelCS.getFaceH();
591  // Real muMax = 1.23456789e+300;
592  // Real muMin = 0.0;
593  for (dit.begin(); dit.ok(); ++dit)
594  {
595 
596  for (int dir=0; dir<SpaceDim; dir++)
597  {
598  FArrayBox& thisMu = levelMu[dit][dir];
599  const Box& box = thisMu.box();
600 
601  // FORT_MAXFAB1(CHF_FRA(thisMu),
602  // CHF_CONST_REAL(muMin),
603  // CHF_BOX(box));
604 
605  thisMu.mult(faceH[dit][dir],box,0,0,1);
606  CH_assert(thisMu.min() >= 0.0);
607 
608  // FORT_MINFAB1(CHF_FRA(thisMu),
609  // CHF_CONST_REAL(muMax),
610  // CHF_BOX(box));
611  }
612 
613  // also update alpha (or C)
614  const Box& gridBox = levelGrids[dit];
616  (levelC[dit], levelVel[dit], levelCS.getThicknessOverFlotation()[dit], levelBeta[dit] ,
617  levelCS.getFloatingMask()[dit],gridBox);
618 
619  levelC[dit] += levelBeta0[dit];
620 
621 // #if CH_SPACEDIM==2
622 // {
623 // Real mu0 = 1.0;
624 // Real C0 = 1.0;
625 
626 // FORT_ENFORCEWELLPOSEDCELL
627 // (CHF_FRA1(levelC[dit],0),
628 // CHF_FRA1(levelMu[dit][0],0),
629 // CHF_FRA1(levelMu[dit][1],0),
630 // CHF_CONST_REAL(mu0),
631 // CHF_CONST_REAL(C0),
632 // CHF_BOX(levelGrids[dit]));
633 
634 // }
635 // #endif
636 
637  // lambda = 2*mu
638  FluxBox& lambda = levelLambda[dit];
639  for (int dir=0; dir<SpaceDim; dir++)
640  {
641  lambda[dir].copy(levelMu[dit][dir]);
642  lambda[dir] *= 2.0;
643  }
644  }
645 }
646 
647 #include "NamespaceFooter.H"
RefCountedPtr< LevelData< FluxBox > > m_faceA
Definition: FASIceSolver.H:132
virtual void reflux(const LevelData< FArrayBox > &a_phiFine, const LevelData< FArrayBox > &a_phi, LevelData< FArrayBox > &a_residual, AMRFASOp< LevelData< FArrayBox > > *a_finerOp)
Definition: FASIceSolverI.H:216
virtual int solve(Vector< LevelData< FArrayBox > * > &a_horizontalVel, Vector< LevelData< FArrayBox > * > &a_calvedIce, Vector< LevelData< FArrayBox > * > &a_addedIce, Vector< LevelData< FArrayBox > * > &a_removedIce, Real &a_initialResidualNorm, Real &a_finalResidualNorm, const Real a_convergenceMetric, const Vector< LevelData< FArrayBox > * > &a_rhs, const Vector< LevelData< FArrayBox > * > &a_C, const Vector< LevelData< FArrayBox > * > &a_C0, const Vector< LevelData< FArrayBox > * > &a_A, const Vector< LevelData< FluxBox > * > &a_muCoef, Vector< RefCountedPtr< LevelSigmaCS > > &a_coordSys, Real a_time, int a_lbase, int a_maxLevel)
full solve for non-isothermal ice
Definition: FASIceSolverI.H:389
Definition: FASIceSolver.H:66
RefCountedPtr< LevelData< FArrayBox > > m_Beta0
Definition: FASIceSolver.H:131
Abstract class around the englacial constitutive relations for ice.
Definition: ConstitutiveRelation.H:34
virtual void CFInterp(LevelData< FArrayBox > &a_phi, const LevelData< FArrayBox > &a_phiCoarse)
Definition: FASIceSolverI.H:55
ViscousTensorOp * m_VTO
Definition: FASIceSolver.H:134
virtual void define(const ProblemDomain &a_coarseDomain, ConstitutiveRelation *a_constRel, BasalFrictionRelation *a_basalFrictionRel, const Vector< DisjointBoxLayout > &a_vectGrids, const Vector< int > &a_vectRefRatio, const RealVect &a_dxCrse, IceThicknessIBC *a_bc, int a_numLevels)
Definition: FASIceSolverI.H:285
virtual RefCountedPtr< CompGridVTOBC > velocitySolveBC()=0
return boundary condition for Ice velocity solve
Physical/domain initial and boundary conditions for ice-sheet problems.
Definition: IceThicknessIBC.H:84
const ConstitutiveRelation * m_constRelPtr
Definition: FASIceSolver.H:122
virtual void computeFaceMu(LevelData< FluxBox > &a_mu, LevelData< FArrayBox > &a_vel, const Real &a_scale, const LevelData< FArrayBox > *a_crseVel, int a_nRefCrse, const LevelData< FluxBox > &a_A, const LevelSigmaCS &a_coordSys, const ProblemDomain &a_domain, const IntVect &a_ghostVect=IntVect::Zero) const =0
compute face-centered effective viscosity based on cell-centered velocity
RefCountedPtr< LevelData< FArrayBox > > m_Beta
Definition: FASIceSolver.H:130
FASIceViscouseTensorOp(int a_o, const DisjointBoxLayout &a_grid, const ConstitutiveRelation *a_constRelPtr, const BasalFrictionRelation *a_basalFrictionRelPtr, IceThicknessIBC *a_bc)
Constructor.
Definition: FASIceSolverI.H:28
Real m_time
Definition: FASIceSolver.H:126
virtual void define(const ProblemDomain &a_coarseDomain, const RealVect &a_crsDx, const Vector< DisjointBoxLayout > &a_grids, const Vector< int > &a_refRatios, int a_nSRGrids=0)
Definition: FASIceSolverI.H:319
RefCountedPtr< LevelSigmaCS > m_coordSys
Definition: FASIceSolver.H:127
virtual RefCountedPtr< AMRFASOp< LevelData< FArrayBox > > > AMRNewOp(int a_ilev, const DisjointBoxLayout &a_grid, bool a_isSR=false)
override base
Definition: FASIceSolverI.H:256
LevelData< FluxBox > & getFaceH()
returns modifiable face-centered H
Definition: LevelSigmaCS.cpp:356
virtual void computeAlpha(FArrayBox &a_alpha, const FArrayBox &a_basalVel, const FArrayBox &a_C, const Real &a_scale, const LevelSigmaCS &a_coords, const DataIterator &a_dit, int a_level, const Box &a_box) const =0
Computes cell-centered effective basal friction coeffcient such that .
void computeMu(LevelData< FArrayBox > &a_vel, const LevelData< FArrayBox > *a_crseVel, const LevelData< FArrayBox > *)
Definition: FASIceSolverI.H:526
virtual void levelGSRB(RefCountedPtr< LevelData< FArrayBox > > a_phi, const RefCountedPtr< LevelData< FArrayBox > > a_rhs)
Definition: FASIceSolverI.H:90
virtual void velocityGhostBC(LevelData< FArrayBox > &a_velocity, const LevelSigmaCS &a_coords, const ProblemDomain &a_domain, Real a_time)
fill ghost cells on velocity
Definition: IceThicknessIBC.H:199
Basic Sigma fourth-order coordinate system on an AMR level.
Definition: LevelSigmaCS.H:48
const LevelData< FArrayBox > & getThicknessOverFlotation() const
Definition: LevelSigmaCS.cpp:516
friend class FASIceViscouseTensorOpFactory
Definition: FASIceSolver.H:68
virtual void levelRich(RefCountedPtr< LevelData< FArrayBox > > a_phi, const RefCountedPtr< LevelData< FArrayBox > > a_rhs)
Definition: FASIceSolverI.H:113
Virtual base class for basal friction relations.
Definition: BasalFrictionRelation.H:27
static bool s_always_recompute_mu
Definition: FASIceSolverI.H:22
const LevelData< BaseFab< int > > & getFloatingMask() const
returns floating mask specifying whether ice is grounded or floating
Definition: LevelSigmaCS.H:187
virtual void applyLevel(LevelData< FArrayBox > &a_LofPhi, const LevelData< FArrayBox > &a_phi)
Definition: FASIceSolverI.H:65
const BasalFrictionRelation * m_basalFrictionRelPtr
Definition: FASIceSolver.H:123
IceThicknessIBC * m_bc
Definition: FASIceSolver.H:135
virtual void restrictState(RefCountedPtr< AMRFASOp< LevelData< FArrayBox > > >, Copier &a_copier)
Definition: FASIceSolverI.H:143
virtual bool computeState(RefCountedPtr< LevelData< FArrayBox > > a_phi, const RefCountedPtr< LevelData< FArrayBox > > a_CrsPhi, const RefCountedPtr< LevelData< FArrayBox > > a_FinePhi)
Definition: FASIceSolverI.H:195
FASIceViscouseTensorOpFactory(ConstitutiveRelation *a_constRelPtr, BasalFrictionRelation *a_basalFrictionRelPtr, IceThicknessIBC *a_bc)
Constructor.
Definition: FASIceSolverI.H:238