@@ -758,7 +758,6 @@ run(MPI_Comm const &communicator, boost::property_tree::ptree const &database,
758758 std::unique_ptr<adamantine::ThermalPhysicsInterface<dim, MemorySpaceType>>
759759 thermal_physics;
760760 adamantine::HeatSources<dim, dealii::MemorySpace::Host> heat_sources;
761- std::vector<std::pair<double , bool >> scan_path_end;
762761 if (use_thermal_physics)
763762 {
764763 // PropertyTreeInput discretization.thermal.fe_degree
@@ -771,15 +770,6 @@ run(MPI_Comm const &communicator, boost::property_tree::ptree const &database,
771770 fe_degree, quadrature_type, communicator, database, geometry,
772771 material_properties);
773772 heat_sources = thermal_physics->get_heat_sources ();
774-
775- // Store the current end time of each heat source and set a flag that the
776- // scan path has changed
777- auto const &scan_paths = heat_sources.get_scan_paths ();
778- for (auto const &scan_path : scan_paths)
779- {
780- scan_path_end.emplace_back (scan_path.get_segment_list ().back ().end_time ,
781- true );
782- }
783773 post_processor_database.put (" thermal_output" , true );
784774 }
785775
@@ -954,8 +944,13 @@ run(MPI_Comm const &communicator, boost::property_tree::ptree const &database,
954944 database.get_child (" time_stepping" );
955945 // PropertyTreeInput time_stepping.time_step
956946 double time_step = time_stepping_database.get <double >(" time_step" );
947+ // PropertyTreeInput time_stepping.scan_path_for_duration
948+ bool const scan_path_for_duration =
949+ time_stepping_database.get (" scan_path_for_duration" , false );
957950 // PropertyTreeInput time_stepping.duration
958- double const duration = time_stepping_database.get <double >(" duration" );
951+ double const duration = scan_path_for_duration
952+ ? std::numeric_limits<double >::max ()
953+ : time_stepping_database.get <double >(" duration" );
959954
960955 // Extract the refinement database
961956 boost::property_tree::ptree refinement_database =
@@ -1007,41 +1002,44 @@ run(MPI_Comm const &communicator, boost::property_tree::ptree const &database,
10071002 timers[adamantine::add_material_activate].start ();
10081003 if (time > activation_time_end)
10091004 {
1010- double const eps = time_step / 1e10 ;
1011-
1012- // We may need to check if the scan path has been updated. We don't want
1013- // to keep reading the file if it's not going to be updated. Once we
1014- // reach the end of the scan path, we reread the scan path file. If it was
1015- // not updated, we won't try to read it again.
1016- bool scan_path_updated = false ;
1017- for (unsigned int s = 0 ; s < scan_path_end.size (); ++s)
1005+ // If we use scan_path_for_duration, we may need to read the scan path
1006+ // file once again.
1007+ if (scan_path_for_duration)
10181008 {
1019- if ((time > scan_path_end[s].first - eps) && (scan_path_end[s].second ))
1009+ // Check if we have reached the end of current scan path.
1010+ bool need_updated_scan_path = false ;
1011+ auto const &scan_paths = heat_sources.get_scan_paths ();
1012+ for (auto &scan_path : scan_paths)
10201013 {
1021- scan_path_updated = true ;
1022- break ;
1014+ if (time > scan_path.get_segment_list ().back ().end_time )
1015+ {
1016+ need_updated_scan_path = true ;
1017+ break ;
1018+ }
10231019 }
1024- }
1025- if (scan_path_updated)
1026- {
1027- heat_sources.update_scan_paths ();
10281020
1029- auto const &scan_paths = heat_sources.get_scan_paths ();
1030- for (unsigned int s = 0 ; s < scan_path_end.size (); ++s)
1021+ if (need_updated_scan_path)
10311022 {
1032- // Update scan_path_end
1033- double new_end_time =
1034- scan_paths[s].get_segment_list ().back ().end_time ;
1035- scan_path_end[s].second = scan_path_end[s].first != new_end_time;
1036- scan_path_end[s].first = new_end_time;
1037- }
1023+ // Check if we have reached the end of the file. If not, read the
1024+ // updated scan path file
1025+ bool scan_path_end = heat_sources.update_scan_paths ();
1026+
1027+ // If we have reached the end of scan path file for all the heat
1028+ // sources, we just exit.
1029+ if (scan_path_end)
1030+ {
1031+ break ;
1032+ }
10381033
1039- std::tie (material_deposition_boxes, deposition_times, deposition_cos,
1040- deposition_sin) =
1041- adamantine::create_material_deposition_boxes<dim>(geometry_database,
1042- heat_sources);
1034+ std::tie (material_deposition_boxes, deposition_times, deposition_cos,
1035+ deposition_sin) =
1036+ adamantine::create_material_deposition_boxes<dim>(
1037+ geometry_database, heat_sources);
1038+ }
10431039 }
10441040
1041+ double const eps = time_step / 1e10 ;
1042+
10451043 auto activation_start =
10461044 std::lower_bound (deposition_times.begin (), deposition_times.end (),
10471045 time - eps) -
@@ -1480,8 +1478,7 @@ run_ensemble(MPI_Comm const &global_communicator,
14801478 checkpoint_database.get <unsigned int >(" time_steps_between_checkpoint" );
14811479 // PropertyTreeInput checkpoint.filename_prefix
14821480 checkpoint_filename =
1483- checkpoint_database.get <std::string>(" filename_prefix" ) + ' _' +
1484- std::to_string (global_rank);
1481+ checkpoint_database.get <std::string>(" filename_prefix" );
14851482 // PropertyTreeInput checkpoint.overwrite_files
14861483 checkpoint_overwrite = checkpoint_database.get <bool >(" overwrite_files" );
14871484 }
@@ -1600,6 +1597,27 @@ run_ensemble(MPI_Comm const &global_communicator,
16001597 global_communicator, post_processor_expt_database,
16011598 thermal_physics_ensemble[0 ]->get_dof_handler ());
16021599
1600+ // ----- Initialize time and time stepping counters -----
1601+ unsigned int progress = 0 ;
1602+ unsigned int n_time_step = 0 ;
1603+ double time = 0 .;
1604+ double activation_time_end = -1 .;
1605+ if (restart == true )
1606+ {
1607+ if (global_rank == 0 )
1608+ {
1609+ std::cout << " Restarting from file" << std::endl;
1610+ }
1611+ std::ifstream file{restart_filename + " _time.txt" };
1612+ boost::archive::text_iarchive ia{file};
1613+ ia >> time;
1614+ ia >> n_time_step;
1615+ }
1616+
1617+ // PropertyTreeInput geometry.deposition_time
1618+ double const activation_time =
1619+ geometry_database.get <double >(" deposition_time" , 0 .);
1620+
16031621 // ----- Read the experimental data -----
16041622 std::vector<std::vector<double >> frame_time_stamps;
16051623 std::unique_ptr<adamantine::ExperimentalData<dim>> experimental_data;
@@ -1655,30 +1673,26 @@ run_ensemble(MPI_Comm const &global_communicator,
16551673 thermal_physics_ensemble[0 ]->get_dof_handler ()));
16561674 }
16571675 }
1658- }
1659- }
16601676
1661- // ----- Initialize time and time stepping counters -----
1662- unsigned int progress = 0 ;
1663- unsigned int n_time_step = 0 ;
1664- double time = 0 .;
1665- double activation_time_end = -1 .;
1666- if (restart == true )
1667- {
1668- if (global_rank == 0 )
1669- {
1670- std::cout << " Restarting from file" << std::endl;
1677+ // Advance the experimental frame counter upon restart, if necessary
1678+ if (restart)
1679+ {
1680+ bool found_frame = false ;
1681+ while (!found_frame)
1682+ {
1683+ if (frame_time_stamps[0 ][experimental_frame_index + 1 ] < time)
1684+ {
1685+ experimental_frame_index++;
1686+ }
1687+ else
1688+ {
1689+ found_frame = true ;
1690+ }
1691+ }
1692+ }
16711693 }
1672- std::ifstream file{restart_filename + " _time.txt" };
1673- boost::archive::text_iarchive ia{file};
1674- ia >> time;
1675- ia >> n_time_step;
16761694 }
16771695
1678- // PropertyTreeInput geometry.deposition_time
1679- double const activation_time =
1680- geometry_database.get <double >(" deposition_time" , 0 .);
1681-
16821696 // ----- Output the initial solution -----
16831697 std::unique_ptr<adamantine::MechanicalPhysics<dim, p_order, MaterialStates,
16841698 MemorySpaceType>>
@@ -1703,8 +1717,13 @@ run_ensemble(MPI_Comm const &global_communicator,
17031717 refinement_database.get (" time_steps_between_refinement" , 10 );
17041718 // PropertyTreeInput time_stepping.time_step
17051719 double time_step = time_stepping_database.get <double >(" time_step" );
1720+ // PropertyTreeInput time_stepping.scan_path_for_duration
1721+ bool const scan_path_for_duration =
1722+ time_stepping_database.get (" scan_path_for_duration" , false );
17061723 // PropertyTreeInput time_stepping.duration
1707- double const duration = time_stepping_database.get <double >(" duration" );
1724+ double const duration = scan_path_for_duration
1725+ ? std::numeric_limits<double >::max ()
1726+ : time_stepping_database.get <double >(" duration" );
17081727 // PropertyTreeInput post_processor.time_steps_between_output
17091728 unsigned int const time_steps_output =
17101729 post_processor_database.get (" time_steps_between_output" , 1 );
@@ -1781,6 +1800,52 @@ run_ensemble(MPI_Comm const &global_communicator,
17811800 timers[adamantine::add_material_activate].start ();
17821801 if (time > activation_time_end)
17831802 {
1803+ // If we use scan_path_for_duration, we may need to read the scan path
1804+ // file once again.
1805+ if (scan_path_for_duration)
1806+ {
1807+ // Check if we have reached the end of current scan path.
1808+ bool need_updated_scan_path = false ;
1809+ {
1810+ auto const &scan_paths = heat_sources_ensemble[0 ].get_scan_paths ();
1811+ for (auto &scan_path : scan_paths)
1812+ {
1813+ if (time > scan_path.get_segment_list ().back ().end_time )
1814+ {
1815+ need_updated_scan_path = true ;
1816+ break ;
1817+ }
1818+ }
1819+ }
1820+
1821+ if (need_updated_scan_path)
1822+ {
1823+ // Check if we have reached the end of the file. If not, read the
1824+ // updated scan path file. We assume that the scan paths are identical
1825+ // for all the heat sources and thus, we can use
1826+ // heat_sources_ensemble[0] to get the material deposition boxes and
1827+ // times. We still need every ensemble member to read the scan path in
1828+ // order to compute the correct heat sources.
1829+ bool scan_path_end = true ;
1830+ for (unsigned int member = 0 ; member < local_ensemble_size; ++member)
1831+ {
1832+ scan_path_end &= heat_sources_ensemble[member].update_scan_paths ();
1833+ }
1834+
1835+ // If we have reached the end of scan path file for all the heat
1836+ // sources, we just exit.
1837+ if (scan_path_end)
1838+ {
1839+ break ;
1840+ }
1841+
1842+ std::tie (material_deposition_boxes, deposition_times, deposition_cos,
1843+ deposition_sin) =
1844+ adamantine::create_material_deposition_boxes<dim>(
1845+ geometry_database, heat_sources_ensemble[0 ]);
1846+ }
1847+ }
1848+
17841849 double const eps = time_step / 1e12 ;
17851850 auto activation_start =
17861851 std::lower_bound (deposition_times.begin (), deposition_times.end (),
0 commit comments