| 350 | } // fixMassLoss2PhaseFlows |
| 351 | |
| 352 | void |
| 353 | fixMassLoss3PhaseFlows(double /*current_time*/, |
| 354 | double new_time, |
| 355 | bool /*skip_synchronize_new_state_data*/, |
| 356 | int /*num_cycles*/, |
| 357 | void* ctx) |
| 358 | { |
| 359 | LevelSetMassLossFixer* mass_fixer = static_cast<LevelSetMassLossFixer*>(ctx); |
| 360 | #if !defined(NDEBUG) |
| 361 | TBOX_ASSERT(mass_fixer); |
| 362 | #endif |
| 363 | const LevelSetContainer& ls_container = mass_fixer->getLevelSetContainer(); |
| 364 | Pointer<AdvDiffHierarchyIntegrator> adv_diff_integrator = ls_container.getAdvDiffHierarchyIntegrator(); |
| 365 | const int integrator_step = adv_diff_integrator->getIntegratorStep(); |
| 366 | const int mass_correction_interval = mass_fixer->getCorrectionInterval(); |
| 367 | |
| 368 | if (integrator_step % mass_correction_interval != 0) return; |
| 369 | |
| 370 | Pointer<PatchHierarchy<NDIM>> patch_hier = adv_diff_integrator->getPatchHierarchy(); |
| 371 | Pointer<HierarchyMathOps> hier_math_ops = adv_diff_integrator->getHierarchyMathOps(); |
| 372 | |
| 373 | const int hier_finest_ln = patch_hier->getFinestLevelNumber(); |
| 374 | const double vol_target = mass_fixer->getTargetVolume(); |
| 375 | const double ncells = ls_container.getInterfaceHalfWidth(); |
| 376 | |
| 377 | // NOTE: In practice the level set mass loss would be fixed during the postprocess integrate hierarchy stage. |
| 378 | // Hence the application time would be the new time and the variable context would be the new context. |
| 379 | VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); |
| 380 | const int fluid_ls_idx = |
| 381 | var_db->mapVariableAndContextToIndex(ls_container.getLevelSetVariable(0), adv_diff_integrator->getNewContext()); |
| 382 | const int solid_ls_idx = |
| 383 | var_db->mapVariableAndContextToIndex(ls_container.getLevelSetVariable(1), adv_diff_integrator->getNewContext()); |
| 384 | |
| 385 | // Carry out the Newton iterations |
| 386 | double rel_error = 1.0e12; |
| 387 | int current_iter = 0; |
| 388 | |
| 389 | const double min_rel_error = mass_fixer->getErrorRelTolerance(); |
| 390 | const int max_its = mass_fixer->getMaxIterations(); |
| 391 | |
| 392 | double q = 0.0; |
| 393 | HierarchyCellDataOpsReal<NDIM, double> hier_cc_ops(patch_hier, 0, hier_finest_ln); |
| 394 | while (rel_error > min_rel_error && current_iter < max_its) |
| 395 | { |
| 396 | std::vector<double> integrals = compute_heaviside_integrals(hier_math_ops, fluid_ls_idx, solid_ls_idx, ncells); |
| 397 | const double& vol_phase2 = integrals[1]; // Target the liquid volume |
| 398 | const double& integral_delta = integrals[3]; |
| 399 | |
| 400 | rel_error = std::abs(vol_phase2 / vol_target - 1.0); |
| 401 | |
| 402 | if (mass_fixer->enableLogging()) |
| 403 | { |
| 404 | plog << "fixMassLoss3PhaseFlows():: current iter = " << current_iter << " , rel error = " << rel_error |
| 405 | << std::endl; |
| 406 | } |
| 407 | |
| 408 | const double delta_q = -(vol_phase2 - vol_target) / integral_delta; |
| 409 | hier_cc_ops.addScalar(fluid_ls_idx, fluid_ls_idx, delta_q); |
nothing calls this directly
no test coverage detected