@@ -100,7 +100,9 @@ int main(int argc, char **argv)
100100
101101 auto &couplingParticipant = Dumux::Precice::CouplingAdapter::getInstance ();
102102
103- if (getParam<bool >(" Precice.RunWithCoupling" ) == true ) {
103+ const auto runWithCoupling = getParam<bool >(" Precice.RunWithCoupling" );
104+
105+ if (runWithCoupling) {
104106 couplingParticipant.announceSolver (" macro-heat" , preciceConfigFilename,
105107 mpiHelper.rank (), mpiHelper.size ());
106108 // verify that dimensions match
@@ -132,13 +134,13 @@ int main(int argc, char **argv)
132134 std::cout << " ;" << std::endl;
133135 }
134136 }
137+
135138 std::cout << " Number of Coupled Cells:" << coupledElementIdxs.size ()
136139 << std::endl;
137140
138- // initialize preCICE
139141 auto numberOfElements =
140142 coords.size () / couplingParticipant.getMeshDimensions (meshName);
141- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
143+ if (runWithCoupling ) {
142144 couplingParticipant.setMesh (meshName, coords);
143145
144146 // couples between dumux element indices and preciceIndices;
@@ -154,7 +156,7 @@ int main(int argc, char **argv)
154156 const std::string writeDataConcentration = " concentration" ;
155157 // const std::string writeDataTemperature = "temperature";
156158
157- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
159+ if (runWithCoupling ) {
158160 couplingParticipant.announceQuantity (meshName, readDatak00);
159161 couplingParticipant.announceQuantity (meshName, readDatak01);
160162 couplingParticipant.announceQuantity (meshName, readDatak10);
@@ -171,13 +173,17 @@ int main(int argc, char **argv)
171173 problem->applyInitialSolution (x);
172174 auto xOld = x;
173175
176+ auto xCheckpoint = x;
177+ double timeCheckpoint = 0.0 ;
178+ int timeStepCheckpoint = 0 ;
179+
174180 // initialize the coupling data
175181 std::vector<double > temperatures;
176182 for (int solIdx = 0 ; solIdx < numberOfElements; ++solIdx) {
177183 temperatures.push_back (x[solIdx][problem->returnTemperatureIdx ()]);
178184 };
179185
180- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
186+ if (runWithCoupling ) {
181187 couplingParticipant.writeQuantityVector (meshName, writeDataConcentration,
182188 temperatures);
183189 if (couplingParticipant
@@ -203,7 +209,7 @@ int main(int argc, char **argv)
203209 auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
204210 gridVariables->init (x);
205211
206- // intialize the vtk output module
212+ // initialize the vtk output module
207213 using IOFields = GetPropType<TypeTag, Properties::IOFields>;
208214 VtkOutputModule<GridVariables, SolutionVector> vtkWriter (*gridVariables, x,
209215 problem->name ());
@@ -220,7 +226,7 @@ int main(int argc, char **argv)
220226 // output every vtkOutputInterval time step
221227 const int vtkOutputInterval = getParam<int >(" TimeLoop.OutputInterval" );
222228
223- // initialize
229+ // initialize preCICE
224230 couplingParticipant.initialize ();
225231
226232 // time loop parameters
@@ -229,7 +235,7 @@ int main(int argc, char **argv)
229235 double solverDt;
230236 double dt;
231237
232- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
238+ if (runWithCoupling ) {
233239 solverDt = getParam<Scalar>(" TimeLoop.InitialDt" );
234240 dt = std::min (preciceDt, solverDt);
235241 } else {
@@ -261,16 +267,25 @@ int main(int argc, char **argv)
261267 std::cout << " Time Loop starts" << std::endl;
262268 timeLoop->start ();
263269 do {
264- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
270+ if (runWithCoupling ) {
265271 if (couplingParticipant.isCouplingOngoing () == false )
266272 break ;
267273
268274 // write checkpoint
269275 if (couplingParticipant.requiresToWriteCheckpoint ()) {
270- xOld = x;
276+ xCheckpoint = x;
277+ timeCheckpoint = timeLoop->time ();
278+ timeStepCheckpoint = timeLoop->timeStepIndex ();
271279 }
272280
281+ preciceDt = couplingParticipant.getMaxTimeStepSize ();
282+ solverDt = std::min (nonLinearSolver.suggestTimeStepSize (timeLoop->timeStepSize ()),
283+ timeLoop->maxTimeStepSize ());
284+ dt = std::min (preciceDt, solverDt);
285+
273286 // read porosity and conductivity data from other solver
287+ // TODO: data needs to be updated if Newton solver adapts time-step size
288+ // and coupling data is interpolated in time
274289 couplingParticipant.readQuantityFromOtherSolver (meshName, readDatak00,
275290 dt);
276291 couplingParticipant.readQuantityFromOtherSolver (meshName, readDatak01,
@@ -281,89 +296,79 @@ int main(int argc, char **argv)
281296 dt);
282297 couplingParticipant.readQuantityFromOtherSolver (meshName,
283298 readDataPorosity, dt);
284- // store coupling data in problem
299+ // store coupling data in spatial params, exchange with MPI
285300 problem->spatialParams ().updateCouplingData ();
301+ } else {
302+ dt = std::min (
303+ nonLinearSolver.suggestTimeStepSize (timeLoop->timeStepSize ()),
304+ timeLoop->maxTimeStepSize ());
286305 }
287- std::cout << " Solver starts" << std::endl;
306+ // set new dt as suggested by the Newton solver or by preCICE
307+ timeLoop->setTimeStepSize (dt);
308+
309+ std::cout << " Solver starts with target dt: " << dt << std::endl;
288310
289311 // linearize & solve
290312 nonLinearSolver.solve (x, *timeLoop);
291313
292- int solIdx = 0 ;
293- for (const auto &element : elements (leafGridView, Dune::Partitions::interior)) {
294- auto fvGeometry = localView (*gridGeometry);
295- fvGeometry.bindElement (element);
296- for (const auto &scv : scvs (fvGeometry)) {
297- temperatures[solIdx++] =
298- x[scv.elementIndex ()][problem->returnTemperatureIdx ()];
299- }
314+ // save dt value that was actually used by the non-linear solver
315+ dt = timeLoop->timeStepSize ();
316+
317+ // DuMux advance + report
318+ gridVariables->advanceTimeStep ();
319+ timeLoop->advanceTimeStep ();
320+ timeLoop->reportTimeStep ();
321+ xOld = x;
322+
323+ // Vtk output
324+ // TODO: output interval does not work seamlessly when subcycling
325+ n += 1 ;
326+ if (n == vtkOutputInterval) {
327+ problem->updateVtkOutput (x);
328+ vtkWriter.write (timeLoop->time ());
329+ n = 0 ;
300330 }
301331
302- if (getParam<bool >(" Precice.RunWithCoupling" ) == true ) {
332+ if (runWithCoupling) {
333+ int solIdx = 0 ;
334+ for (const auto &element : elements (leafGridView, Dune::Partitions::interior)) {
335+ auto fvGeometry = localView (*gridGeometry);
336+ fvGeometry.bindElement (element);
337+ for (const auto &scv : scvs (fvGeometry)) {
338+ temperatures[solIdx++] =
339+ x[scv.elementIndex ()][problem->returnTemperatureIdx ()];
340+ }
341+ }
342+
303343 couplingParticipant.writeQuantityVector (meshName,
304344 writeDataConcentration, temperatures);
305345 couplingParticipant.writeQuantityToOtherSolver (meshName,
306346 writeDataConcentration);
307- }
308-
309- // advance precice
310- if (getParam<bool >(" Precice.RunWithCoupling" ) == true ) {
311- couplingParticipant.advance (timeLoop->timeStepSize ());
312-
313- preciceDt = couplingParticipant.getMaxTimeStepSize ();
314- solverDt = std::min (nonLinearSolver.suggestTimeStepSize (timeLoop->timeStepSize ()), timeLoop->maxTimeStepSize ());
315- dt = std::min (preciceDt, solverDt);
316347
348+ // advance preCICE
317349 if ((!fabs (preciceDt - dt)) < 1e-14 ) {
318- std::cout << " dt from preCICE is different than dt from DuMuX. "
319- " preCICE dt = "
320- << preciceDt << " and DuMuX dt =" << solverDt << std::endl;
350+ std::cout << " dt from preCICE is different than dt from DuMuX."
351+ << " preCICE dt = " << preciceDt
352+ << " and DuMuX dt = " << solverDt
353+ << " resulted in dt = " << dt
354+ << std::endl;
321355 }
322- } else
323- dt = std::min (
324- nonLinearSolver.suggestTimeStepSize (timeLoop->timeStepSize ()),
325- getParam<Scalar>(" TimeLoop.MaxDt" ));
356+ std::flush (std::cout);
357+ couplingParticipant.advance (dt);
326358
327- std::cout << " Using dt: " << dt << std::endl;
328-
329- if (getParam<bool >(" Precice.RunWithCoupling" ) == true ) {
359+ // reset to checkpoint if not converged
330360 if (couplingParticipant.requiresToReadCheckpoint ()) {
331- // make the new solution the old solution
332- x = xOld;
361+ x = xCheckpoint;
362+ xOld = x;
363+ timeLoop->setTime (timeCheckpoint, timeStepCheckpoint);
364+
365+ // TODO: previousTimeStep might be more appropriate, last one could be small
366+ timeLoop->setTimeStepSize (dt);
333367 gridVariables->update (x);
334368 gridVariables->advanceTimeStep ();
335- } else // coupling successful
336- {
337- n += 1 ;
338- if (n == vtkOutputInterval) {
339- problem->updateVtkOutput (x);
340- vtkWriter.write (timeLoop->time ());
341- n = 0 ;
342- }
343- gridVariables->advanceTimeStep ();
344- // advance the time loop to the next step
345- timeLoop->advanceTimeStep ();
346- // report statistics of this time step
347- timeLoop->reportTimeStep ();
348- }
349- } else {
350- xOld = x;
351- gridVariables->advanceTimeStep ();
352- // advance the time loop to the next step
353- timeLoop->advanceTimeStep ();
354- // report statistics of this time step
355- timeLoop->reportTimeStep ();
356-
357- // output every outputinterval steps
358- n += 1 ;
359- if (n == vtkOutputInterval) {
360- problem->updateVtkOutput (x);
361- vtkWriter.write (timeLoop->time ());
362- n = 0 ;
369+ continue ;
363370 }
364371 }
365- // set new dt as suggested by the newton solver or by preCICE
366- timeLoop->setTimeStepSize (dt);
367372
368373 std::cout << " Time: " << timeLoop->time () << std::endl;
369374
@@ -374,7 +379,7 @@ int main(int argc, char **argv)
374379 // //////////////////////////////////////////////////////////
375380 // finalize, print dumux message to say goodbye
376381 // //////////////////////////////////////////////////////////
377- if (getParam< bool >( " Precice.RunWithCoupling " ) == true ) {
382+ if (runWithCoupling ) {
378383 couplingParticipant.finalize ();
379384 }
380385 // print dumux end message
0 commit comments