/******************************************************************************* * 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 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 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,PETSC_NULL,PETSC_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().isNull(); const bool is_from_restart = app_initializer->isFromRestart(); 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<IBMethod> ib_method_ops = new IBMethod("IBMethod", app_initializer->getComponentDatabase("IBMethod")); Pointer<INSHierarchyIntegrator> navier_stokes_integrator = new INSStaggeredHierarchyIntegrator("INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); 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. if (input_db->keyExists("VelocityInitialConditions")) { navier_stokes_integrator->registerVelocityInitialConditions(new muParserCartGridFunction("u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry)); } if (input_db->keyExists("PressureInitialConditions")) { navier_stokes_integrator->registerPressureInitialConditions(new muParserCartGridFunction("p_init", app_initializer->getComponentDatabase("PressureInitialConditions"), grid_geometry)); } // Create Eulerian boundary condition specification objects (when necessary). const bool periodic_domain = grid_geometry->getPeriodicShift().min() > 0; std::vector<RobinBcCoefStrategy<NDIM>*> u_bc_coefs(NDIM,static_cast<RobinBcCoefStrategy<NDIM>*>(NULL)); if (!periodic_domain) { 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")) { time_integrator->registerBodyForceFunction(new muParserCartGridFunction("f_fcn", app_initializer->getComponentDatabase("ForcingFunction"), grid_geometry)); } // 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); // Write restart data before starting main time integration loop. if (dump_restart_data && !is_from_restart) { pout << "\nWriting restart files...\n\n"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, 0); } // 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(); pout << "\n\nSetupPlotData() finished.. \n\n"; visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); pout << "\n\nwritePlotData(...) finished.. \n\n"; silo_data_writer->writePlotData(iteration_num, loop_time); pout << "\n\n write PlotData(...) 2 finished.. \n\n"; } // 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(); LDataManager* l_data_manager = ib_method_ops->getLDataManager(); // update_target_point_positions(patch_hierarchy, l_data_manager, loop_time, dt); 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, l_data_manager, iteration_num, loop_time, postproc_data_dump_dirname); } } // 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 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, "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(); 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(); 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> time_integrator; const string solver_type = app_initializer->getComponentDatabase("Main")->getStringWithDefault("solver_type", "STAGGERED"); if (solver_type == "STAGGERED") { time_integrator = new INSStaggeredHierarchyIntegrator( "INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); } else if (solver_type == "COLLOCATED") { time_integrator = new INSCollocatedHierarchyIntegrator( "INSCollocatedHierarchyIntegrator", app_initializer->getComponentDatabase("INSCollocatedHierarchyIntegrator")); } else { TBOX_ERROR("Unsupported solver type: " << solver_type << "\n" << "Valid options are: COLLOCATED, STAGGERED"); } 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 initial condition specification objects. if (input_db->keyExists("VelocityInitialConditions")) { Pointer<CartGridFunction> u_init = new muParserCartGridFunction( "u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); time_integrator->registerVelocityInitialConditions(u_init); } // 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); } time_integrator->registerPhysicalBoundaryConditions(u_bc_coefs); } // Create body force function specification objects (when necessary). 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(); 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); } 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); } } // 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 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(); { // 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 is_from_restart = app_initializer->isFromRestart(); 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<INSStaggeredHierarchyIntegrator> navier_stokes_integrator = new INSStaggeredHierarchyIntegrator( "INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); 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. if (input_db->keyExists("VelocityInitialConditions")) { Pointer<CartGridFunction> u_init = new muParserCartGridFunction( "u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); navier_stokes_integrator->registerVelocityInitialConditions(u_init); } if (input_db->keyExists("PressureInitialConditions")) { 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) { 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); } navier_stokes_integrator->registerPhysicalBoundaryConditions(u_bc_coefs); } // Create stochastic forcing function specification object. Pointer<INSStaggeredStochasticForcing> f_fcn = new INSStaggeredStochasticForcing("INSStaggeredStochasticForcing", app_initializer->getComponentDatabase("INSStaggeredStochasticForcing"), navier_stokes_integrator); time_integrator->registerBodyForceFunction(f_fcn); // Seed the random number generator. int seed = 0; if (input_db->keyExists("SEED")) { seed = input_db->getInteger("SEED"); } else { TBOX_ERROR("Key data `seed' not found in input."); } RNG::parallel_seed(seed); // We are primarily interested in the Lagrangian data so we can skip writing Eulerian data: int output_level = 1; // -1=none, 0=txt, 1=silo+txt, 2=visit+silo+txt, 3=visit+SAMRAI+silo+txt, >3=verbose if (input_db->keyExists("OUTPUT_LEVEL")) { output_level = input_db->getInteger("OUTPUT_LEVEL"); } // 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); // Write restart data before starting main time integration loop. if (dump_restart_data && !is_from_restart) { pout << "\nWriting restart files...\n\n"; RestartManager::getManager()->writeRestartFile(restart_dump_dirname, 0); } // Write out initial visualization data. int iteration_num = time_integrator->getIntegratorStep(); double loop_time = time_integrator->getIntegratorTime(); if (dump_viz_data && uses_visit) { if (output_level >= 0) pout << "\nWriting visualization files at timestep # " << iteration_num << " t=" << loop_time << "\n"; time_integrator->setupPlotData(); if (output_level >= 2) visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); if (output_level >= 1) silo_data_writer->writePlotData(iteration_num, loop_time); } if (dump_postproc_data) { output_data(patch_hierarchy, navier_stokes_integrator, ib_method_ops->getLDataManager(), iteration_num, loop_time, output_level, postproc_data_dump_dirname); } // 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(); if (output_level > 3) { pout << "\n"; pout << "+++++++++++++++++++++++++++++++++++++++++++++++++++\n"; pout << "At beginning of timestep # " << iteration_num << "\n"; pout << "Simulation time is " << loop_time << "\n"; } const double dt = time_integrator->getMaximumTimeStepSize(); time_integrator->advanceHierarchy(dt); loop_time += dt; if (output_level > 3) { 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)) { if (output_level >= 0) pout << "\nWriting visualization files at timestep # " << iteration_num << " t=" << loop_time << "\n"; time_integrator->setupPlotData(); if (output_level >= 2) visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); if (output_level >= 1) 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, output_level, postproc_data_dump_dirname); } } // 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 true; } // main
bool run_example(int argc, char** argv) { // Initialize libMesh, PETSc, MPI, and SAMRAI. LibMeshInit init(argc, argv); 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(); // Setup user-defined kernel function. LEInteractor::s_kernel_fcn = &kernel; LEInteractor::s_kernel_fcn_stencil_size = 8; // 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(); #ifdef LIBMESH_HAVE_EXODUS_API const bool uses_exodus = dump_viz_data && !app_initializer->getExodusIIFilename().empty(); #else const bool uses_exodus = false; if (!app_initializer->getExodusIIFilename().empty()) { plog << "WARNING: libMesh was compiled without Exodus support, so no " << "Exodus output will be written in this program.\n"; } #endif const string exodus_filename = app_initializer->getExodusIIFilename(); 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 a simple FE mesh. Mesh solid_mesh(init.comm(), NDIM); const double dx = input_db->getDouble("DX"); const double ds = input_db->getDouble("MFAC") * dx; string elem_type = input_db->getString("ELEM_TYPE"); R = input_db->getDouble("R"); if (NDIM == 2 && (elem_type == "TRI3" || elem_type == "TRI6")) { #ifdef LIBMESH_HAVE_TRIANGLE const int num_circum_nodes = ceil(2.0 * M_PI * R / ds); for (int k = 0; k < num_circum_nodes; ++k) { const double theta = 2.0 * M_PI * static_cast<double>(k) / static_cast<double>(num_circum_nodes); solid_mesh.add_point(libMesh::Point(R * cos(theta), R * sin(theta))); } TriangleInterface triangle(solid_mesh); triangle.triangulation_type() = TriangleInterface::GENERATE_CONVEX_HULL; triangle.elem_type() = Utility::string_to_enum<ElemType>(elem_type); triangle.desired_area() = 1.5 * sqrt(3.0) / 4.0 * ds * ds; triangle.insert_extra_points() = true; triangle.smooth_after_generating() = true; triangle.triangulate(); #else TBOX_ERROR("ERROR: libMesh appears to have been configured without support for Triangle,\n" << " but Triangle is required for TRI3 or TRI6 elements.\n"); #endif } else { // NOTE: number of segments along boundary is 4*2^r. const double num_circum_segments = 2.0 * M_PI * R / ds; const int r = log2(0.25 * num_circum_segments); MeshTools::Generation::build_sphere(solid_mesh, R, r, Utility::string_to_enum<ElemType>(elem_type)); } // Ensure nodes on the surface are on the analytic boundary. MeshBase::element_iterator el_end = solid_mesh.elements_end(); for (MeshBase::element_iterator el = solid_mesh.elements_begin(); el != el_end; ++el) { Elem* const elem = *el; for (unsigned int side = 0; side < elem->n_sides(); ++side) { const bool at_mesh_bdry = !elem->neighbor_ptr(side); if (!at_mesh_bdry) continue; for (unsigned int k = 0; k < elem->n_nodes(); ++k) { if (!elem->is_node_on_side(k, side)) continue; Node& n = elem->node_ref(k); n = R * n.unit(); } } } solid_mesh.prepare_for_use(); Mesh& mesh = solid_mesh; // 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 = new INSStaggeredHierarchyIntegrator( "INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); Pointer<IBFEMethod> ib_method_ops = new IBFEMethod("IBFEMethod", app_initializer->getComponentDatabase("IBFEMethod"), &mesh, app_initializer->getComponentDatabase("GriddingAlgorithm")->getInteger("max_levels")); 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); // Create IBFE direct forcing kinematics object. Pointer<IBFEDirectForcingKinematics> df_kinematics_ops = new IBFEDirectForcingKinematics( "cylinder_dfk", app_initializer->getComponentDatabase("CylinderIBFEDirectForcingKinematics"), ib_method_ops, /*part*/ 0, /*register_for_restart*/ true); ib_method_ops->registerDirectForcingKinematics(df_kinematics_ops, /*part*/ 0); // Specify structure kinematics FreeRigidDOFVector solve_dofs; solve_dofs.setZero(); df_kinematics_ops->setSolveRigidBodyVelocity(solve_dofs); df_kinematics_ops->registerKinematicsFunction(&cylinder_kinematics, NULL); // Configure the IBFE solver. ib_method_ops->initializeFEEquationSystems(); EquationSystems* equation_systems = ib_method_ops->getFEDataManager()->getEquationSystems(); // Create Eulerian initial condition specification objects. if (input_db->keyExists("VelocityInitialConditions")) { Pointer<CartGridFunction> u_init = new muParserCartGridFunction( "u_init", app_initializer->getComponentDatabase("VelocityInitialConditions"), grid_geometry); navier_stokes_integrator->registerVelocityInitialConditions(u_init); } if (input_db->keyExists("PressureInitialConditions")) { 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) { 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); } 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(); if (uses_visit) { time_integrator->registerVisItDataWriter(visit_data_writer); } std::unique_ptr<ExodusII_IO> exodus_io(uses_exodus ? new ExodusII_IO(mesh) : NULL); // Initialize hierarchy configuration and data on all patches. ib_method_ops->initializeFEData(); 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) { pout << "\n\nWriting visualization files...\n\n"; if (uses_visit) { time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } if (uses_exodus) { exodus_io->write_timestep( exodus_filename, *equation_systems, iteration_num / viz_dump_interval + 1, loop_time); } } // Open streams to save lift and drag coefficients. if (SAMRAI_MPI::getRank() == 0) { drag_stream.open("C_D.curve", ios_base::out | ios_base::trunc); lift_stream.open("C_L.curve", ios_base::out | ios_base::trunc); drag_stream.precision(10); lift_stream.precision(10); } // 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 && (iteration_num % viz_dump_interval == 0 || last_step)) { pout << "\nWriting visualization files...\n\n"; if (uses_visit) { time_integrator->setupPlotData(); visit_data_writer->writePlotData(patch_hierarchy, iteration_num, loop_time); } if (uses_exodus) { exodus_io->write_timestep( exodus_filename, *equation_systems, iteration_num / viz_dump_interval + 1, 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)) { postprocess_data(patch_hierarchy, navier_stokes_integrator, mesh, equation_systems, iteration_num, loop_time, postproc_data_dump_dirname); } } // Close the logging streams. if (SAMRAI_MPI::getRank() == 0) { drag_stream.close(); lift_stream.close(); } // 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(); 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
/******************************************************************************* * 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, "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(); 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<INSStaggeredHierarchyIntegrator> time_integrator = new INSStaggeredHierarchyIntegrator( "INSStaggeredHierarchyIntegrator", app_initializer->getComponentDatabase("INSStaggeredHierarchyIntegrator")); Pointer<AdvDiffSemiImplicitHierarchyIntegrator> adv_diff_integrator = new AdvDiffSemiImplicitHierarchyIntegrator( "AdvDiffSemiImplicitHierarchyIntegrator", app_initializer->getComponentDatabase("AdvDiffSemiImplicitHierarchyIntegrator")); time_integrator->registerAdvDiffHierarchyIntegrator(adv_diff_integrator); Pointer<CartesianGridGeometry<NDIM> > grid_geometry = new CartesianGridGeometry<NDIM>( "CartesianGeometry", app_initializer->getComponentDatabase("CartesianGeometry")); const bool periodic_domain = grid_geometry->getPeriodicShift().min() > 0; 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 the advected and diffused quantity. Pointer<CellVariable<NDIM, double> > T_var = new CellVariable<NDIM, double>("T"); adv_diff_integrator->registerTransportedQuantity(T_var); adv_diff_integrator->setDiffusionCoefficient(T_var, input_db->getDouble("KAPPA")); adv_diff_integrator->setInitialConditions( T_var, new muParserCartGridFunction( "T_init", app_initializer->getComponentDatabase("TemperatureInitialConditions"), grid_geometry)); RobinBcCoefStrategy<NDIM>* T_bc_coef = NULL; if (!periodic_domain) { T_bc_coef = new muParserRobinBcCoefs( "T_bc_coef", app_initializer->getComponentDatabase("TemperatureBcCoefs"), grid_geometry); adv_diff_integrator->setPhysicalBcCoef(T_var, T_bc_coef); } adv_diff_integrator->setAdvectionVelocity(T_var, time_integrator->getAdvectionVelocityVariable()); Pointer<CellVariable<NDIM, double> > F_T_var = new CellVariable<NDIM, double>("F_T"); adv_diff_integrator->registerSourceTerm(F_T_var); adv_diff_integrator->setSourceTermFunction( F_T_var, new AdvDiffStochasticForcing("AdvDiffStochasticForcing", app_initializer->getComponentDatabase("TemperatureStochasticForcing"), T_var, adv_diff_integrator)); adv_diff_integrator->setSourceTerm(T_var, F_T_var); // Set up the fluid solver. time_integrator->registerBodyForceFunction( new BoussinesqForcing(T_var, adv_diff_integrator, input_db->getDouble("GAMMA"))); time_integrator->registerBodyForceFunction( new INSStaggeredStochasticForcing("INSStaggeredStochasticForcing", app_initializer->getComponentDatabase("VelocityStochasticForcing"), time_integrator)); vector<RobinBcCoefStrategy<NDIM>*> u_bc_coefs(NDIM); for (unsigned int d = 0; d < NDIM; ++d) u_bc_coefs[d] = NULL; if (!periodic_domain) { 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); } time_integrator->registerPhysicalBoundaryConditions(u_bc_coefs); } // Seed the random number generator. int seed = 0; if (input_db->keyExists("SEED")) { seed = input_db->getInteger("SEED"); } else { TBOX_ERROR("Key data `seed' not found in input."); } RNG::parallel_seed(seed); // 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); } } // Cleanup boundary condition specification objects (when necessary). for (unsigned int d = 0; d < NDIM; ++d) delete u_bc_coefs[d]; delete T_bc_coef; } // cleanup dynamically allocated objects prior to shutdown SAMRAIManager::shutdown(); PetscFinalize(); return 0; } // main