| 282 | } // setLSData |
| 283 | |
| 284 | void |
| 285 | fixMassLoss2PhaseFlows(double /*current_time*/, |
| 286 | double new_time, |
| 287 | bool /*skip_synchronize_new_state_data*/, |
| 288 | int /*num_cycles*/, |
| 289 | void* ctx) |
| 290 | { |
| 291 | LevelSetMassLossFixer* mass_fixer = static_cast<LevelSetMassLossFixer*>(ctx); |
| 292 | #if !defined(NDEBUG) |
| 293 | TBOX_ASSERT(mass_fixer); |
| 294 | #endif |
| 295 | const LevelSetContainer& ls_container = mass_fixer->getLevelSetContainer(); |
| 296 | Pointer<AdvDiffHierarchyIntegrator> adv_diff_integrator = ls_container.getAdvDiffHierarchyIntegrator(); |
| 297 | const int integrator_step = adv_diff_integrator->getIntegratorStep(); |
| 298 | const int mass_correction_interval = mass_fixer->getCorrectionInterval(); |
| 299 | |
| 300 | if (integrator_step % mass_correction_interval != 0) return; |
| 301 | |
| 302 | Pointer<PatchHierarchy<NDIM>> patch_hier = adv_diff_integrator->getPatchHierarchy(); |
| 303 | Pointer<HierarchyMathOps> hier_math_ops = adv_diff_integrator->getHierarchyMathOps(); |
| 304 | |
| 305 | const int hier_finest_ln = patch_hier->getFinestLevelNumber(); |
| 306 | const double vol_target = mass_fixer->getTargetVolume(); |
| 307 | const double ncells = ls_container.getInterfaceHalfWidth(); |
| 308 | |
| 309 | // NOTE: In practice the level set mass loss would be fixed during the postprocess integrate hierarchy stage. |
| 310 | // Hence the application time would be the new time and the variable context would be the new context. |
| 311 | VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); |
| 312 | const int ls_idx = |
| 313 | var_db->mapVariableAndContextToIndex(ls_container.getLevelSetVariable(), adv_diff_integrator->getNewContext()); |
| 314 | |
| 315 | // Carry out the Newton iterations |
| 316 | double rel_error = 1.0e12; |
| 317 | int current_iter = 0; |
| 318 | |
| 319 | const double min_rel_error = mass_fixer->getErrorRelTolerance(); |
| 320 | const int max_its = mass_fixer->getMaxIterations(); |
| 321 | |
| 322 | double q = 0.0; |
| 323 | HierarchyCellDataOpsReal<NDIM, double> hier_cc_ops(patch_hier, 0, hier_finest_ln); |
| 324 | while (rel_error > min_rel_error && current_iter < max_its) |
| 325 | { |
| 326 | std::vector<double> integrals = compute_heaviside_integrals(hier_math_ops, ls_idx, ncells); |
| 327 | const double& vol_phase1 = integrals[0]; // Target the gas volume |
| 328 | const double& integral_delta = integrals[2]; |
| 329 | |
| 330 | rel_error = std::abs(vol_phase1 / vol_target - 1.0); |
| 331 | |
| 332 | if (mass_fixer->enableLogging()) |
| 333 | { |
| 334 | plog << "fixMassLoss2PhaseFlows():: current iter = " << current_iter << " , rel error = " << rel_error |
| 335 | << std::endl; |
| 336 | } |
| 337 | |
| 338 | const double delta_q = (vol_phase1 - vol_target) / integral_delta; |
| 339 | hier_cc_ops.addScalar(ls_idx, ls_idx, delta_q); |
| 340 | |
| 341 | q += delta_q; |
nothing calls this directly
no test coverage detected