19#ifndef DUMUX_FVTRANSPORT_HH
20#define DUMUX_FVTRANSPORT_HH
22#include <dune/grid/common/gridenums.hh>
26#include <unordered_map>
50template<
class TypeTag>
59 dim = GridView::dimension, dimWorld = GridView::dimensionworld
70 using Element =
typename GridView::Traits::template Codim<0>::Entity;
71 using Intersection =
typename GridView::Intersection;
73 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
75 struct LocalTimesteppingData
77 Dune::FieldVector<Scalar, 2*dim> faceFluxes;
78 Dune::FieldVector<Scalar, 2*dim> faceTargetDt;
80 LocalTimesteppingData():faceFluxes(0.0), faceTargetDt(0.0), dt(0)
86 EvalCflFluxFunction& evalCflFluxFunction()
88 return *evalCflFluxFunction_;
91 const EvalCflFluxFunction& evalCflFluxFunction()
const
93 return *evalCflFluxFunction_;
102 void update(
const Scalar t, Scalar& dt, TransportSolutionType& updateVec,
bool impet =
false);
106 asImp_().updateMaterialLaws();
107 asImp_().update(t, dt, updateVec);
118 void getFlux(Scalar&
update,
const Intersection& intersection, CellData& cellDataI);
143 evalCflFluxFunction_->initialize();
157 template<
class DataEntry>
178 template<
class MultiWriter>
204 return localTimeStepping_;
214 problem_(problem), switchNormals_(
getParam<bool>(
"Impet.SwitchNormals")),
215 subCFLFactor_(1.0), accumulatedDt_(0), dtThreshold_(1e-6)
217 evalCflFluxFunction_ = std::make_shared<EvalCflFluxFunction>(problem);
219 Scalar cFLFactor = getParam<Scalar>(
"Impet.CFLFactor");
221 subCFLFactor_ = min(getParam<Scalar>(
"Impet.SubCFLFactor"), cFLFactor);
222 verbosity_ = getParam<int>(
"TimeManager.SubTimestepVerbosity");
224 localTimeStepping_ = subCFLFactor_/cFLFactor < 1.0 - dtThreshold_;
226 if (localTimeStepping_)
227 std::cout<<
"max CFL-Number of "<<cFLFactor<<
", max Sub-CFL-Number of "<<subCFLFactor_<<
": Enable local time-stepping!\n";
232 Implementation &asImp_()
233 {
return *
static_cast<Implementation *
>(
this); }
236 const Implementation &asImp_()
const
237 {
return *
static_cast<const Implementation *
>(
this); }
239 void updatedTargetDt_(Scalar &dt);
241 void resetTimeStepData_()
243 timeStepData_.clear();
250 std::shared_ptr<EvalCflFluxFunction> evalCflFluxFunction_;
251 std::vector<LocalTimesteppingData> timeStepData_;
252 bool localTimeStepping_;
253 Scalar subCFLFactor_;
254 Scalar accumulatedDt_;
255 const Scalar dtThreshold_;
269template<
class TypeTag>
274 asImp_().updateMaterialLaws();
277 unsigned int size = problem_.gridView().size(0);
278 if (localTimeStepping_)
280 if (timeStepData_.size() != size)
281 timeStepData_.resize(size);
284 dt = std::numeric_limits<Scalar>::max();
287 updateVec.resize(size);
291 for (
const auto& element : elements(problem_.gridView()))
294 if (element.partitionType() != Dune::InteriorEntity)
301 int globalIdxI = problem_.variables().index(element);
303 CellData& cellDataI = problem_.variables().cellData(globalIdxI);
306 evalCflFluxFunction().reset();
308 if (localTimeStepping_)
310 LocalTimesteppingData& localData = timeStepData_[globalIdxI];
311 for (
int i = 0; i < 2*dim; i++)
313 if (localData.faceTargetDt[i] < accumulatedDt_ + dtThreshold_)
315 localData.faceFluxes[i] = 0.0;
321 for (
const auto& intersection : intersections(problem_.gridView(), element))
323 GlobalPosition unitOuterNormal = intersection.centerUnitOuterNormal();
325 unitOuterNormal *= -1.0;
327 int indexInInside = intersection.indexInInside();
330 if (intersection.neighbor())
332 if (localTimeStepping_)
334 LocalTimesteppingData& localData = timeStepData_[globalIdxI];
336 if (localData.faceTargetDt[indexInInside] < accumulatedDt_ + dtThreshold_)
338 asImp_().getFlux(localData.faceFluxes[indexInInside], intersection, cellDataI);
342 asImp_().getFlux(update, intersection, cellDataI);
348 asImp_().getFlux(update, intersection, cellDataI);
352 else if (intersection.boundary())
354 if (localTimeStepping_)
356 LocalTimesteppingData& localData = timeStepData_[globalIdxI];
357 if (localData.faceTargetDt[indexInInside] < accumulatedDt_ + dtThreshold_)
359 asImp_().getFluxOnBoundary(localData.faceFluxes[indexInInside], intersection, cellDataI);
363 asImp_().getFluxOnBoundary(update, intersection, cellDataI);
369 asImp_().getFluxOnBoundary(update, intersection, cellDataI);
374 if (localTimeStepping_)
376 LocalTimesteppingData& localData = timeStepData_[globalIdxI];
377 for (
int i=0; i < 2*dim; i++)
379 updateVec[globalIdxI] += localData.faceFluxes[i];
385 updateVec[globalIdxI] += update;
392 asImp_().getSource(source,element, cellDataI);
393 updateVec[globalIdxI] += source;
397 if (localTimeStepping_)
399 Scalar dtCfl = evalCflFluxFunction().getDt(element);
401 timeStepData_[globalIdxI].dt = dtCfl;
407 dt = min(dt, evalCflFluxFunction().getDt(element));
411 cellDataI.setUpdate(updateVec[globalIdxI]);
418 using ElementMapper =
typename SolutionTypes::ElementMapper;
420 DataHandle dataHandle(problem_.elementMapper(), updateVec);
421 problem_.gridView().template communicate<DataHandle>(dataHandle,
422 Dune::InteriorBorder_All_Interface,
423 Dune::ForwardCommunication);
425 if (localTimeStepping_)
429 TimeDataHandle timeDataHandle(problem_.elementMapper(), timeStepData_);
430 problem_.gridView().template communicate<TimeDataHandle>(timeDataHandle,
431 Dune::InteriorBorder_All_Interface,
432 Dune::ForwardCommunication);
435 dt = problem_.gridView().comm().min(dt);
439template<
class TypeTag>
442 dt = std::numeric_limits<Scalar>::max();
445 for (
const auto& element : elements(problem_.gridView()))
448 if (element.partitionType() != Dune::InteriorEntity)
455 int globalIdxI = problem_.variables().index(element);
457 LocalTimesteppingData& localDataI = timeStepData_[globalIdxI];
460 using FaceDt = std::unordered_map<int, Scalar>;
464 for (
const auto& intersection : intersections(problem_.gridView(), element))
466 int indexInInside = intersection.indexInInside();
468 if (intersection.neighbor())
470 auto neighbor = intersection.outside();
471 int globalIdxJ = problem_.variables().index(neighbor);
473 int levelI = element.level();
474 int levelJ = neighbor.level();
476 if (globalIdxI < globalIdxJ && levelI <= levelJ)
478 LocalTimesteppingData& localDataJ = timeStepData_[globalIdxJ];
480 int indexInOutside = intersection.indexInOutside();
482 if (localDataI.faceTargetDt[indexInInside] < accumulatedDt_ + dtThreshold_
483 || localDataJ.faceTargetDt[indexInOutside] < accumulatedDt_ + dtThreshold_)
485 Scalar timeStep = min(localDataI.dt, localDataJ.dt);
489 typename FaceDt::iterator it = faceDt.find(indexInInside);
490 if (it != faceDt.end())
492 it->second = min(it->second, timeStep);
496 faceDt.insert(std::make_pair(indexInInside, timeStep));
501 localDataI.faceTargetDt[indexInInside] += subCFLFactor_ * timeStep;
502 localDataJ.faceTargetDt[indexInOutside] += subCFLFactor_ * timeStep;
505 dt = min(dt, timeStep);
509 else if (intersection.boundary())
511 if (localDataI.faceTargetDt[indexInInside] < accumulatedDt_ + dtThreshold_)
513 localDataI.faceTargetDt[indexInInside] += subCFLFactor_ * localDataI.dt;
514 dt =min(dt, subCFLFactor_ * localDataI.dt);
518 if (faceDt.size() > 0)
520 typename FaceDt::iterator it = faceDt.begin();
521 for (;it != faceDt.end();++it)
523 localDataI.faceTargetDt[it->first] += subCFLFactor_ * it->second;
526 for (
const auto& intersection : intersections(problem_.gridView(), element))
528 if (intersection.neighbor())
530 int indexInInside = intersection.indexInInside();
532 it = faceDt.find(indexInInside);
533 if (it != faceDt.end())
535 int globalIdxJ = problem_.variables().index(intersection.outside());
537 LocalTimesteppingData& localDataJ = timeStepData_[globalIdxJ];
539 int indexInOutside = intersection.indexInOutside();
541 localDataJ.faceTargetDt[indexInOutside] += subCFLFactor_ * it->second;
550 using SolutionTypes = GetProp<TypeTag, Properties::SolutionTypes>;
551 using ElementMapper =
typename SolutionTypes::ElementMapper;
552 using TimeDataHandle = VectorExchange<ElementMapper, std::vector<LocalTimesteppingData> >;
554 TimeDataHandle timeDataHandle(problem_.elementMapper(), timeStepData_);
555 problem_.gridView().template communicate<TimeDataHandle>(timeDataHandle,
556 Dune::InteriorBorder_All_Interface,
557 Dune::ForwardCommunication);
559 dt = problem_.gridView().comm().min(dt);
563template<
class TypeTag>
566 if (localTimeStepping_)
568 Scalar realDt = problem_.timeManager().timeStepSize();
570 Scalar subDt = realDt;
572 updatedTargetDt_(subDt);
574 Scalar accumulatedDtOld = accumulatedDt_;
575 accumulatedDt_ += subDt;
577 Scalar t = problem_.timeManager().time();
579 if (accumulatedDt_ < realDt)
584 Scalar dtCorrection = min(0.0, realDt - accumulatedDt_);
585 subDt += dtCorrection;
588 std::cout<<
" Sub-time-step size: "<<subDt<<
"\n";
590 TransportSolutionType transportedQuantity;
591 asImp_().getTransportedQuantity(transportedQuantity);
593 bool stopTimeStep =
false;
594 int size = transportedQuantity.size();
595 for (
int i = 0; i < size; i++)
597 Scalar newVal = transportedQuantity[i] += updateVec[i] * subDt;
598 if (!asImp_().inPhysicalRange(newVal))
609 rank = problem_.gridView().comm().rank();
611 rank = problem_.gridView().comm().max(rank);
612 problem_.gridView().comm().broadcast(&stopTimeStep,1,rank);
616 if (stopTimeStep && accumulatedDtOld > dtThreshold_)
618 problem_.timeManager().setTimeStepSize(accumulatedDtOld);
623 asImp_().setTransportedQuantity(transportedQuantity);
627 if (accumulatedDt_ >= realDt)
632 problem_.model().updateTransport(t, subDt, updateVec);
634 updatedTargetDt_(subDt);
636 accumulatedDtOld = accumulatedDt_;
637 accumulatedDt_ += subDt;
642 asImp_().updateTransportedQuantity(updateVec, realDt);
645 resetTimeStepData_();
Contains a class to exchange entries of a vector.
Specifies the properties for immiscible 2p transport.
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition: parameters.hh:365
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:140
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
A data handle class to exchange entries of a vector.
Definition: vectorcommdatahandle.hh:79
The finite volume discretization of a transport equation.
Definition: transport.hh:52
void initialize()
Sets the initial solution .
Definition: transport.hh:141
void updateMaterialLaws()
Updates constitutive relations and stores them in the variable class.
void deserializeEntity(std::istream &instream, const Element &element)
Function for deserialization of the primary transport variable.
Definition: transport.hh:199
void getTransportedQuantity(TransportSolutionType &transportedQuantity)
Writes the current values of the primary transport variable into the transportedQuantity-vector (come...
void addOutputVtkFields(MultiWriter &writer)
Adds transport output to the output file.
Definition: transport.hh:179
void serializeEntity(std::ostream &outstream, const Element &element)
Function for serialization of the primary transport variable.
Definition: transport.hh:189
void getSource(Scalar &update, const Element &element, CellData &cellDataI)
Function which calculates the source update.
bool enableLocalTimeStepping()
Definition: transport.hh:202
void getFlux(Scalar &update, const Intersection &intersection, CellData &cellDataI)
Function which calculates the flux update.
void setTransportedQuantity(TransportSolutionType &transportedQuantity)
Writes the current values of the primary transport variable into the variable container.
void updateTransportedQuantity(TransportSolutionType &updateVec)
Updates the primary transport variable.
FVTransport(Problem &problem)
Constructs a FVTransport object.
Definition: transport.hh:213
void getFluxOnBoundary(Scalar &update, const Intersection &intersection, CellData &cellDataI)
Function which calculates the boundary flux update.
void updateTransport(const Scalar t, Scalar &dt, TransportSolutionType &updateVec)
Definition: transport.hh:104
void update(const Scalar t, Scalar &dt, TransportSolutionType &updateVec, bool impet=false)
Calculate the update vector.
Definition: transport.hh:270
void innerUpdate(TransportSolutionType &updateVec)
Definition: transport.hh:564
bool inPhysicalRange(DataEntry &entry)
Base file for properties related to sequential models.