void beam_PK1_dil_stress_function(TensorValue<double>& PP, const TensorValue<double>& FF, const libMesh::Point& /*X*/, const libMesh::Point& /*s*/, Elem* const /*elem*/, const vector<NumericVector<double>*>& /*system_data*/, double /*time*/, void* /*ctx*/) { double J = FF.det(); J_dil_min = std::min(J, J_dil_min); J_dil_max = std::max(J, J_dil_max); PP.zero(); if (!MathUtilities<double>::equalEps(beta_s, 0.0)) { const TensorValue<double> FF_inv_trans = tensor_inverse_transpose(FF, NDIM); PP -= 2.0 * beta_s * log(FF.det()) * FF_inv_trans; } return; } // beam_PK1_dil_stress_function
void PK1_dil_stress_function( TensorValue<double>& PP, const TensorValue<double>& FF, const libMesh::Point& /*X*/, const libMesh::Point& /*s*/, Elem* const /*elem*/, const std::vector<NumericVector<double>*>& /*system_data*/, double /*time*/, void* /*ctx*/) { PP = 2.0*(-p0_s + beta_s*log(FF.det()))*tensor_inverse_transpose(FF, NDIM); return; }// PK1_dil_stress_function
void PK1_stress_function(TensorValue<double>& PP, const TensorValue<double>& FF, const libMesh::Point& /*x*/, const libMesh::Point& /*X*/, subdomain_id_type /*subdomain_id*/, std::vector<double>& /*internal_vars*/, double /*time*/, void* /*ctx*/) { const TensorValue<double> FF_inv_trans = tensor_inverse_transpose(FF, NDIM); const TensorValue<double> CC = FF.transpose() * FF; PP = 2.0 * c1_s * FF; if (!MathUtilities<double>::equalEps(p0_s, 0.0)) { PP -= 2.0 * p0_s * FF_inv_trans; } if (!MathUtilities<double>::equalEps(beta_s, 0.0)) { PP += beta_s * log(CC.det()) * FF_inv_trans; } return; } // PK1_stress_function
/******************************************************************************* * 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 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(); // 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 uses_exodus = dump_viz_data && !app_initializer->getExodusIIFilename().empty(); 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 mesh(NDIM); const double dx = input_db->getDouble("DX"); const double ds = input_db->getDouble("MFAC")*dx; string elem_type = input_db->getString("ELEM_TYPE"); const double R = 0.2; if (NDIM == 2 && (elem_type == "TRI3" || elem_type == "TRI6")) { 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); mesh.add_point(libMesh::Point(R*cos(theta), R*sin(theta))); } TriangleInterface triangle(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 { // 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(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 = mesh.elements_end(); for (MeshBase::element_iterator el = 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(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->get_node(k); n = R*n.unit(); } } } mesh.prepare_for_use(); c1_s = input_db->getDouble("C1_S"); p0_s = input_db->getDouble("P0_S"); beta_s = input_db->getDouble("BETA_S"); // 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")->getString("solver_type"); 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<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); // Configure the IBFE solver. ib_method_ops->registerInitialCoordinateMappingFunction(coordinate_mapping_function); IBFEMethod::PK1StressFcnData PK1_dev_stress_data(PK1_dev_stress_function); IBFEMethod::PK1StressFcnData PK1_dil_stress_data(PK1_dil_stress_function); PK1_dev_stress_data.quad_order = Utility::string_to_enum<libMeshEnums::Order>(input_db->getStringWithDefault("PK1_DEV_QUAD_ORDER","THIRD")); PK1_dil_stress_data.quad_order = Utility::string_to_enum<libMeshEnums::Order>(input_db->getStringWithDefault("PK1_DIL_QUAD_ORDER","FIRST")); ib_method_ops->registerPK1StressFunction(PK1_dev_stress_data); ib_method_ops->registerPK1StressFunction(PK1_dil_stress_data); EquationSystems* equation_systems = ib_method_ops->getFEDataManager()->getEquationSystems(); // Set up post processor to recover computed stresses. FEDataManager* fe_data_manager = ib_method_ops->getFEDataManager(); Pointer<IBFEPostProcessor> ib_post_processor = new IBFECentroidPostProcessor("IBFEPostProcessor", fe_data_manager); ib_post_processor->registerTensorVariable( "FF", MONOMIAL, CONSTANT, IBFEPostProcessor::FF_fcn); std::pair<IBTK::TensorMeshFcnPtr,void*> PK1_dev_stress_fcn_data(PK1_dev_stress_function,static_cast<void*>(NULL)); ib_post_processor->registerTensorVariable( "sigma_dev", MONOMIAL, CONSTANT, IBFEPostProcessor::cauchy_stress_from_PK1_stress_fcn, std::vector<unsigned int>(), &PK1_dev_stress_fcn_data); std::pair<IBTK::TensorMeshFcnPtr,void*> PK1_dil_stress_fcn_data(PK1_dil_stress_function,static_cast<void*>(NULL)); ib_post_processor->registerTensorVariable( "sigma_dil", MONOMIAL, CONSTANT, IBFEPostProcessor::cauchy_stress_from_PK1_stress_fcn, std::vector<unsigned int>(), &PK1_dil_stress_fcn_data); ib_post_processor->registerInterpolatedScalarEulerianVariable( "p_f", LAGRANGE, FIRST, navier_stokes_integrator->getPressureVariable(), navier_stokes_integrator->getCurrentContext()); // 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) { 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(); if (uses_visit) { time_integrator->registerVisItDataWriter(visit_data_writer); } AutoPtr<ExodusII_IO> exodus_io(uses_exodus ? new ExodusII_IO(mesh) : NULL); // Initialize hierarchy configuration and data on all patches. ib_method_ops->initializeFEData(); ib_post_processor->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) { ib_post_processor->postProcessData(loop_time); exodus_io->write_timestep(exodus_filename, *equation_systems, iteration_num/viz_dump_interval+1, loop_time); } } // Open streams to save volume of structure. ofstream volume_stream; if (SAMRAI_MPI::getRank() == 0) { volume_stream.open("volume.curve", ios_base::out | ios_base::trunc); } // 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) { ib_post_processor->postProcessData(loop_time); 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)) { output_data(patch_hierarchy, navier_stokes_integrator, mesh, equation_systems, iteration_num, loop_time, postproc_data_dump_dirname); } // Compute the volume of the structure. double J_integral = 0.0; System& X_system = equation_systems->get_system<System>(IBFEMethod::COORDS_SYSTEM_NAME); NumericVector<double>* X_vec = X_system.solution.get(); NumericVector<double>* X_ghost_vec = X_system.current_local_solution.get(); X_vec->localize(*X_ghost_vec); DofMap& X_dof_map = X_system.get_dof_map(); std::vector<std::vector<unsigned int> > X_dof_indices(NDIM); AutoPtr<FEBase> fe(FEBase::build(NDIM, X_dof_map.variable_type(0))); AutoPtr<QBase> qrule = QBase::build(QGAUSS, NDIM, FIFTH); fe->attach_quadrature_rule(qrule.get()); const std::vector<double>& JxW = fe->get_JxW(); const std::vector<std::vector<VectorValue<double> > >& dphi = fe->get_dphi(); TensorValue<double> FF; boost::multi_array<double,2> X_node; const MeshBase::const_element_iterator el_begin = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator el_end = mesh.active_local_elements_end(); for (MeshBase::const_element_iterator el_it = el_begin; el_it != el_end; ++el_it) { Elem* const elem = *el_it; fe->reinit(elem); for (unsigned int d = 0; d < NDIM; ++d) { X_dof_map.dof_indices(elem, X_dof_indices[d], d); } const int n_qp = qrule->n_points(); get_values_for_interpolation(X_node, *X_ghost_vec, X_dof_indices); for (int qp = 0; qp < n_qp; ++qp) { jacobian(FF,qp,X_node,dphi); J_integral += abs(FF.det())*JxW[qp]; } } J_integral = SAMRAI_MPI::sumReduction(J_integral); if (SAMRAI_MPI::getRank() == 0) { volume_stream.precision(12); volume_stream.setf(ios::fixed,ios::floatfield); volume_stream << loop_time << " " << J_integral << endl; } } // Close the logging streams. if (SAMRAI_MPI::getRank() == 0) { volume_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 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 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(); // 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 uses_exodus = dump_viz_data && !app_initializer->getExodusIIFilename().empty(); 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 with periodic boundary conditions in the "x" // direction. // // Note that boundary condition data must be registered with each FE // system before calling IBFEMethod::initializeFEData(). Mesh mesh(NDIM); const double R = 0.25; const double w = 0.0625; const double dx0 = 1.0/64.0; const double dx = input_db->getDouble("DX"); const double ds0 = input_db->getDouble("MFAC")*dx0; string elem_type = input_db->getString("ELEM_TYPE"); MeshTools::Generation::build_square(mesh, 4*static_cast<int>((dx0/dx)*ceil(2.0*M_PI*R/ds0/4.0)), static_cast<int>((dx0/dx)*ceil(w/ds0)), 0.0, 2.0*M_PI*R, 0.0, w, Utility::string_to_enum<ElemType>(elem_type)); VectorValue<double> boundary_translation(2.0*M_PI*R, 0.0, 0.0); PeriodicBoundary pbc(boundary_translation); pbc.myboundary = 3; pbc.pairedboundary = 1; // Configure stress tensor options. smooth_case = input_db->getBool("SMOOTH_CASE"); // 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")->getString("solver_type"); 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<IBFEMethod> ib_method_ops = new IBFEMethod( "IBFEMethod", app_initializer->getComponentDatabase("IBFEMethod"), &mesh, app_initializer->getComponentDatabase("GriddingAlgorithm")->getInteger("max_levels")); Pointer<IBHierarchyIntegrator> time_integrator = new IBHierarchyIntegrator( "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 IBFE solver. ib_method_ops->registerInitialCoordinateMappingFunction(&coordinate_mapping_function); ib_method_ops->registerPK1StressTensorFunction(&PK1_stress_function); EquationSystems* equation_systems = ib_method_ops->getFEDataManager()->getEquationSystems(); for (unsigned int k = 0; k < equation_systems->n_systems(); ++k) { System& system = equation_systems->get_system(k); system.get_dof_map().add_periodic_boundary(pbc); } // 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(); TinyVector<RobinBcCoefStrategy<NDIM>*,NDIM> u_bc_coefs; 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(); if (uses_visit) { time_integrator->registerVisItDataWriter(visit_data_writer); } AutoPtr<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); // Setup data used to determine the accuracy of the computed solution. VariableDatabase<NDIM>* var_db = VariableDatabase<NDIM>::getDatabase(); const Pointer<hier::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<hier::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) { 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 volume of structure. ofstream volume_stream; if (SAMRAI_MPI::getRank() == 0) { volume_stream.open("volume.curve", ios_base::out | ios_base::trunc); } // 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->getTimeStepSize(); 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)) { pout << "\nWriting state data...\n\n"; output_data(patch_hierarchy, navier_stokes_integrator, mesh, equation_systems, 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 double volume = hier_math_ops.getVolumeOfPhysicalDomain(); 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.isNull()) { 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.isNull()) { 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); const double p_mean = (1.0/volume)*hier_cc_data_ops.integral(p_idx, wgt_cc_idx); hier_cc_data_ops.addScalar(p_idx, p_idx, -p_mean); const double p_cloned_mean = (1.0/volume)*hier_cc_data_ops.integral(p_cloned_idx, wgt_cc_idx); hier_cc_data_ops.addScalar(p_cloned_idx, p_cloned_idx, -p_cloned_mean); 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"; // Compute the volume of the structure. double J_integral = 0.0; System& X_system = equation_systems->get_system<System>(IBFEMethod::COORDS_SYSTEM_NAME); NumericVector<double>* X_vec = X_system.solution.get(); NumericVector<double>* X_ghost_vec = X_system.current_local_solution.get(); X_vec->localize(*X_ghost_vec); DofMap& X_dof_map = X_system.get_dof_map(); blitz::Array<std::vector<unsigned int>,1> X_dof_indices(NDIM); AutoPtr<FEBase> fe(FEBase::build(NDIM, X_dof_map.variable_type(0))); AutoPtr<QBase> qrule = QBase::build(QGAUSS, NDIM, FIFTH); fe->attach_quadrature_rule(qrule.get()); const std::vector<double>& JxW = fe->get_JxW(); const std::vector<std::vector<VectorValue<double> > >& dphi = fe->get_dphi(); TensorValue<double> FF; blitz::Array<double,2> X_node; const MeshBase::const_element_iterator el_begin = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator el_end = mesh.active_local_elements_end(); for (MeshBase::const_element_iterator el_it = el_begin; el_it != el_end; ++el_it) { Elem* const elem = *el_it; fe->reinit(elem); for (unsigned int d = 0; d < NDIM; ++d) { X_dof_map.dof_indices(elem, X_dof_indices(d), d); } const int n_qp = qrule->n_points(); get_values_for_interpolation(X_node, *X_ghost_vec, X_dof_indices); for (int qp = 0; qp < n_qp; ++qp) { jacobian(FF,qp,X_node,dphi); J_integral += abs(FF.det())*JxW[qp]; } } J_integral = SAMRAI_MPI::sumReduction(J_integral); if (SAMRAI_MPI::getRank() == 0) { volume_stream.precision(12); volume_stream.setf(ios::fixed,ios::floatfield); volume_stream << loop_time << " " << J_integral << endl; } } // Close the logging streams. if (SAMRAI_MPI::getRank() == 0) { volume_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 0; }// main