/******************************************************************************* * For each run, the input filename must be given on the command line. In all * * cases, the command line is: * * * * executable <input file name> * * * *******************************************************************************/ int main(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); { // cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "vc_laplace.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database. Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>( "StandardTagAndInitialize", NULL, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Create variables and register them with the variable database. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); Pointer<VariableContext> ctx = var_db->getContext("context"); Pointer<SideVariable<NDIM, double> > u_side_var = new SideVariable<NDIM, double>("u_side"); Pointer<SideVariable<NDIM, double> > f_side_var = new SideVariable<NDIM, double>("f_side"); Pointer<SideVariable<NDIM, double> > e_side_var = new SideVariable<NDIM, double>("e_side"); const int u_side_idx = var_db->registerVariableAndContext(u_side_var, ctx, IntVector<NDIM>(1)); const int f_side_idx = var_db->registerVariableAndContext(f_side_var, ctx, IntVector<NDIM>(1)); const int e_side_idx = var_db->registerVariableAndContext(e_side_var, ctx, IntVector<NDIM>(1)); Pointer<CellVariable<NDIM, double> > u_cell_var = new CellVariable<NDIM, double>("u_cell", NDIM); Pointer<CellVariable<NDIM, double> > f_cell_var = new CellVariable<NDIM, double>("f_cell", NDIM); Pointer<CellVariable<NDIM, double> > e_cell_var = new CellVariable<NDIM, double>("e_cell", NDIM); const int u_cell_idx = var_db->registerVariableAndContext(u_cell_var, ctx, IntVector<NDIM>(0)); const int f_cell_idx = var_db->registerVariableAndContext(f_cell_var, ctx, IntVector<NDIM>(0)); const int e_cell_idx = var_db->registerVariableAndContext(e_cell_var, ctx, IntVector<NDIM>(0)); Pointer<NodeVariable<NDIM, double> > mu_node_var = new NodeVariable<NDIM, double>("mu_node"); const int mu_node_idx = var_db->registerVariableAndContext(mu_node_var, ctx, IntVector<NDIM>(1)); // Register variables for plotting. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); TBOX_ASSERT(visit_data_writer); visit_data_writer->registerPlotQuantity(u_cell_var->getName(), "VECTOR", u_cell_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(u_cell_var->getName() + stream.str(), "SCALAR", u_cell_idx, d); } visit_data_writer->registerPlotQuantity(f_cell_var->getName(), "VECTOR", f_cell_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(f_cell_var->getName() + stream.str(), "SCALAR", f_cell_idx, d); } visit_data_writer->registerPlotQuantity(e_cell_var->getName(), "VECTOR", e_cell_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(e_cell_var->getName() + stream.str(), "SCALAR", e_cell_idx, d); } visit_data_writer->registerPlotQuantity(mu_node_var->getName(), "SCALAR", mu_node_idx); // Initialize the AMR patch hierarchy. gridding_algorithm->makeCoarsestLevel(patch_hierarchy, 0.0); int tag_buffer = 1; int level_number = 0; bool done = false; while (!done && (gridding_algorithm->levelCanBeRefined(level_number))) { gridding_algorithm->makeFinerLevel(patch_hierarchy, 0.0, 0.0, tag_buffer); done = !patch_hierarchy->finerLevelExists(level_number); ++level_number; } // Set the simulation time to be zero. const double data_time = 0.0; // Allocate data on each level of the patch hierarchy. for (int ln = 0; ln <= patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(u_side_idx, data_time); level->allocatePatchData(f_side_idx, data_time); level->allocatePatchData(e_side_idx, data_time); level->allocatePatchData(u_cell_idx, data_time); level->allocatePatchData(f_cell_idx, data_time); level->allocatePatchData(e_cell_idx, data_time); level->allocatePatchData(mu_node_idx, data_time); } // Setup exact solution data. muParserCartGridFunction u_fcn("u", app_initializer->getComponentDatabase("u"), grid_geometry); muParserCartGridFunction f_fcn("f", app_initializer->getComponentDatabase("f"), grid_geometry); muParserCartGridFunction mu_fcn("mu", app_initializer->getComponentDatabase("mu"), grid_geometry); u_fcn.setDataOnPatchHierarchy(u_side_idx, u_side_var, patch_hierarchy, data_time); f_fcn.setDataOnPatchHierarchy(e_side_idx, e_side_var, patch_hierarchy, data_time); mu_fcn.setDataOnPatchHierarchy(mu_node_idx, mu_node_var, patch_hierarchy, data_time); // Create an object to communicate ghost cell data. typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent; InterpolationTransactionComponent u_transaction(u_side_idx, "CUBIC_COARSEN", "LINEAR"); InterpolationTransactionComponent mu_transaction(mu_node_idx, "CONSTANT_COARSEN", "LINEAR"); vector<InterpolationTransactionComponent> transactions(2); transactions[0] = u_transaction; transactions[1] = mu_transaction; Pointer<HierarchyGhostCellInterpolation> bdry_fill_op = new HierarchyGhostCellInterpolation(); bdry_fill_op->initializeOperatorState(transactions, patch_hierarchy); // Create the math operations object and get the patch data index for // the side-centered weighting factor. HierarchyMathOps hier_math_ops("hier_math_ops", patch_hierarchy); const int dx_side_idx = hier_math_ops.getSideWeightPatchDescriptorIndex(); // Compute (f0,f1) := div mu (grad(u0,u1) + grad(u0,u1)^T). hier_math_ops.vc_laplace(f_side_idx, f_side_var, 1.0, 0.0, mu_node_idx, mu_node_var, u_side_idx, u_side_var, bdry_fill_op, data_time); // Compute error and print error norms. Pointer<HierarchyDataOpsReal<NDIM, double> > hier_side_data_ops = HierarchyDataOpsManager<NDIM>::getManager()->getOperationsDouble(u_side_var, patch_hierarchy, true); hier_side_data_ops->subtract(e_side_idx, e_side_idx, f_side_idx); // computes e := e - f pout << "|e|_oo = " << hier_side_data_ops->maxNorm(e_side_idx, dx_side_idx) << "\n"; pout << "|e|_2 = " << hier_side_data_ops->L2Norm(e_side_idx, dx_side_idx) << "\n"; pout << "|e|_1 = " << hier_side_data_ops->L1Norm(e_side_idx, dx_side_idx) << "\n"; // Interpolate the side-centered data to cell centers for output. static const bool synch_cf_interface = true; hier_math_ops.interp(u_cell_idx, u_cell_var, u_side_idx, u_side_var, NULL, data_time, synch_cf_interface); hier_math_ops.interp(f_cell_idx, f_cell_var, f_side_idx, f_side_var, NULL, data_time, synch_cf_interface); hier_math_ops.interp(e_cell_idx, e_cell_var, e_side_idx, e_side_var, NULL, data_time, synch_cf_interface); // Output data for plotting. visit_data_writer->writePlotData(patch_hierarchy, 0, data_time); } // cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return 0; } // main
/******************************************************************************* * For each run, the input filename and restart information (if needed) must * * be given on the command line. For non-restarted case, command line is: * * * * executable <input file name> * * * * For restarted run, command line is: * * * * executable <input file name> <restart directory> <restart number> * * * *******************************************************************************/ int main(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); { // cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, initialize the restart database (if this is a restarted run), // and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "IB.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Get various standard options set in the input file. const bool dump_viz_data = app_initializer->dumpVizData(); const int viz_dump_interval = app_initializer->getVizDumpInterval(); const bool uses_visit = dump_viz_data && app_initializer->getVisItDataWriter(); const bool dump_restart_data = app_initializer->dumpRestartData(); const int restart_dump_interval = app_initializer->getRestartDumpInterval(); const string restart_dump_dirname = app_initializer->getRestartDumpDirectory(); const bool dump_postproc_data = app_initializer->dumpPostProcessingData(); const int postproc_data_dump_interval = app_initializer->getPostProcessingDataDumpInterval(); const string postproc_data_dump_dirname = app_initializer->getPostProcessingDataDumpDirectory(); if (dump_postproc_data && (postproc_data_dump_interval > 0) && !postproc_data_dump_dirname.empty()) { Utilities::recursiveMkdir(postproc_data_dump_dirname); } const bool dump_timer_data = app_initializer->dumpTimerData(); const int timer_dump_interval = app_initializer->getTimerDumpInterval(); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database // and, if this is a restarted run, from the restart database. Pointer<INSHierarchyIntegrator> navier_stokes_integrator; const string solver_type = app_initializer->getComponentDatabase("Main")->getStringWithDefault("solver_type", "STAGGERED"); if (solver_type == "STAGGERED") { navier_stokes_integrator = new INSStaggeredHierarchyIntegrator( "INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); } else if (solver_type == "COLLOCATED") { navier_stokes_integrator = new INSCollocatedHierarchyIntegrator( "INSCollocatedHierarchyIntegrator", app_initializer->getComponentDatabase("INSCollocatedHierarchyIntegrator")); } else { TBOX_ERROR("Unsupported solver type: " << solver_type << "\n" << "Valid options are: COLLOCATED, STAGGERED"); } Pointer<IBMethod> ib_method_ops = new IBMethod("IBMethod", app_initializer->getComponentDatabase("IBMethod")); Pointer<IBHierarchyIntegrator> time_integrator = new IBExplicitHierarchyIntegrator( "IBHierarchyIntegrator", app_initializer->getComponentDatabase("IBHierarchyIntegrator"), ib_method_ops, navier_stokes_integrator); Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>("StandardTagAndInitialize", time_integrator, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Configure the IB solver. Pointer<IBStandardInitializer> ib_initializer = new IBStandardInitializer( "IBStandardInitializer", app_initializer->getComponentDatabase("IBStandardInitializer")); ib_method_ops->registerLInitStrategy(ib_initializer); Pointer<IBStandardForceGen> ib_force_fcn = new IBStandardForceGen(); ib_method_ops->registerIBLagrangianForceFunction(ib_force_fcn); // Create Eulerian initial condition specification objects. These // objects also are used to specify exact solution values for error // analysis. Pointer<CartGridFunction> u_init = new muParserCartGridFunction( "u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); navier_stokes_integrator->registerVelocityInitialConditions(u_init); Pointer<CartGridFunction> p_init = new muParserCartGridFunction( "p_init", app_initializer->getComponentDatabase("PressureInitialConditions"), grid_geometry); navier_stokes_integrator->registerPressureInitialConditions(p_init); // Create Eulerian boundary condition specification objects (when necessary). const IntVector<NDIM>& periodic_shift = grid_geometry->getPeriodicShift(); vector<RobinBcCoefStrategy<NDIM>*> u_bc_coefs(NDIM); if (periodic_shift.min() > 0) { for (unsigned int d = 0; d < NDIM; ++d) { u_bc_coefs[d] = NULL; } } else { for (unsigned int d = 0; d < NDIM; ++d) { ostringstream bc_coefs_name_stream; bc_coefs_name_stream << "u_bc_coefs_" << d; const string bc_coefs_name = bc_coefs_name_stream.str(); ostringstream bc_coefs_db_name_stream; bc_coefs_db_name_stream << "VelocityBcCoefs_" << d; const string bc_coefs_db_name = bc_coefs_db_name_stream.str(); u_bc_coefs[d] = new muParserRobinBcCoefs( bc_coefs_name, app_initializer->getComponentDatabase(bc_coefs_db_name), grid_geometry); } navier_stokes_integrator->registerPhysicalBoundaryConditions(u_bc_coefs); } // Create Eulerian body force function specification objects. if (input_db->keyExists("ForcingFunction")) { Pointer<CartGridFunction> f_fcn = new muParserCartGridFunction( "f_fcn", app_initializer->getComponentDatabase("ForcingFunction"), grid_geometry); time_integrator->registerBodyForceFunction(f_fcn); } // Set up visualization plot file writers. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); Pointer<LSiloDataWriter> silo_data_writer = app_initializer->getLSiloDataWriter(); if (uses_visit) { ib_initializer->registerLSiloDataWriter(silo_data_writer); time_integrator->registerVisItDataWriter(visit_data_writer); ib_method_ops->registerLSiloDataWriter(silo_data_writer); } // Initialize hierarchy configuration and data on all patches. time_integrator->initializePatchHierarchy(patch_hierarchy, gridding_algorithm); // Deallocate initialization objects. ib_method_ops->freeLInitStrategy(); ib_initializer.setNull(); app_initializer.setNull(); // Print the input database contents to the log file. plog << "Input database:\n"; input_db->printClassData(plog); // Setup data used to determine the accuracy of the computed solution. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); const Pointer<Variable<NDIM> > u_var = navier_stokes_integrator->getVelocityVariable(); const Pointer<VariableContext> u_ctx = navier_stokes_integrator->getCurrentContext(); const int u_idx = var_db->mapVariableAndContextToIndex(u_var, u_ctx); const int u_cloned_idx = var_db->registerClonedPatchDataIndex(u_var, u_idx); const Pointer<Variable<NDIM> > p_var = navier_stokes_integrator->getPressureVariable(); const Pointer<VariableContext> p_ctx = navier_stokes_integrator->getCurrentContext(); const int p_idx = var_db->mapVariableAndContextToIndex(p_var, p_ctx); const int p_cloned_idx = var_db->registerClonedPatchDataIndex(p_var, p_idx); visit_data_writer->registerPlotQuantity("P error", "SCALAR", p_cloned_idx); const int coarsest_ln = 0; const int finest_ln = patch_hierarchy->getFinestLevelNumber(); for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { patch_hierarchy->getPatchLevel(ln)->allocatePatchData(u_cloned_idx); patch_hierarchy->getPatchLevel(ln)->allocatePatchData(p_cloned_idx); } // Write out initial visualization data. int iteration_num = time_integrator->getIntegratorStep(); double loop_time = time_integrator->getIntegratorTime(); if (dump_viz_data && uses_visit) { pout << "\n\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); silo_data_writer->writePlotData(iteration_num, loop_time); } // Main time step loop. double loop_time_end = time_integrator->getEndTime(); double dt = 0.0; while (!MathUtilities<double>::equalEps(loop_time, loop_time_end) && time_integrator->stepsRemaining()) { iteration_num = time_integrator->getIntegratorStep(); loop_time = time_integrator->getIntegratorTime(); pout << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "At beginning of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; dt = time_integrator->getMaximumTimeStepSize(); time_integrator->advanceHierarchy(dt); loop_time += dt; pout << "\n"; pout << "At end of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "\n"; // At specified intervals, write visualization and restart files, // print out timer data, and store hierarchy data for post // processing. iteration_num += 1; const bool last_step = !time_integrator->stepsRemaining(); if (dump_viz_data && uses_visit && (iteration_num % viz_dump_interval == 0 || last_step)) { pout << "\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); silo_data_writer->writePlotData(iteration_num, loop_time); } if (dump_restart_data && (iteration_num % restart_dump_interval == 0 || last_step)) { pout << "\nWriting restart files...\n\n"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, iteration_num); } if (dump_timer_data && (iteration_num % timer_dump_interval == 0 || last_step)) { pout << "\nWriting timer data...\n\n"; TimerManager::getManager()->print(plog); } if (dump_postproc_data && (iteration_num % postproc_data_dump_interval == 0 || last_step)) { output_data(patch_hierarchy, navier_stokes_integrator, ib_method_ops->getLDataManager(), iteration_num, loop_time, postproc_data_dump_dirname); } // Compute velocity and pressure error norms. const int coarsest_ln = 0; const int finest_ln = patch_hierarchy->getFinestLevelNumber(); for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); if (!level->checkAllocated(u_cloned_idx)) level->allocatePatchData(u_cloned_idx); if (!level->checkAllocated(p_cloned_idx)) level->allocatePatchData(p_cloned_idx); } pout << "\n" << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n" << "Computing error norms.\n\n"; u_init->setDataOnPatchHierarchy(u_cloned_idx, u_var, patch_hierarchy, loop_time); p_init->setDataOnPatchHierarchy(p_cloned_idx, p_var, patch_hierarchy, loop_time - 0.5 * dt); HierarchyMathOps hier_math_ops("HierarchyMathOps", patch_hierarchy); hier_math_ops.setPatchHierarchy(patch_hierarchy); hier_math_ops.resetLevels(coarsest_ln, finest_ln); const int wgt_cc_idx = hier_math_ops.getCellWeightPatchDescriptorIndex(); const int wgt_sc_idx = hier_math_ops.getSideWeightPatchDescriptorIndex(); Pointer<CellVariable<NDIM, double> > u_cc_var = u_var; if (u_cc_var) { HierarchyCellDataOpsReal<NDIM, double> hier_cc_data_ops(patch_hierarchy, coarsest_ln, finest_ln); hier_cc_data_ops.subtract(u_cloned_idx, u_idx, u_cloned_idx); pout << "Error in u at time " << loop_time << ":\n" << " L1-norm: " << hier_cc_data_ops.L1Norm(u_cloned_idx, wgt_cc_idx) << "\n" << " L2-norm: " << hier_cc_data_ops.L2Norm(u_cloned_idx, wgt_cc_idx) << "\n" << " max-norm: " << hier_cc_data_ops.maxNorm(u_cloned_idx, wgt_cc_idx) << "\n"; } Pointer<SideVariable<NDIM, double> > u_sc_var = u_var; if (u_sc_var) { HierarchySideDataOpsReal<NDIM, double> hier_sc_data_ops(patch_hierarchy, coarsest_ln, finest_ln); hier_sc_data_ops.subtract(u_cloned_idx, u_idx, u_cloned_idx); pout << "Error in u at time " << loop_time << ":\n" << " L1-norm: " << hier_sc_data_ops.L1Norm(u_cloned_idx, wgt_sc_idx) << "\n" << " L2-norm: " << hier_sc_data_ops.L2Norm(u_cloned_idx, wgt_sc_idx) << "\n" << " max-norm: " << hier_sc_data_ops.maxNorm(u_cloned_idx, wgt_sc_idx) << "\n"; } HierarchyCellDataOpsReal<NDIM, double> hier_cc_data_ops(patch_hierarchy, coarsest_ln, finest_ln); hier_cc_data_ops.subtract(p_cloned_idx, p_idx, p_cloned_idx); pout << "Error in p at time " << loop_time - 0.5 * dt << ":\n" << " L1-norm: " << hier_cc_data_ops.L1Norm(p_cloned_idx, wgt_cc_idx) << "\n" << " L2-norm: " << hier_cc_data_ops.L2Norm(p_cloned_idx, wgt_cc_idx) << "\n" << " max-norm: " << hier_cc_data_ops.maxNorm(p_cloned_idx, wgt_cc_idx) << "\n" << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; } // Cleanup Eulerian boundary condition specification objects (when // necessary). for (unsigned int d = 0; d < NDIM; ++d) delete u_bc_coefs[d]; } // cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return 0; } // main
/******************************************************************************* * For each run, the input filename must be given on the command line. In all * * cases, the command line is: * * * * executable <input file name> * * * *******************************************************************************/ int main(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); { // cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "sc_poisson.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database. Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>( "StandardTagAndInitialize", NULL, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Create variables and register them with the variable database. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); Pointer<VariableContext> ctx = var_db->getContext("context"); Pointer<SideVariable<NDIM, double> > u_sc_var = new SideVariable<NDIM, double>("u_sc"); Pointer<SideVariable<NDIM, double> > f_sc_var = new SideVariable<NDIM, double>("f_sc"); Pointer<SideVariable<NDIM, double> > e_sc_var = new SideVariable<NDIM, double>("e_sc"); Pointer<SideVariable<NDIM, double> > r_sc_var = new SideVariable<NDIM, double>("r_sc"); const int u_sc_idx = var_db->registerVariableAndContext(u_sc_var, ctx, IntVector<NDIM>(1)); const int f_sc_idx = var_db->registerVariableAndContext(f_sc_var, ctx, IntVector<NDIM>(1)); const int e_sc_idx = var_db->registerVariableAndContext(e_sc_var, ctx, IntVector<NDIM>(1)); const int r_sc_idx = var_db->registerVariableAndContext(r_sc_var, ctx, IntVector<NDIM>(1)); Pointer<CellVariable<NDIM, double> > u_cc_var = new CellVariable<NDIM, double>("u_cc", NDIM); Pointer<CellVariable<NDIM, double> > f_cc_var = new CellVariable<NDIM, double>("f_cc", NDIM); Pointer<CellVariable<NDIM, double> > e_cc_var = new CellVariable<NDIM, double>("e_cc", NDIM); Pointer<CellVariable<NDIM, double> > r_cc_var = new CellVariable<NDIM, double>("r_cc", NDIM); const int u_cc_idx = var_db->registerVariableAndContext(u_cc_var, ctx, IntVector<NDIM>(0)); const int f_cc_idx = var_db->registerVariableAndContext(f_cc_var, ctx, IntVector<NDIM>(0)); const int e_cc_idx = var_db->registerVariableAndContext(e_cc_var, ctx, IntVector<NDIM>(0)); const int r_cc_idx = var_db->registerVariableAndContext(r_cc_var, ctx, IntVector<NDIM>(0)); // Register variables for plotting. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); TBOX_ASSERT(visit_data_writer); visit_data_writer->registerPlotQuantity(u_cc_var->getName(), "VECTOR", u_cc_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(u_cc_var->getName() + stream.str(), "SCALAR", u_cc_idx, d); } visit_data_writer->registerPlotQuantity(f_cc_var->getName(), "VECTOR", f_cc_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(f_cc_var->getName() + stream.str(), "SCALAR", f_cc_idx, d); } visit_data_writer->registerPlotQuantity(e_cc_var->getName(), "VECTOR", e_cc_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(e_cc_var->getName() + stream.str(), "SCALAR", e_cc_idx, d); } visit_data_writer->registerPlotQuantity(r_cc_var->getName(), "VECTOR", r_cc_idx); for (unsigned int d = 0; d < NDIM; ++d) { ostringstream stream; stream << d; visit_data_writer->registerPlotQuantity(r_cc_var->getName() + stream.str(), "SCALAR", r_cc_idx, d); } // Initialize the AMR patch hierarchy. gridding_algorithm->makeCoarsestLevel(patch_hierarchy, 0.0); int tag_buffer = 1; int level_number = 0; bool done = false; while (!done && (gridding_algorithm->levelCanBeRefined(level_number))) { gridding_algorithm->makeFinerLevel(patch_hierarchy, 0.0, 0.0, tag_buffer); done = !patch_hierarchy->finerLevelExists(level_number); ++level_number; } // Allocate data on each level of the patch hierarchy. for (int ln = 0; ln <= patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(u_sc_idx, 0.0); level->allocatePatchData(f_sc_idx, 0.0); level->allocatePatchData(e_sc_idx, 0.0); level->allocatePatchData(r_sc_idx, 0.0); level->allocatePatchData(u_cc_idx, 0.0); level->allocatePatchData(f_cc_idx, 0.0); level->allocatePatchData(e_cc_idx, 0.0); level->allocatePatchData(r_cc_idx, 0.0); } // Setup vector objects. HierarchyMathOps hier_math_ops("hier_math_ops", patch_hierarchy); const int h_sc_idx = hier_math_ops.getSideWeightPatchDescriptorIndex(); SAMRAIVectorReal<NDIM, double> u_vec("u", patch_hierarchy, 0, patch_hierarchy->getFinestLevelNumber()); SAMRAIVectorReal<NDIM, double> f_vec("f", patch_hierarchy, 0, patch_hierarchy->getFinestLevelNumber()); SAMRAIVectorReal<NDIM, double> e_vec("e", patch_hierarchy, 0, patch_hierarchy->getFinestLevelNumber()); SAMRAIVectorReal<NDIM, double> r_vec("r", patch_hierarchy, 0, patch_hierarchy->getFinestLevelNumber()); u_vec.addComponent(u_sc_var, u_sc_idx, h_sc_idx); f_vec.addComponent(f_sc_var, f_sc_idx, h_sc_idx); e_vec.addComponent(e_sc_var, e_sc_idx, h_sc_idx); r_vec.addComponent(r_sc_var, r_sc_idx, h_sc_idx); u_vec.setToScalar(0.0); f_vec.setToScalar(0.0); e_vec.setToScalar(0.0); r_vec.setToScalar(0.0); // Setup exact solutions. muParserCartGridFunction u_fcn("u", app_initializer->getComponentDatabase("u"), grid_geometry); muParserCartGridFunction f_fcn("f", app_initializer->getComponentDatabase("f"), grid_geometry); u_fcn.setDataOnPatchHierarchy(e_sc_idx, e_sc_var, patch_hierarchy, 0.0); f_fcn.setDataOnPatchHierarchy(f_sc_idx, f_sc_var, patch_hierarchy, 0.0); // Setup the Poisson solver. PoissonSpecifications poisson_spec("poisson_spec"); poisson_spec.setCConstant(0.0); poisson_spec.setDConstant(-1.0); vector<RobinBcCoefStrategy<NDIM>*> bc_coefs(NDIM, static_cast<RobinBcCoefStrategy<NDIM>*>(NULL)); SCLaplaceOperator laplace_op("laplace_op"); laplace_op.setPoissonSpecifications(poisson_spec); laplace_op.setPhysicalBcCoefs(bc_coefs); laplace_op.initializeOperatorState(u_vec, f_vec); string solver_type = input_db->getString("solver_type"); Pointer<Database> solver_db = input_db->getDatabase("solver_db"); string precond_type = input_db->getString("precond_type"); Pointer<Database> precond_db = input_db->getDatabase("precond_db"); Pointer<PoissonSolver> poisson_solver = SCPoissonSolverManager::getManager()->allocateSolver( solver_type, "poisson_solver", solver_db, "", precond_type, "poisson_precond", precond_db, ""); poisson_solver->setPoissonSpecifications(poisson_spec); poisson_solver->setPhysicalBcCoefs(bc_coefs); poisson_solver->initializeSolverState(u_vec, f_vec); // Solve -L*u = f. u_vec.setToScalar(0.0); poisson_solver->solveSystem(u_vec, f_vec); // Compute error and print error norms. e_vec.subtract(Pointer<SAMRAIVectorReal<NDIM, double> >(&e_vec, false), Pointer<SAMRAIVectorReal<NDIM, double> >(&u_vec, false)); pout << "|e|_oo = " << e_vec.maxNorm() << "\n"; pout << "|e|_2 = " << e_vec.L2Norm() << "\n"; pout << "|e|_1 = " << e_vec.L1Norm() << "\n"; // Compute the residual and print residual norms. laplace_op.apply(u_vec, r_vec); r_vec.subtract(Pointer<SAMRAIVectorReal<NDIM, double> >(&f_vec, false), Pointer<SAMRAIVectorReal<NDIM, double> >(&r_vec, false)); pout << "|r|_oo = " << r_vec.maxNorm() << "\n"; pout << "|r|_2 = " << r_vec.L2Norm() << "\n"; pout << "|r|_1 = " << r_vec.L1Norm() << "\n"; // Interpolate the side-centered data to cell centers for output. static const bool synch_cf_interface = true; hier_math_ops.interp(u_cc_idx, u_cc_var, u_sc_idx, u_sc_var, NULL, 0.0, synch_cf_interface); hier_math_ops.interp(f_cc_idx, f_cc_var, f_sc_idx, f_sc_var, NULL, 0.0, synch_cf_interface); hier_math_ops.interp(e_cc_idx, e_cc_var, e_sc_idx, e_sc_var, NULL, 0.0, synch_cf_interface); hier_math_ops.interp(r_cc_idx, r_cc_var, r_sc_idx, r_sc_var, NULL, 0.0, synch_cf_interface); // Set invalid values on coarse levels (i.e., coarse-grid values that // are covered by finer grid patches) to equal zero. for (int ln = 0; ln <= patch_hierarchy->getFinestLevelNumber() - 1; ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); BoxArray<NDIM> refined_region_boxes; Pointer<PatchLevel<NDIM> > next_finer_level = patch_hierarchy->getPatchLevel(ln + 1); refined_region_boxes = next_finer_level->getBoxes(); refined_region_boxes.coarsen(next_finer_level->getRatioToCoarserLevel()); for (PatchLevel<NDIM>::Iterator p(level); p; p++) { Pointer<Patch<NDIM> > patch = level->getPatch(p()); const Box<NDIM>& patch_box = patch->getBox(); Pointer<CellData<NDIM, double> > e_cc_data = patch->getPatchData(e_cc_idx); Pointer<CellData<NDIM, double> > r_cc_data = patch->getPatchData(r_cc_idx); for (int i = 0; i < refined_region_boxes.getNumberOfBoxes(); ++i) { const Box<NDIM> refined_box = refined_region_boxes[i]; const Box<NDIM> intersection = Box<NDIM>::grow(patch_box, 1) * refined_box; if (!intersection.empty()) { e_cc_data->fillAll(0.0, intersection); r_cc_data->fillAll(0.0, intersection); } } } } // Output data for plotting. visit_data_writer->writePlotData(patch_hierarchy, 0, 0.0); } // cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return 0; } // main
/******************************************************************************* * For each run, the input filename and restart information (if needed) must * * be given on the command line. For non-restarted case, command line is: * * * * executable <input file name> * * * * For restarted run, command line is: * * * * executable <input file name> <restart directory> <restart number> * * * *******************************************************************************/ int main( int argc, char *argv[]) { // Initialize MPI and SAMRAI. SAMRAI_MPI::init(&argc, &argv); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); {// cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, initialize the restart database (if this is a restarted run), // and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "advect.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); Pointer<Database> main_db = app_initializer->getComponentDatabase("Main"); // Get various standard options set in the input file. const bool dump_viz_data = app_initializer->dumpVizData(); const int viz_dump_interval = app_initializer->getVizDumpInterval(); const bool uses_visit = dump_viz_data && app_initializer->getVisItDataWriter(); const bool dump_restart_data = app_initializer->dumpRestartData(); const int restart_dump_interval = app_initializer->getRestartDumpInterval(); const string restart_dump_dirname = app_initializer->getRestartDumpDirectory(); const bool dump_timer_data = app_initializer->dumpTimerData(); const int timer_dump_interval = app_initializer->getTimerDumpInterval(); // Get solver configuration options. bool using_refined_timestepping = false; if (main_db->keyExists("timestepping")) { string timestepping_method = main_db->getString("timestepping"); if (timestepping_method == "SYNCHRONIZED") { using_refined_timestepping = false; } else { using_refined_timestepping = true; } } if (using_refined_timestepping) { pout << "using subcycled timestepping.\n"; } else { pout << "NOT using subcycled timestepping.\n"; } // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database // and, if this is a restarted run, from the restart database. Pointer<AdvectorExplicitPredictorStrategy> explicit_predictor = new AdvectorExplicitPredictorStrategy( "AdvectorExplicitPredictorStrategy", app_initializer->getComponentDatabase("AdvectorExplicitPredictorStrategy")); Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<AdvectorPredictorCorrectorHyperbolicPatchOps> hyp_patch_ops = new AdvectorPredictorCorrectorHyperbolicPatchOps( "AdvectorPredictorCorrectorHyperbolicPatchOps", app_initializer->getComponentDatabase("AdvectorPredictorCorrectorHyperbolicPatchOps"), explicit_predictor, grid_geometry); Pointer<HyperbolicLevelIntegrator<NDIM> > hyp_level_integrator = new HyperbolicLevelIntegrator<NDIM>( "HyperbolicLevelIntegrator", app_initializer->getComponentDatabase("HyperbolicLevelIntegrator"), hyp_patch_ops, true, using_refined_timestepping); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>( "PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>( "StandardTagAndInitialize", hyp_level_integrator, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>( "LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>( "GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); Pointer<TimeRefinementIntegrator<NDIM> > time_integrator = new TimeRefinementIntegrator<NDIM>( "TimeRefinementIntegrator", app_initializer->getComponentDatabase("TimeRefinementIntegrator"), patch_hierarchy, hyp_level_integrator, gridding_algorithm); // Setup the advection velocity. const bool u_is_div_free = main_db->getBoolWithDefault("u_is_div_free", false); if (u_is_div_free) { pout << "advection velocity u is discretely divergence free.\n"; } else { pout << "advection velocity u is NOT discretely divergence free.\n"; } Pointer<FaceVariable<NDIM,double> > u_var = new FaceVariable<NDIM,double>("u"); UFunction u_fcn("UFunction", grid_geometry, app_initializer->getComponentDatabase("UFunction")); hyp_patch_ops->registerAdvectionVelocity(u_var); hyp_patch_ops->setAdvectionVelocityIsDivergenceFree(u_var, u_is_div_free); hyp_patch_ops->setAdvectionVelocityFunction(u_var, Pointer<CartGridFunction>(&u_fcn,false)); // Setup the advected quantity. const ConvectiveDifferencingType difference_form = IBAMR::string_to_enum<ConvectiveDifferencingType>( main_db->getStringWithDefault( "difference_form", IBAMR::enum_to_string<ConvectiveDifferencingType>(ADVECTIVE))); pout << "solving the advection equation in " << enum_to_string<ConvectiveDifferencingType>(difference_form) << " form.\n"; Pointer<CellVariable<NDIM,double> > Q_var = new CellVariable<NDIM,double>("Q"); QInit Q_init("QInit", grid_geometry, app_initializer->getComponentDatabase("QInit")); LocationIndexRobinBcCoefs<NDIM> physical_bc_coef( "physical_bc_coef", app_initializer->getComponentDatabase("LocationIndexRobinBcCoefs")); hyp_patch_ops->registerTransportedQuantity(Q_var); hyp_patch_ops->setAdvectionVelocity(Q_var, u_var); hyp_patch_ops->setConvectiveDifferencingType(Q_var, difference_form); hyp_patch_ops->setInitialConditions(Q_var, Pointer<CartGridFunction>(&Q_init,false)); hyp_patch_ops->setPhysicalBcCoefs(Q_var, &physical_bc_coef); // Set up visualization plot file writer. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); if (uses_visit) hyp_patch_ops->registerVisItDataWriter(visit_data_writer); // Initialize hierarchy configuration and data on all patches. double dt_now = time_integrator->initializeHierarchy(); // Deallocate initialization objects. app_initializer.setNull(); // Print the input database contents to the log file. plog << "Input database:\n"; input_db->printClassData(plog); // Write out initial visualization data. int iteration_num = time_integrator->getIntegratorStep(); double loop_time = time_integrator->getIntegratorTime(); if (dump_viz_data && uses_visit) { pout << "\n\nWriting visualization files...\n\n"; visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } // Main time step loop. double loop_time_end = time_integrator->getEndTime(); while (!MathUtilities<double>::equalEps(loop_time,loop_time_end) && time_integrator->stepsRemaining()) { iteration_num = time_integrator->getIntegratorStep(); loop_time = time_integrator->getIntegratorTime(); pout << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "At beginning of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; double dt_new = time_integrator->advanceHierarchy(dt_now); loop_time += dt_now; dt_now = dt_new; pout << "\n"; pout << "At end of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "\n"; // At specified intervals, write visualization and restart files, // and print out timer data. iteration_num += 1; const bool last_step = !time_integrator->stepsRemaining(); if (dump_viz_data && uses_visit && (iteration_num%viz_dump_interval == 0 || last_step)) { pout << "\nWriting visualization files...\n\n"; visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } if (dump_restart_data && (iteration_num%restart_dump_interval == 0 || last_step)) { pout << "\nWriting restart files...\n\nn"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, iteration_num); } if (dump_timer_data && (iteration_num%timer_dump_interval == 0 || last_step)) { pout << "\nWriting timer data...\n\n"; TimerManager::getManager()->print(plog); } } // Determine the accuracy of the computed solution. pout << "\n" << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n" << "Computing error norms.\n\n"; VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); const Pointer<VariableContext> Q_ctx = hyp_level_integrator->getCurrentContext(); const int Q_idx = var_db->mapVariableAndContextToIndex(Q_var, Q_ctx); const int Q_cloned_idx = var_db->registerClonedPatchDataIndex(Q_var, Q_idx); const int coarsest_ln = 0; const int finest_ln = patch_hierarchy->getFinestLevelNumber(); for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { patch_hierarchy->getPatchLevel(ln)->allocatePatchData(Q_cloned_idx, loop_time); } Q_init.setDataOnPatchHierarchy(Q_cloned_idx, Q_var, patch_hierarchy, loop_time); HierarchyMathOps hier_math_ops("HierarchyMathOps", patch_hierarchy); hier_math_ops.setPatchHierarchy(patch_hierarchy); hier_math_ops.resetLevels(coarsest_ln, finest_ln); const int wgt_idx = hier_math_ops.getCellWeightPatchDescriptorIndex(); HierarchyCellDataOpsReal<NDIM,double> hier_cc_data_ops(patch_hierarchy, coarsest_ln, finest_ln); hier_cc_data_ops.subtract(Q_idx, Q_idx, Q_cloned_idx); pout << "Error in " << Q_var->getName() << " at time " << loop_time << ":\n" << " L1-norm: " << hier_cc_data_ops.L1Norm(Q_idx,wgt_idx) << "\n" << " L2-norm: " << hier_cc_data_ops.L2Norm(Q_idx,wgt_idx) << "\n" << " max-norm: " << hier_cc_data_ops.maxNorm(Q_idx,wgt_idx) << "\n" << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; if (dump_viz_data && uses_visit) { visit_data_writer->writePlotData(patch_hierarchy, iteration_num+1, loop_time); } }// cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); SAMRAI_MPI::finalize(); return 0; }// main
/******************************************************************************* * For each run, the input filename must be given on the command line. In all * * cases, the command line is: * * * * executable <input file name> [PETSc options] * * * *******************************************************************************/ int main(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); // Parse command line options, set some standard options from the input // file, and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "INS.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Retrieve "Main" section of the input database. Pointer<Database> main_db = app_initializer->getComponentDatabase("Main"); int coarse_hier_dump_interval = 0; int fine_hier_dump_interval = 0; if (main_db->keyExists("hier_dump_interval")) { coarse_hier_dump_interval = main_db->getInteger("hier_dump_interval"); fine_hier_dump_interval = main_db->getInteger("hier_dump_interval"); } else if (main_db->keyExists("coarse_hier_dump_interval") && main_db->keyExists("fine_hier_dump_interval")) { coarse_hier_dump_interval = main_db->getInteger("coarse_hier_dump_interval"); fine_hier_dump_interval = main_db->getInteger("fine_hier_dump_interval"); } else { TBOX_ERROR("hierarchy dump intervals not specified in input file. . .\n"); } string coarse_hier_dump_dirname; if (main_db->keyExists("coarse_hier_dump_dirname")) { coarse_hier_dump_dirname = main_db->getString("coarse_hier_dump_dirname"); } else { TBOX_ERROR("key `coarse_hier_dump_dirname' not specified in input file"); } string fine_hier_dump_dirname; if (main_db->keyExists("fine_hier_dump_dirname")) { fine_hier_dump_dirname = main_db->getString("fine_hier_dump_dirname"); } else { TBOX_ERROR("key `fine_hier_dump_dirname' not specified in input file"); } // Create major algorithm and data objects that comprise application. Pointer<CartesianGridGeometry<NDIM> > grid_geom = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); // Initialize variables. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); Pointer<VariableContext> current_ctx = var_db->getContext("INSStaggeredHierarchyIntegrator::CURRENT"); Pointer<VariableContext> scratch_ctx = var_db->getContext("INSStaggeredHierarchyIntegrator::SCRATCH"); Pointer<SideVariable<NDIM, double> > U_var = new SideVariable<NDIM, double>("INSStaggeredHierarchyIntegrator::U"); const int U_idx = var_db->registerVariableAndContext(U_var, current_ctx); const int U_interp_idx = var_db->registerClonedPatchDataIndex(U_var, U_idx); const int U_scratch_idx = var_db->registerVariableAndContext(U_var, scratch_ctx, 2); Pointer<CellVariable<NDIM, double> > P_var = new CellVariable<NDIM, double>("INSStaggeredHierarchyIntegrator::P"); const int P_idx = var_db->registerVariableAndContext(P_var, current_ctx); const int P_interp_idx = var_db->registerClonedPatchDataIndex(P_var, P_idx); const int P_scratch_idx = var_db->registerVariableAndContext(P_var, scratch_ctx, 2); // Set up visualization plot file writer. Pointer<VisItDataWriter<NDIM> > visit_data_writer = new VisItDataWriter<NDIM>("VisIt Writer", main_db->getString("viz_dump_dirname"), 1); visit_data_writer->registerPlotQuantity("P", "SCALAR", P_idx); visit_data_writer->registerPlotQuantity("P interp", "SCALAR", P_interp_idx); // Time step loop. double loop_time = 0.0; int coarse_iteration_num = coarse_hier_dump_interval; int fine_iteration_num = fine_hier_dump_interval; bool files_exist = true; for (; files_exist; coarse_iteration_num += coarse_hier_dump_interval, fine_iteration_num += fine_hier_dump_interval) { char temp_buf[128]; sprintf(temp_buf, "%05d.samrai.%05d", coarse_iteration_num, SAMRAI_MPI::getRank()); string coarse_file_name = coarse_hier_dump_dirname + "/" + "hier_data."; coarse_file_name += temp_buf; sprintf(temp_buf, "%05d.samrai.%05d", fine_iteration_num, SAMRAI_MPI::getRank()); string fine_file_name = fine_hier_dump_dirname + "/" + "hier_data."; fine_file_name += temp_buf; for (int rank = 0; rank < SAMRAI_MPI::getNodes(); ++rank) { if (rank == SAMRAI_MPI::getRank()) { fstream coarse_fin, fine_fin; coarse_fin.open(coarse_file_name.c_str(), ios::in); fine_fin.open(fine_file_name.c_str(), ios::in); if (!coarse_fin.is_open() || !fine_fin.is_open()) { files_exist = false; } coarse_fin.close(); fine_fin.close(); } SAMRAI_MPI::barrier(); } if (!files_exist) break; pout << endl; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; pout << "processing data" << endl; pout << " coarse iteration number = " << coarse_iteration_num << endl; pout << " fine iteration number = " << fine_iteration_num << endl; pout << " coarse file name = " << coarse_file_name << endl; pout << " fine file name = " << fine_file_name << endl; // Read in data to post-process. ComponentSelector hier_data; hier_data.setFlag(U_idx); hier_data.setFlag(P_idx); Pointer<HDFDatabase> coarse_hier_db = new HDFDatabase("coarse_hier_db"); coarse_hier_db->open(coarse_file_name); Pointer<PatchHierarchy<NDIM> > coarse_patch_hierarchy = new PatchHierarchy<NDIM>("CoarsePatchHierarchy", grid_geom, false); coarse_patch_hierarchy->getFromDatabase(coarse_hier_db->getDatabase("PatchHierarchy"), hier_data); const double coarse_loop_time = coarse_hier_db->getDouble("loop_time"); coarse_hier_db->close(); Pointer<HDFDatabase> fine_hier_db = new HDFDatabase("fine_hier_db"); fine_hier_db->open(fine_file_name); Pointer<PatchHierarchy<NDIM> > fine_patch_hierarchy = new PatchHierarchy<NDIM>( "FinePatchHierarchy", grid_geom->makeRefinedGridGeometry("FineGridGeometry", 2, false), false); fine_patch_hierarchy->getFromDatabase(fine_hier_db->getDatabase("PatchHierarchy"), hier_data); const double fine_loop_time = fine_hier_db->getDouble("loop_time"); fine_hier_db->close(); TBOX_ASSERT(MathUtilities<double>::equalEps(coarse_loop_time, fine_loop_time)); loop_time = fine_loop_time; pout << " loop time = " << loop_time << endl; Pointer<PatchHierarchy<NDIM> > coarsened_fine_patch_hierarchy = fine_patch_hierarchy->makeCoarsenedPatchHierarchy("CoarsenedFinePatchHierarchy", 2, false); // Setup hierarchy operations objects. HierarchyCellDataOpsReal<NDIM, double> coarse_hier_cc_data_ops( coarse_patch_hierarchy, 0, coarse_patch_hierarchy->getFinestLevelNumber()); HierarchySideDataOpsReal<NDIM, double> coarse_hier_sc_data_ops( coarse_patch_hierarchy, 0, coarse_patch_hierarchy->getFinestLevelNumber()); HierarchyMathOps hier_math_ops("hier_math_ops", coarse_patch_hierarchy); hier_math_ops.setPatchHierarchy(coarse_patch_hierarchy); hier_math_ops.resetLevels(0, coarse_patch_hierarchy->getFinestLevelNumber()); const int wgt_cc_idx = hier_math_ops.getCellWeightPatchDescriptorIndex(); const int wgt_sc_idx = hier_math_ops.getSideWeightPatchDescriptorIndex(); // Allocate patch data. for (int ln = 0; ln <= coarse_patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > level = coarse_patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(U_interp_idx, loop_time); level->allocatePatchData(P_interp_idx, loop_time); level->allocatePatchData(U_scratch_idx, loop_time); level->allocatePatchData(P_scratch_idx, loop_time); } for (int ln = 0; ln <= fine_patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > level = fine_patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(U_interp_idx, loop_time); level->allocatePatchData(P_interp_idx, loop_time); level->allocatePatchData(U_scratch_idx, loop_time); level->allocatePatchData(P_scratch_idx, loop_time); } for (int ln = 0; ln <= coarsened_fine_patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > level = coarsened_fine_patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(U_idx, loop_time); level->allocatePatchData(P_idx, loop_time); level->allocatePatchData(U_interp_idx, loop_time); level->allocatePatchData(P_interp_idx, loop_time); level->allocatePatchData(U_scratch_idx, loop_time); level->allocatePatchData(P_scratch_idx, loop_time); } // Synchronize the coarse hierarchy data. for (int ln = coarse_patch_hierarchy->getFinestLevelNumber(); ln > 0; --ln) { Pointer<PatchLevel<NDIM> > coarser_level = coarse_patch_hierarchy->getPatchLevel(ln - 1); Pointer<PatchLevel<NDIM> > finer_level = coarse_patch_hierarchy->getPatchLevel(ln); CoarsenAlgorithm<NDIM> coarsen_alg; Pointer<CoarsenOperator<NDIM> > coarsen_op; coarsen_op = grid_geom->lookupCoarsenOperator(U_var, "CONSERVATIVE_COARSEN"); coarsen_alg.registerCoarsen(U_idx, U_idx, coarsen_op); coarsen_op = grid_geom->lookupCoarsenOperator(P_var, "CONSERVATIVE_COARSEN"); coarsen_alg.registerCoarsen(P_idx, P_idx, coarsen_op); coarsen_alg.createSchedule(coarser_level, finer_level)->coarsenData(); } // Synchronize the fine hierarchy data. for (int ln = fine_patch_hierarchy->getFinestLevelNumber(); ln > 0; --ln) { Pointer<PatchLevel<NDIM> > coarser_level = fine_patch_hierarchy->getPatchLevel(ln - 1); Pointer<PatchLevel<NDIM> > finer_level = fine_patch_hierarchy->getPatchLevel(ln); CoarsenAlgorithm<NDIM> coarsen_alg; Pointer<CoarsenOperator<NDIM> > coarsen_op; coarsen_op = grid_geom->lookupCoarsenOperator(U_var, "CONSERVATIVE_COARSEN"); coarsen_alg.registerCoarsen(U_idx, U_idx, coarsen_op); coarsen_op = grid_geom->lookupCoarsenOperator(P_var, "CONSERVATIVE_COARSEN"); coarsen_alg.registerCoarsen(P_idx, P_idx, coarsen_op); coarsen_alg.createSchedule(coarser_level, finer_level)->coarsenData(); } // Coarsen data from the fine hierarchy to the coarsened fine hierarchy. for (int ln = 0; ln <= fine_patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > dst_level = coarsened_fine_patch_hierarchy->getPatchLevel(ln); Pointer<PatchLevel<NDIM> > src_level = fine_patch_hierarchy->getPatchLevel(ln); Pointer<CoarsenOperator<NDIM> > coarsen_op; for (PatchLevel<NDIM>::Iterator p(dst_level); p; p++) { Pointer<Patch<NDIM> > dst_patch = dst_level->getPatch(p()); Pointer<Patch<NDIM> > src_patch = src_level->getPatch(p()); const Box<NDIM>& coarse_box = dst_patch->getBox(); TBOX_ASSERT(Box<NDIM>::coarsen(src_patch->getBox(), 2) == coarse_box); coarsen_op = grid_geom->lookupCoarsenOperator(U_var, "CONSERVATIVE_COARSEN"); coarsen_op->coarsen(*dst_patch, *src_patch, U_interp_idx, U_idx, coarse_box, 2); coarsen_op = grid_geom->lookupCoarsenOperator(P_var, "CONSERVATIVE_COARSEN"); coarsen_op->coarsen(*dst_patch, *src_patch, P_interp_idx, P_idx, coarse_box, 2); } } // Interpolate and copy data from the coarsened fine patch hierarchy to // the coarse patch hierarchy. for (int ln = 0; ln <= coarse_patch_hierarchy->getFinestLevelNumber(); ++ln) { Pointer<PatchLevel<NDIM> > dst_level = coarse_patch_hierarchy->getPatchLevel(ln); Pointer<PatchLevel<NDIM> > src_level = coarsened_fine_patch_hierarchy->getPatchLevel(ln); RefineAlgorithm<NDIM> refine_alg; Pointer<RefineOperator<NDIM> > refine_op; refine_op = grid_geom->lookupRefineOperator(U_var, "CONSERVATIVE_LINEAR_REFINE"); refine_alg.registerRefine(U_interp_idx, U_interp_idx, U_scratch_idx, refine_op); refine_op = grid_geom->lookupRefineOperator(P_var, "LINEAR_REFINE"); refine_alg.registerRefine(P_interp_idx, P_interp_idx, P_scratch_idx, refine_op); ComponentSelector data_indices; data_indices.setFlag(U_scratch_idx); data_indices.setFlag(P_scratch_idx); CartExtrapPhysBdryOp bc_helper(data_indices, "LINEAR"); refine_alg.createSchedule(dst_level, src_level, ln - 1, coarse_patch_hierarchy, &bc_helper) ->fillData(loop_time); } // Output plot data before taking norms of differences. visit_data_writer->writePlotData(coarse_patch_hierarchy, coarse_iteration_num, loop_time); // Compute norms of differences. coarse_hier_sc_data_ops.subtract(U_interp_idx, U_idx, U_interp_idx); coarse_hier_cc_data_ops.subtract(P_interp_idx, P_idx, P_interp_idx); pout << "\n" << "Error in " << U_var->getName() << " at time " << loop_time << ":\n" << " L1-norm: " << coarse_hier_sc_data_ops.L1Norm(U_interp_idx, wgt_sc_idx) << "\n" << " L2-norm: " << coarse_hier_sc_data_ops.L2Norm(U_interp_idx, wgt_sc_idx) << "\n" << " max-norm: " << coarse_hier_sc_data_ops.maxNorm(U_interp_idx, wgt_sc_idx) << "\n"; pout << "\n" << "Error in " << P_var->getName() << " at time " << loop_time << ":\n" << " L1-norm: " << coarse_hier_cc_data_ops.L1Norm(P_interp_idx, wgt_cc_idx) << "\n" << " L2-norm: " << coarse_hier_cc_data_ops.L2Norm(P_interp_idx, wgt_cc_idx) << "\n" << " max-norm: " << coarse_hier_cc_data_ops.maxNorm(P_interp_idx, wgt_cc_idx) << "\n"; // Output plot data after taking norms of differences. visit_data_writer->writePlotData(coarse_patch_hierarchy, coarse_iteration_num + 1, loop_time); pout << endl; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; pout << endl; } SAMRAIManager::shutdown(); SAMRAI_MPI::finalize(); return 0; } // main
/******************************************************************************* * For each run, the input filename and restart information (if needed) must * * be given on the command line. For non-restarted case, command line is: * * * * executable <input file name> * * * * For restarted run, command line is: * * * * executable <input file name> <restart directory> <restart number> * * * *******************************************************************************/ int main( int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc,&argv,NULL,NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); {// cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, initialize the restart database (if this is a restarted run), // and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "adv_diff.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Get various standard options set in the input file. const bool dump_viz_data = app_initializer->dumpVizData(); const int viz_dump_interval = app_initializer->getVizDumpInterval(); const bool uses_visit = dump_viz_data && app_initializer->getVisItDataWriter(); const bool dump_restart_data = app_initializer->dumpRestartData(); const int restart_dump_interval = app_initializer->getRestartDumpInterval(); const string restart_dump_dirname = app_initializer->getRestartDumpDirectory(); const bool dump_timer_data = app_initializer->dumpTimerData(); const int timer_dump_interval = app_initializer->getTimerDumpInterval(); Pointer<Database> main_db = app_initializer->getComponentDatabase("Main"); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database // and, if this is a restarted run, from the restart database. Pointer<AdvDiffHierarchyIntegrator> time_integrator; const string solver_type = main_db->getStringWithDefault("solver_type", "GODUNOV"); if (solver_type == "GODUNOV") { Pointer<AdvectorExplicitPredictorPatchOps> predictor = new AdvectorExplicitPredictorPatchOps("AdvectorExplicitPredictorPatchOps", app_initializer->getComponentDatabase("AdvectorExplicitPredictorPatchOps")); time_integrator = new AdvDiffPredictorCorrectorHierarchyIntegrator("AdvDiffPredictorCorrectorHierarchyIntegrator", app_initializer->getComponentDatabase("AdvDiffPredictorCorrectorHierarchyIntegrator"), predictor); } else if (solver_type == "SEMI_IMPLICIT") { time_integrator = new AdvDiffSemiImplicitHierarchyIntegrator("AdvDiffSemiImplicitHierarchyIntegrator", app_initializer->getComponentDatabase("AdvDiffSemiImplicitHierarchyIntegrator")); } else { TBOX_ERROR("Unsupported solver type: " << solver_type << "\n" << "Valid options are: GODUNOV, SEMI_IMPLICIT"); } Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>("CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>("StandardTagAndInitialize", time_integrator, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Create an initial condition specification object. Pointer<CartGridFunction> u_init = new muParserCartGridFunction("u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); // Create boundary condition specification objects (when necessary). const IntVector<NDIM>& periodic_shift = grid_geometry->getPeriodicShift(); vector<RobinBcCoefStrategy<NDIM>*> u_bc_coefs(NDIM); if (periodic_shift.min() > 0) { for (unsigned int d = 0; d < NDIM; ++d) { u_bc_coefs[d] = NULL; } } else { for (unsigned int d = 0; d < NDIM; ++d) { ostringstream bc_coefs_name_stream; bc_coefs_name_stream << "u_bc_coefs_" << d; const string bc_coefs_name = bc_coefs_name_stream.str(); ostringstream bc_coefs_db_name_stream; bc_coefs_db_name_stream << "VelocityBcCoefs_" << d; const string bc_coefs_db_name = bc_coefs_db_name_stream.str(); u_bc_coefs[d] = new muParserRobinBcCoefs(bc_coefs_name, app_initializer->getComponentDatabase(bc_coefs_db_name), grid_geometry); } } // Set up the advected and diffused quantity. Pointer<CellVariable<NDIM,double> > U_var = new CellVariable<NDIM,double>("U",NDIM); time_integrator->registerTransportedQuantity(U_var); time_integrator->setDiffusionCoefficient(U_var, input_db->getDouble("MU")/input_db->getDouble("RHO")); time_integrator->setInitialConditions(U_var, u_init); time_integrator->setPhysicalBcCoefs(U_var, u_bc_coefs); Pointer<FaceVariable<NDIM,double> > u_adv_var = new FaceVariable<NDIM,double>("u_adv"); time_integrator->registerAdvectionVelocity(u_adv_var); time_integrator->setAdvectionVelocityFunction(u_adv_var, u_init); time_integrator->setAdvectionVelocity(U_var, u_adv_var); if (input_db->keyExists("ForcingFunction")) { Pointer<CellVariable<NDIM,double> > F_var = new CellVariable<NDIM,double>("F",NDIM); Pointer<CartGridFunction> F_fcn = new muParserCartGridFunction("F_fcn", app_initializer->getComponentDatabase("ForcingFunction"), grid_geometry); time_integrator->registerSourceTerm(F_var); time_integrator->setSourceTermFunction(F_var, F_fcn); time_integrator->setSourceTerm(U_var, F_var); } // Set up visualization plot file writers. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); if (uses_visit) { time_integrator->registerVisItDataWriter(visit_data_writer); } // Initialize hierarchy configuration and data on all patches. time_integrator->initializePatchHierarchy(patch_hierarchy, gridding_algorithm); // Deallocate initialization objects. app_initializer.setNull(); // Print the input database contents to the log file. plog << "Input database:\n"; input_db->printClassData(plog); // Write out initial visualization data. int iteration_num = time_integrator->getIntegratorStep(); double loop_time = time_integrator->getIntegratorTime(); if (dump_viz_data && uses_visit) { pout << "\n\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } // Main time step loop. double loop_time_end = time_integrator->getEndTime(); double dt = 0.0; while (!MathUtilities<double>::equalEps(loop_time,loop_time_end) && time_integrator->stepsRemaining()) { iteration_num = time_integrator->getIntegratorStep(); loop_time = time_integrator->getIntegratorTime(); pout << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "At beginning of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; dt = time_integrator->getMaximumTimeStepSize(); time_integrator->advanceHierarchy(dt); loop_time += dt; pout << "\n"; pout << "At end of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "\n"; // At specified intervals, write visualization and restart files, // print out timer data, and store hierarchy data for post // processing. iteration_num += 1; const bool last_step = !time_integrator->stepsRemaining(); if (dump_viz_data && uses_visit && (iteration_num%viz_dump_interval == 0 || last_step)) { pout << "\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } if (dump_restart_data && (iteration_num%restart_dump_interval == 0 || last_step)) { pout << "\nWriting restart files...\n\n"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, iteration_num); } if (dump_timer_data && (iteration_num%timer_dump_interval == 0 || last_step)) { pout << "\nWriting timer data...\n\n"; TimerManager::getManager()->print(plog); } } // Determine the accuracy of the computed solution. pout << "\n" << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n" << "Computing error norms.\n\n"; VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); const Pointer<VariableContext> U_ctx = time_integrator->getCurrentContext(); const int U_idx = var_db->mapVariableAndContextToIndex(U_var, U_ctx); const int U_cloned_idx = var_db->registerClonedPatchDataIndex(U_var, U_idx); const int coarsest_ln = 0; const int finest_ln = patch_hierarchy->getFinestLevelNumber(); for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { patch_hierarchy->getPatchLevel(ln)->allocatePatchData(U_cloned_idx, loop_time); } u_init->setDataOnPatchHierarchy(U_cloned_idx, U_var, patch_hierarchy, loop_time); HierarchyMathOps hier_math_ops("HierarchyMathOps", patch_hierarchy); hier_math_ops.setPatchHierarchy(patch_hierarchy); hier_math_ops.resetLevels(coarsest_ln, finest_ln); const int wgt_cc_idx = hier_math_ops.getCellWeightPatchDescriptorIndex(); HierarchyCellDataOpsReal<NDIM,double> hier_cc_data_ops(patch_hierarchy, coarsest_ln, finest_ln); hier_cc_data_ops.subtract(U_idx, U_idx, U_cloned_idx); pout << "Error in U at time " << loop_time << ":\n" << " L1-norm: " << hier_cc_data_ops. L1Norm(U_idx,wgt_cc_idx) << "\n" << " L2-norm: " << hier_cc_data_ops. L2Norm(U_idx,wgt_cc_idx) << "\n" << " max-norm: " << hier_cc_data_ops.maxNorm(U_idx,wgt_cc_idx) << "\n"; if (dump_viz_data && uses_visit) { time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num+1, loop_time); } // Cleanup boundary condition specification objects (when necessary). for (unsigned int d = 0; d < NDIM; ++d) delete u_bc_coefs[d]; }// cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return 0; }// main
/******************************************************************************* * For each run, the input filename must be given on the command line. In all * * cases, the command line is: * * * * executable <input file name> * * * *******************************************************************************/ bool run_example(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); // Since SAMRAI and PETSc both require finalization routines we have to // ensure that no SAMRAI or PETSc objects are active at the point where we // call SAMRAIManager::shutdown() or PetscFinalize. Hence, to guarantee // that all objects are cleaned up by that point, we put everything we use // in an inner scope. { // Parse command line options, set some standard options from the input // file, and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "cc_laplace.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input // database. Nearly all SAMRAI applications (at least those in IBAMR) // start by setting up the same half-dozen objects. Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>( "StandardTagAndInitialize", NULL, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Create variables and register them with the variable database. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); Pointer<VariableContext> ctx = var_db->getContext("context"); // We create a variable for every vector we ultimately declare, // instead of creating and then cloning vectors. The rationale for // this is given below. Pointer<CellVariable<NDIM, double> > u_cc_var = new CellVariable<NDIM, double>("u_cc"); Pointer<CellVariable<NDIM, double> > f_cc_var = new CellVariable<NDIM, double>("f_cc"); Pointer<CellVariable<NDIM, double> > e_cc_var = new CellVariable<NDIM, double>("e_cc"); Pointer<CellVariable<NDIM, double> > f_approx_cc_var = new CellVariable<NDIM, double>("f_approx_cc"); // Internally, SAMRAI keeps track of variables (and their // corresponding vectors, data, etc.) by converting them to // indices. Here we get the indices after notifying the variable // database about them. const int u_cc_idx = var_db->registerVariableAndContext(u_cc_var, ctx, IntVector<NDIM>(1)); const int f_cc_idx = var_db->registerVariableAndContext(f_cc_var, ctx, IntVector<NDIM>(1)); const int e_cc_idx = var_db->registerVariableAndContext(e_cc_var, ctx, IntVector<NDIM>(1)); const int f_approx_cc_idx = var_db->registerVariableAndContext(f_approx_cc_var, ctx, IntVector<NDIM>(1)); // Register variables for plotting. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); TBOX_ASSERT(visit_data_writer); visit_data_writer->registerPlotQuantity(u_cc_var->getName(), "SCALAR", u_cc_idx); visit_data_writer->registerPlotQuantity(f_cc_var->getName(), "SCALAR", f_cc_idx); visit_data_writer->registerPlotQuantity(f_approx_cc_var->getName(), "SCALAR", f_approx_cc_idx); visit_data_writer->registerPlotQuantity(e_cc_var->getName(), "SCALAR", e_cc_idx); // Initialize the AMR patch hierarchy. This sets up the coarsest level // (level 0) as well as any other levels specified in the input // file. We normally use the value tag_buffer to specify the number of // cells between a patch on level N and a patch on level N - 2: // however, SAMRAI ignores this value when setting up a hierarchy from // an input file so we just set it to an invalid value. gridding_algorithm->makeCoarsestLevel(patch_hierarchy, 0.0); const int tag_buffer = std::numeric_limits<int>::max(); int level_number = 0; while ((gridding_algorithm->levelCanBeRefined(level_number))) { gridding_algorithm->makeFinerLevel(patch_hierarchy, 0.0, 0.0, tag_buffer); ++level_number; } const int finest_level = patch_hierarchy->getFinestLevelNumber(); // Allocate data for each variable on each level of the patch // hierarchy. for (int ln = 0; ln <= finest_level; ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); level->allocatePatchData(u_cc_idx, 0.0); level->allocatePatchData(f_cc_idx, 0.0); level->allocatePatchData(e_cc_idx, 0.0); level->allocatePatchData(f_approx_cc_idx, 0.0); } // By default, the norms defined on SAMRAI vectors are vectors in R^n: // however, in IBAMR we almost always want to use a norm that // corresponds to a numerical quadrature. To do this we have to // associate each vector with a set of cell-centered volumes. Rather // than set this up manually, we rely on an IBTK utility class that // computes this (as well as many other things!). These values are // known as `cell weights' in this context, so we get the ID of the // associated data by asking for that. Behind the scenes // HierarchyMathOps sets up the necessary cell-centered variables and // registers them with the usual SAMRAI objects: all we need to do is // ask for the ID. Due to the way SAMRAI works these calls must occur HierarchyMathOps hier_math_ops("hier_math_ops", patch_hierarchy); const int cv_cc_idx = hier_math_ops.getCellWeightPatchDescriptorIndex(); // SAMRAI patches do not store data as a single contiguous arrays; // instead, each hierarchy contains several contiguous arrays. Hence, // to do linear algebra, we rely on SAMRAI's own vector class which // understands these relationships. We begin by initializing each // vector with the patch hierarchy: SAMRAIVectorReal<NDIM, double> u_vec("u", patch_hierarchy, 0, finest_level); SAMRAIVectorReal<NDIM, double> f_vec("f", patch_hierarchy, 0, finest_level); SAMRAIVectorReal<NDIM, double> f_approx_vec("f_approx", patch_hierarchy, 0, finest_level); SAMRAIVectorReal<NDIM, double> e_vec("e", patch_hierarchy, 0, finest_level); // and then associate them with, in each case, the relevant // component. Note that adding the components in this way will // register the vector with the visit data writer declared above and // we will compute cell integrals over the entire domain with respect // to the control volumes defined by cv_cc_idx. u_vec.addComponent(u_cc_var, u_cc_idx, cv_cc_idx); f_vec.addComponent(f_cc_var, f_cc_idx, cv_cc_idx); f_approx_vec.addComponent(f_approx_cc_var, f_approx_cc_idx, cv_cc_idx); e_vec.addComponent(e_cc_var, e_cc_idx, cv_cc_idx); // By default, in SAMRAI, if we create another vector as // // SAMRAIVectorReal<NDIM, double> f_approx_vec("f_approx", patch_hierarchy, 0, finest_level); // // we will simply get a shallow copy of the u vector: put another way, // the two vectors will have different names but refer to the same // numerical values. Unfortunately cloning the vector doesn't work // either: the following code // // tbox::Pointer<SAMRAIVectorReal<NDIM, double> > f_approx = u_vec.cloneVector("f_approx"); // SAMRAIVectorReal<NDIM, double> &f_approx_vec = *f_approx; // f_approx_vec.setToScalar(0.0, false); // // crashes in SAMRAI 2.4.4 with a failed assertion referring to an // unknown variable ID. While ambiguous, the error message is not // wrong: we have to explicitly allocate data for each variable, so // creating a new anonymous variable for a cloned vector does not make // much sense. // Zero the vectors, including possible ghost data: u_vec.setToScalar(0.0, false); f_vec.setToScalar(0.0, false); f_approx_vec.setToScalar(0.0, false); e_vec.setToScalar(0.0, false); // Next, we use functions defined with muParser to set up the right // hand side and solution. These functions are read from the input // database and can be changed without recompiling. { muParserCartGridFunction u_fcn("u", app_initializer->getComponentDatabase("u"), grid_geometry); muParserCartGridFunction f_fcn("f", app_initializer->getComponentDatabase("f"), grid_geometry); u_fcn.setDataOnPatchHierarchy(u_cc_idx, u_cc_var, patch_hierarchy, 0.0); f_fcn.setDataOnPatchHierarchy(f_cc_idx, f_cc_var, patch_hierarchy, 0.0); } // Compute -L*u = f. PoissonSpecifications poisson_spec("poisson_spec"); poisson_spec.setCConstant(0.0); poisson_spec.setDConstant(-1.0); RobinBcCoefStrategy<NDIM>* bc_coef = NULL; CCLaplaceOperator laplace_op("laplace op"); laplace_op.setPoissonSpecifications(poisson_spec); laplace_op.setPhysicalBcCoef(bc_coef); laplace_op.initializeOperatorState(u_vec, f_vec); laplace_op.apply(u_vec, f_approx_vec); // Compute error and print error norms. Here we create temporary smart // pointers that will not delete the underlying object since the // second argument to the constructor is false. e_vec.subtract(Pointer<SAMRAIVectorReal<NDIM, double> >(&f_vec, false), Pointer<SAMRAIVectorReal<NDIM, double> >(&f_approx_vec, false)); pout << "|e|_oo = " << e_vec.maxNorm() << "\n"; pout << "|e|_2 = " << e_vec.L2Norm() << "\n"; pout << "|e|_1 = " << e_vec.L1Norm() << "\n"; // Finally, we clean up the output by setting error values on patches // on coarser levels which are covered by finer levels to zero. for (int ln = 0; ln < finest_level; ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); Pointer<PatchLevel<NDIM> > next_finer_level = patch_hierarchy->getPatchLevel(ln + 1); BoxArray<NDIM> refined_region_boxes = next_finer_level->getBoxes(); refined_region_boxes.coarsen(next_finer_level->getRatioToCoarserLevel()); for (PatchLevel<NDIM>::Iterator p(level); p; p++) { const Patch<NDIM>& patch = *level->getPatch(p()); const Box<NDIM>& patch_box = patch.getBox(); Pointer<CellData<NDIM, double> > e_cc_data = patch.getPatchData(e_cc_idx); for (int i = 0; i < refined_region_boxes.getNumberOfBoxes(); ++i) { const Box<NDIM>& refined_box = refined_region_boxes[i]; // Box::operator* returns the intersection of two boxes. const Box<NDIM>& intersection = patch_box * refined_box; if (!intersection.empty()) { e_cc_data->fillAll(0.0, intersection); } } } } // Output data for plotting. visit_data_writer->writePlotData(patch_hierarchy, 0, 0.0); } // At this point all SAMRAI, PETSc, and IBAMR objects have been cleaned // up, so we shut things down in the opposite order of initialization: SAMRAIManager::shutdown(); PetscFinalize(); return true; } // run_example
/******************************************************************************* * For each run, the input filename and restart information (if needed) must * * be given on the command line. For non-restarted case, command line is: * * * * executable <input file name> * * * * For restarted run, command line is: * * * * executable <input file name> <restart directory> <restart number> * * * *******************************************************************************/ bool run_example(int argc, char* argv[]) { // Initialize PETSc, MPI, and SAMRAI. PetscInitialize(&argc, &argv, NULL, NULL); SAMRAI_MPI::setCommunicator(PETSC_COMM_WORLD); SAMRAI_MPI::setCallAbortInSerialInsteadOfExit(); SAMRAIManager::startup(); // Increase maximum patch data component indices SAMRAIManager::setMaxNumberPatchDataEntries(2500); { // cleanup dynamically allocated objects prior to shutdown // Parse command line options, set some standard options from the input // file, initialize the restart database (if this is a restarted run), // and enable file logging. Pointer<AppInitializer> app_initializer = new AppInitializer(argc, argv, "INS.log"); Pointer<Database> input_db = app_initializer->getInputDatabase(); // Get various standard options set in the input file. const bool dump_viz_data = app_initializer->dumpVizData(); const int viz_dump_interval = app_initializer->getVizDumpInterval(); const bool uses_visit = dump_viz_data && !app_initializer->getVisItDataWriter().isNull(); const bool dump_restart_data = app_initializer->dumpRestartData(); const int restart_dump_interval = app_initializer->getRestartDumpInterval(); const string restart_dump_dirname = app_initializer->getRestartDumpDirectory(); const bool dump_postproc_data = app_initializer->dumpPostProcessingData(); const int postproc_data_dump_interval = app_initializer->getPostProcessingDataDumpInterval(); const string postproc_data_dump_dirname = app_initializer->getPostProcessingDataDumpDirectory(); if (dump_postproc_data && (postproc_data_dump_interval > 0) && !postproc_data_dump_dirname.empty()) { Utilities::recursiveMkdir(postproc_data_dump_dirname); } const bool dump_timer_data = app_initializer->dumpTimerData(); const int timer_dump_interval = app_initializer->getTimerDumpInterval(); // Create major algorithm and data objects that comprise the // application. These objects are configured from the input database // and, if this is a restarted run, from the restart database. Pointer<INSVCStaggeredHierarchyIntegrator> time_integrator; const string discretization_form = app_initializer->getComponentDatabase("Main")->getString("discretization_form"); const bool conservative_form = (discretization_form == "CONSERVATIVE"); if (conservative_form) { time_integrator = new INSVCStaggeredConservativeHierarchyIntegrator( "INSVCStaggeredConservativeHierarchyIntegrator", app_initializer->getComponentDatabase("INSVCStaggeredConservativeHierarchyIntegrator")); } else if (!conservative_form) { time_integrator = new INSVCStaggeredNonConservativeHierarchyIntegrator( "INSVCStaggeredNonConservativeHierarchyIntegrator", app_initializer->getComponentDatabase("INSVCStaggeredNonConservativeHierarchyIntegrator")); } else { TBOX_ERROR("Unsupported solver type: " << discretization_form << "\n" << "Valid options are: CONSERVATIVE, NON_CONSERVATIVE"); } // Set up the advection diffusion hierarchy integrator Pointer<AdvDiffHierarchyIntegrator> adv_diff_integrator; const string adv_diff_solver_type = app_initializer->getComponentDatabase("Main")->getStringWithDefault( "adv_diff_solver_type", "SEMI_IMPLICIT"); if (adv_diff_solver_type == "SEMI_IMPLICIT") { adv_diff_integrator = new AdvDiffSemiImplicitHierarchyIntegrator( "AdvDiffSemiImplicitHierarchyIntegrator", app_initializer->getComponentDatabase("AdvDiffSemiImplicitHierarchyIntegrator")); } else { TBOX_ERROR("Unsupported solver type: " << adv_diff_solver_type << "\n" << "Valid options are: SEMI_IMPLICIT"); } time_integrator->registerAdvDiffHierarchyIntegrator(adv_diff_integrator); Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); Pointer<PatchHierarchy<NDIM> > patch_hierarchy = new PatchHierarchy<NDIM>("PatchHierarchy", grid_geometry); Pointer<StandardTagAndInitialize<NDIM> > error_detector = new StandardTagAndInitialize<NDIM>("StandardTagAndInitialize", time_integrator, app_initializer->getComponentDatabase("StandardTagAndInitialize")); Pointer<BergerRigoutsos<NDIM> > box_generator = new BergerRigoutsos<NDIM>(); Pointer<LoadBalancer<NDIM> > load_balancer = new LoadBalancer<NDIM>("LoadBalancer", app_initializer->getComponentDatabase("LoadBalancer")); Pointer<GriddingAlgorithm<NDIM> > gridding_algorithm = new GriddingAlgorithm<NDIM>("GriddingAlgorithm", app_initializer->getComponentDatabase("GriddingAlgorithm"), error_detector, box_generator, load_balancer); // Setup level set information ColumnInterface column; input_db->getDoubleArray("X_UR", &column.X_UR[0], NDIM); const string& ls_name = "level_set"; Pointer<CellVariable<NDIM, double> > phi_var = new CellVariable<NDIM, double>(ls_name); adv_diff_integrator->registerTransportedQuantity(phi_var); adv_diff_integrator->setDiffusionCoefficient(phi_var, 0.0); // Set the advection velocity of the bubble. adv_diff_integrator->setAdvectionVelocity(phi_var, time_integrator->getAdvectionVelocityVariable()); Pointer<RelaxationLSMethod> level_set_ops = new RelaxationLSMethod("RelaxationLSMethod", app_initializer->getComponentDatabase("RelaxationLSMethod")); LSLocateColumnInterface* ptr_LSLocateColumnInterface = new LSLocateColumnInterface("LSLocateColumnInterface", adv_diff_integrator, phi_var, column); level_set_ops->registerInterfaceNeighborhoodLocatingFcn(&callLSLocateColumnInterfaceCallbackFunction, static_cast<void*>(ptr_LSLocateColumnInterface)); SetLSProperties* ptr_SetLSProperties = new SetLSProperties("SetLSProperties", level_set_ops); adv_diff_integrator->registerResetFunction( phi_var, &callSetLSCallbackFunction, static_cast<void*>(ptr_SetLSProperties)); // Setup the INS maintained material properties. Pointer<Variable<NDIM> > rho_var; if (conservative_form) { rho_var = new SideVariable<NDIM, double>("rho"); } else { rho_var = new CellVariable<NDIM, double>("rho"); } time_integrator->registerMassDensityVariable(rho_var); Pointer<CellVariable<NDIM, double> > mu_var = new CellVariable<NDIM, double>("mu"); time_integrator->registerViscosityVariable(mu_var); // Array for input into callback function const double rho_inside = input_db->getDouble("RHO_I"); const double rho_outside = input_db->getDouble("RHO_O"); const double mu_inside = input_db->getDouble("MU_I"); const double mu_outside = input_db->getDouble("MU_O"); const int ls_reinit_interval = input_db->getInteger("LS_REINIT_INTERVAL"); const double num_interface_cells = input_db->getDouble("NUM_INTERFACE_CELLS"); // Callback functions can either be registered with the NS integrator, or the advection-diffusion integrator // Note that these will set the initial conditions for density and viscosity, based on level set information SetFluidProperties* ptr_SetFluidProperties = new SetFluidProperties("SetFluidProperties", adv_diff_integrator, phi_var, rho_outside, rho_inside, mu_outside, mu_inside, ls_reinit_interval, num_interface_cells); time_integrator->registerResetFluidDensityFcn(&callSetFluidDensityCallbackFunction, static_cast<void*>(ptr_SetFluidProperties)); time_integrator->registerResetFluidViscosityFcn(&callSetFluidViscosityCallbackFunction, static_cast<void*>(ptr_SetFluidProperties)); // Register callback function for tagging refined cells for level set data const double tag_value = input_db->getDouble("LS_TAG_VALUE"); const double tag_thresh = input_db->getDouble("LS_TAG_ABS_THRESH"); TagLSRefinementCells ls_tagger; ls_tagger.d_ls_gas_var = phi_var; ls_tagger.d_tag_value = tag_value; ls_tagger.d_tag_abs_thresh = tag_thresh; ls_tagger.d_adv_diff_solver = adv_diff_integrator; time_integrator->registerApplyGradientDetectorCallback(&callTagLSRefinementCellsCallbackFunction, static_cast<void*>(&ls_tagger)); // Create Eulerian initial condition specification objects. Pointer<CartGridFunction> u_init = new muParserCartGridFunction( "u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); time_integrator->registerVelocityInitialConditions(u_init); if (input_db->keyExists("PressureInitialConditions")) { Pointer<CartGridFunction> p_init = new muParserCartGridFunction( "p_init", app_initializer->getComponentDatabase("PressureInitialConditions"), grid_geometry); time_integrator->registerPressureInitialConditions(p_init); } // Create Eulerian boundary condition specification objects (when necessary). const IntVector<NDIM>& periodic_shift = grid_geometry->getPeriodicShift(); vector<RobinBcCoefStrategy<NDIM>*> u_bc_coefs(NDIM); if (periodic_shift.min() > 0) { for (unsigned int d = 0; d < NDIM; ++d) { u_bc_coefs[d] = NULL; } } else { for (unsigned int d = 0; d < NDIM; ++d) { const std::string bc_coefs_name = "u_bc_coefs_" + std::to_string(d); const std::string bc_coefs_db_name = "VelocityBcCoefs_" + std::to_string(d); u_bc_coefs[d] = new muParserRobinBcCoefs( bc_coefs_name, app_initializer->getComponentDatabase(bc_coefs_db_name), grid_geometry); } time_integrator->registerPhysicalBoundaryConditions(u_bc_coefs); } RobinBcCoefStrategy<NDIM>* phi_bc_coef = NULL; if (!(periodic_shift.min() > 0) && input_db->keyExists("PhiBcCoefs")) { phi_bc_coef = new muParserRobinBcCoefs( "phi_bc_coef", app_initializer->getComponentDatabase("PhiBcCoefs"), grid_geometry); adv_diff_integrator->setPhysicalBcCoef(phi_var, phi_bc_coef); } level_set_ops->registerPhysicalBoundaryCondition(phi_bc_coef); RobinBcCoefStrategy<NDIM>* rho_bc_coef = NULL; if (!(periodic_shift.min() > 0) && input_db->keyExists("RhoBcCoefs")) { rho_bc_coef = new muParserRobinBcCoefs( "rho_bc_coef", app_initializer->getComponentDatabase("RhoBcCoefs"), grid_geometry); time_integrator->registerMassDensityBoundaryConditions(rho_bc_coef); } RobinBcCoefStrategy<NDIM>* mu_bc_coef = NULL; if (!(periodic_shift.min() > 0) && input_db->keyExists("MuBcCoefs")) { mu_bc_coef = new muParserRobinBcCoefs( "mu_bc_coef", app_initializer->getComponentDatabase("MuBcCoefs"), grid_geometry); time_integrator->registerViscosityBoundaryConditions(mu_bc_coef); } // Forcing terms std::vector<double> grav_const(NDIM); input_db->getDoubleArray("GRAV_CONST", &grav_const[0], NDIM); Pointer<CartGridFunction> grav_force = new GravityForcing("GravityForcing", time_integrator, grav_const); Pointer<SurfaceTensionForceFunction> surface_tension_force = new SurfaceTensionForceFunction("SurfaceTensionForceFunction", app_initializer->getComponentDatabase("SurfaceTensionForceFunction"), adv_diff_integrator, phi_var); Pointer<CartGridFunctionSet> eul_forces = new CartGridFunctionSet("eulerian_forces"); eul_forces->addFunction(surface_tension_force); eul_forces->addFunction(grav_force); time_integrator->registerBodyForceFunction(eul_forces); // Set up visualization plot file writers. Pointer<VisItDataWriter<NDIM> > visit_data_writer = app_initializer->getVisItDataWriter(); if (uses_visit) { time_integrator->registerVisItDataWriter(visit_data_writer); } // Initialize hierarchy configuration and data on all patches. time_integrator->initializePatchHierarchy(patch_hierarchy, gridding_algorithm); // Remove the AppInitializer app_initializer.setNull(); // Print the input database contents to the log file. plog << "Input database:\n"; input_db->printClassData(plog); // Write out initial visualization data. int iteration_num = time_integrator->getIntegratorStep(); double loop_time = time_integrator->getIntegratorTime(); if (dump_viz_data && uses_visit) { pout << "\n\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } // File to write to for fluid mass data ofstream mass_file, front_file, height_file; if (!SAMRAI_MPI::getRank()) { mass_file.open("mass_fluid.txt"); front_file.open("front_position.txt"); height_file.open("height_fluid.txt"); } // Main time step loop. double loop_time_end = time_integrator->getEndTime(); double dt = 0.0; while (!MathUtilities<double>::equalEps(loop_time, loop_time_end) && time_integrator->stepsRemaining()) { iteration_num = time_integrator->getIntegratorStep(); loop_time = time_integrator->getIntegratorTime(); pout << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "At beginning of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; dt = time_integrator->getMaximumTimeStepSize(); time_integrator->advanceHierarchy(dt); loop_time += dt; pout << "\n"; pout << "At end of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "\n"; // Compute the fluid mass in the domain from interpolated density const int rho_ins_idx = time_integrator->getLinearOperatorRhoPatchDataIndex(); #if !defined(NDEBUG) TBOX_ASSERT(rho_ins_idx >= 0); #endif const int coarsest_ln = 0; const int finest_ln = patch_hierarchy->getFinestLevelNumber(); HierarchySideDataOpsReal<NDIM, double> hier_rho_data_ops(patch_hierarchy, coarsest_ln, finest_ln); HierarchyMathOps hier_math_ops("HierarchyMathOps", patch_hierarchy); hier_math_ops.setPatchHierarchy(patch_hierarchy); hier_math_ops.resetLevels(coarsest_ln, finest_ln); const int wgt_sc_idx = hier_math_ops.getSideWeightPatchDescriptorIndex(); const double mass_fluid = hier_rho_data_ops.integral(rho_ins_idx, wgt_sc_idx); // Compute the front position and the height of the fluid. This can be approximately done by finding // the maximum x and y (z in 3D) coordinate of the negative level set values. double fluid_front = -std::numeric_limits<double>::max(); double fluid_height = -std::numeric_limits<double>::max(); VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); const int phi_idx = var_db->mapVariableAndContextToIndex(phi_var, adv_diff_integrator->getCurrentContext()); for (int ln = coarsest_ln; ln <= finest_ln; ++ln) { Pointer<PatchLevel<NDIM> > level = patch_hierarchy->getPatchLevel(ln); for (PatchLevel<NDIM>::Iterator p(level); p; p++) { Pointer<Patch<NDIM> > patch = level->getPatch(p()); const Box<NDIM>& patch_box = patch->getBox(); Pointer<CellData<NDIM, double> > D_data = patch->getPatchData(phi_idx); for (Box<NDIM>::Iterator it(patch_box); it; it++) { CellIndex<NDIM> ci(it()); // Get physical coordinates IBTK::Vector coord = IBTK::Vector::Zero(); Pointer<CartesianPatchGeometry<NDIM> > patch_geom = patch->getPatchGeometry(); const double* patch_X_lower = patch_geom->getXLower(); const hier::Index<NDIM>& patch_lower_idx = patch_box.lower(); const double* const patch_dx = patch_geom->getDx(); for (int d = 0; d < NDIM; ++d) { coord[d] = patch_X_lower[d] + patch_dx[d] * (static_cast<double>(ci(d) - patch_lower_idx(d)) + 0.5); } // Check if this coordinate is maximal for negative level set values const double phi = (*D_data)(ci); const int front_dim = 0; const int height_dim = NDIM - 1; fluid_front = (phi <= 0.0 && coord[front_dim] >= fluid_front) ? coord[front_dim] : fluid_front; fluid_height = (phi <= 0.0 && coord[height_dim] >= fluid_height) ? coord[height_dim] : fluid_height; } } } // Max reduction fluid_front = SAMRAI_MPI::maxReduction(fluid_front); fluid_height = SAMRAI_MPI::maxReduction(fluid_height); // Write to file if (!SAMRAI_MPI::getRank()) { mass_file << std::setprecision(13) << loop_time << "\t" << mass_fluid << std::endl; front_file << std::setprecision(13) << loop_time << "\t" << fluid_front << std::endl; height_file << std::setprecision(13) << loop_time << "\t" << fluid_height << std::endl; } // At specified intervals, write visualization and restart files, // print out timer data, and store hierarchy data for post // processing. iteration_num += 1; const bool last_step = !time_integrator->stepsRemaining(); if (dump_viz_data && uses_visit && (iteration_num % viz_dump_interval == 0 || last_step)) { pout << "\nWriting visualization files...\n\n"; time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } if (dump_restart_data && (iteration_num % restart_dump_interval == 0 || last_step)) { pout << "\nWriting restart files...\n\n"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, iteration_num); } if (dump_timer_data && (iteration_num % timer_dump_interval == 0 || last_step)) { pout << "\nWriting timer data...\n\n"; TimerManager::getManager()->print(plog); } if (dump_postproc_data && (iteration_num % postproc_data_dump_interval == 0 || last_step)) { output_data(patch_hierarchy, time_integrator, iteration_num, loop_time, postproc_data_dump_dirname); } } // Close file if (!SAMRAI_MPI::getRank()) { mass_file.close(); front_file.close(); height_file.close(); } // Cleanup Eulerian boundary condition specification objects (when // necessary). for (unsigned int d = 0; d < NDIM; ++d) delete u_bc_coefs[d]; // Cleanup other dumb pointers delete ptr_SetLSProperties; delete ptr_SetFluidProperties; delete ptr_LSLocateColumnInterface; } // cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return true; } // run_example