diff --git a/apps/tests/core/scene.cpp b/apps/tests/core/scene.cpp index 127a97a96..df4ad4a85 100644 --- a/apps/tests/core/scene.cpp +++ b/apps/tests/core/scene.cpp @@ -293,9 +293,7 @@ TEST_CASE("scene_commit", "[scene]") std::ranges::transform(pos_view.begin(), pos_view.end(), pos_view.begin(), - [](const auto& p) { - return p + Vector3{1, 1, 1}; - }); + [](const auto& p) { return p + Vector3{1, 1, 1}; }); SceneSnapshotCommit commit = scene - snapshot; REQUIRE(commit.contact_models().attribute_collection().find("topo") == nullptr); @@ -358,3 +356,49 @@ TEST_CASE("scene_commit_empty", "[scene]") .find("myattribute") != nullptr); } + + +TEST_CASE("dynamic_dt_config", "[scene]") +{ + using namespace uipc; + using namespace uipc::core; + using namespace uipc::geometry; + + Scene scene; + + // Default dt should be 0.01 + { + auto dt_slot = scene.config().find("dt"); + REQUIRE(dt_slot != nullptr); + REQUIRE(dt_slot->view()[0] == Catch::Approx(0.01)); + } + + // Change dt via config + { + auto dt_slot = scene.config().find("dt"); + view(*dt_slot)[0] = 0.005; + } + + // Read back via config + { + auto dt_slot = scene.config().find("dt"); + REQUIRE(dt_slot->view()[0] == Catch::Approx(0.005)); + } + + // Read back via SceneVisitor + { + backend::SceneVisitor visitor{scene}; + REQUIRE(visitor.dt() == Catch::Approx(0.005)); + } + + // Change again and verify + { + auto dt_slot = scene.config().find("dt"); + view(*dt_slot)[0] = 0.02; + } + + { + backend::SceneVisitor visitor{scene}; + REQUIRE(visitor.dt() == Catch::Approx(0.02)); + } +} diff --git a/apps/tests/sim_case/93_dynamic_dt.cpp b/apps/tests/sim_case/93_dynamic_dt.cpp new file mode 100644 index 000000000..c4c8b0f09 --- /dev/null +++ b/apps/tests/sim_case/93_dynamic_dt.cpp @@ -0,0 +1,175 @@ +#include +#include +#include + +TEST_CASE("93_dynamic_dt", "[abd][dynamic_dt]") +{ + using namespace uipc; + using namespace uipc::core; + using namespace uipc::geometry; + using namespace uipc::constitution; + + auto output_path = AssetDir::output_path(UIPC_RELATIVE_SOURCE_FILE); + + Engine engine{"cuda", output_path}; + World world{engine}; + + auto config = test::Scene::default_config(); + config["gravity"] = Vector3{0, -9.8, 0}; + config["contact"]["enable"] = false; + config["dt"] = 0.01; + test::Scene::dump_config(config, output_path); + + Scene scene{config}; + { + AffineBodyConstitution abd; + + auto object = scene.objects().create("falling_tet"); + + vector Ts = {Vector4i{0, 1, 2, 3}}; + vector Vs = {Vector3{0, 1, 0}, + Vector3{0, 0, 1}, + Vector3{-std::sqrt(3) / 2, 0, -0.5}, + Vector3{std::sqrt(3) / 2, 0, -0.5}}; + + std::transform( + Vs.begin(), Vs.end(), Vs.begin(), [](auto& v) { return v * 0.3; }); + + auto mesh = tetmesh(Vs, Ts); + label_surface(mesh); + label_triangle_orient(mesh); + + mesh.instances().resize(1); + abd.apply_to(mesh, 100.0_MPa); + + auto trans_view = view(mesh.transforms()); + auto is_fixed = mesh.instances().find(builtin::is_fixed); + auto is_fixed_view = view(*is_fixed); + + Transform t = Transform::Identity(); + t.translation() = Vector3::UnitY() * 2; + trans_view[0] = t.matrix(); + is_fixed_view[0] = 0; + + object->geometries().create(mesh); + } + + world.init(scene); + REQUIRE(world.is_valid()); + + auto geo_slots = scene.geometries().find(0); + auto geo_slot = geo_slots.geometry; + + auto read_center_y = [&]() -> Float + { + auto geo = geo_slot->geometry().as(); + auto trans_view = geo->transforms().view(); + Matrix4x4 T = trans_view[0]; + return T(1, 3); + }; + + Float prev_y = read_center_y(); + + // Run frame 1 with dt=0.01 + world.advance(); + REQUIRE(world.is_valid()); + world.retrieve(); + Float y_after_1 = read_center_y(); + Float dy_frame1 = prev_y - y_after_1; + REQUIRE(dy_frame1 > 0.0); + + // Now change dt to 0.005 and reset to the same starting position + // by running a fresh scene. Instead, we compare the first-frame displacement + // at two different dt values. Run additional frames to let it settle. + // + // Simpler approach: compare dy/dt ratio. + // At frame 1 with dt=0.01: dy1 = 0.5 * g * dt^2 = 0.5 * 9.8 * 0.0001 = 0.00049 + // With dt=0.005: dy = 0.5 * g * dt^2 = 0.5 * 9.8 * 0.000025 = 0.0001225 + // ratio should be ~4x + + // Reset: create a second simulation with dt=0.005 from the start + Engine engine2{"cuda", output_path}; + World world2{engine2}; + + auto config2 = test::Scene::default_config(); + config2["gravity"] = Vector3{0, -9.8, 0}; + config2["contact"]["enable"] = false; + config2["dt"] = 0.005; + + Scene scene2{config2}; + { + AffineBodyConstitution abd2; + + auto object2 = scene2.objects().create("falling_tet"); + + vector Ts2 = {Vector4i{0, 1, 2, 3}}; + vector Vs2 = {Vector3{0, 1, 0}, + Vector3{0, 0, 1}, + Vector3{-std::sqrt(3) / 2, 0, -0.5}, + Vector3{std::sqrt(3) / 2, 0, -0.5}}; + + std::transform( + Vs2.begin(), Vs2.end(), Vs2.begin(), [](auto& v) { return v * 0.3; }); + + auto mesh2 = tetmesh(Vs2, Ts2); + label_surface(mesh2); + label_triangle_orient(mesh2); + + mesh2.instances().resize(1); + abd2.apply_to(mesh2, 100.0_MPa); + + auto trans_view2 = view(mesh2.transforms()); + auto is_fixed2 = mesh2.instances().find(builtin::is_fixed); + auto is_fixed_view2 = view(*is_fixed2); + + Transform t2 = Transform::Identity(); + t2.translation() = Vector3::UnitY() * 2; + trans_view2[0] = t2.matrix(); + is_fixed_view2[0] = 0; + + object2->geometries().create(mesh2); + } + + world2.init(scene2); + REQUIRE(world2.is_valid()); + + auto geo_slots2 = scene2.geometries().find(0); + auto geo_slot2 = geo_slots2.geometry; + + auto read_center_y2 = [&]() -> Float + { + auto geo2 = geo_slot2->geometry().as(); + auto trans_view = geo2->transforms().view(); + Matrix4x4 T = trans_view[0]; + return T(1, 3); + }; + + Float prev_y2 = read_center_y2(); + + world2.advance(); + REQUIRE(world2.is_valid()); + world2.retrieve(); + Float y_after_1_small = read_center_y2(); + Float dy_frame1_small = prev_y2 - y_after_1_small; + REQUIRE(dy_frame1_small > 0.0); + + // With dt halved, first-frame displacement (0.5*g*dt^2) should be ~4x smaller + REQUIRE(dy_frame1_small < dy_frame1); + + // Now test dynamic dt change: change dt in scene2 from 0.005 to 0.01 + { + auto dt_slot = scene2.config().find("dt"); + view(*dt_slot)[0] = 0.01; + } + + // Run one more frame with the changed dt + Float prev_y2_before = read_center_y2(); + world2.advance(); + REQUIRE(world2.is_valid()); + world2.retrieve(); + Float y_after_2_changed = read_center_y2(); + Float dy_frame2_changed = prev_y2_before - y_after_2_changed; + + // After changing dt from 0.005 to 0.01, the displacement should increase + REQUIRE(dy_frame2_changed > dy_frame1_small); +} diff --git a/include/uipc/backend/visitors/scene_visitor.h b/include/uipc/backend/visitors/scene_visitor.h index 05573312d..da81d9e7d 100644 --- a/include/uipc/backend/visitors/scene_visitor.h +++ b/include/uipc/backend/visitors/scene_visitor.h @@ -46,6 +46,7 @@ class UIPC_CORE_API SceneVisitor span pending_destroy_ids() const noexcept; const geometry::AttributeCollection& config() const noexcept; + Float dt() const noexcept; const core::ConstitutionTabular& constitution_tabular() const noexcept; core::ConstitutionTabular& constitution_tabular() noexcept; diff --git a/src/backends/cuda/active_set_system/global_active_set_manager.cu b/src/backends/cuda/active_set_system/global_active_set_manager.cu index 1bf754adb..7d3418b34 100644 --- a/src/backends/cuda/active_set_system/global_active_set_manager.cu +++ b/src/backends/cuda/active_set_system/global_active_set_manager.cu @@ -557,7 +557,7 @@ void GlobalActiveSetManager::Impl::update_lambda() { auto PT = PTs(idx); auto mu = min(min(mu_vertices(PT(0)), mu_vertices(PT(1))), - min(mu_vertices(PT(2)), mu_vertices(PT(3)))); + min(mu_vertices(PT(2)), mu_vertices(PT(3)))); auto d_grad = PT_d_grad(idx); auto d = d0(idx), &lambda = PT_lambda(idx), d_shift = 0.0; auto& cnt = PT_cnt(idx); @@ -598,7 +598,7 @@ void GlobalActiveSetManager::Impl::update_lambda() { auto EE = EEs(idx); auto mu = min(min(mu_vertices(EE(0)), mu_vertices(EE(1))), - min(mu_vertices(EE(2)), mu_vertices(EE(3)))); + min(mu_vertices(EE(2)), mu_vertices(EE(3)))); auto d_grad = EE_d_grad(idx); auto d = d0(idx), &lambda = EE_lambda(idx), d_shift = 0.0; auto& cnt = EE_cnt(idx); @@ -851,16 +851,18 @@ muda::BufferView GlobalActiveSetManager::StiffnessEstimateInfo::mu_vertic Float GlobalActiveSetManager::StiffnessEstimateInfo::dt() const noexcept { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } void GlobalActiveSetManager::Impl::init(WorldVisitor& world) { - auto config = world.scene().config(); - dt = config.find("dt")->view()[0]; + auto config = world.scene().config(); + dt_attr = config.find("dt"); + UIPC_ASSERT(dt_attr, "Scene config must have a 'dt' attribute."); decay_factor = config.find("contact/al-ipc/decay_factor")->view()[0]; toi_threshold = config.find("contact/al-ipc/toi_threshold")->view()[0]; - alpha_lower_bound = config.find("contact/al-ipc/alpha_lower_bound")->view()[0]; + alpha_lower_bound = + config.find("contact/al-ipc/alpha_lower_bound")->view()[0]; energy_enabled = true; } diff --git a/src/backends/cuda/active_set_system/global_active_set_manager.h b/src/backends/cuda/active_set_system/global_active_set_manager.h index 437c1e02b..378617563 100644 --- a/src/backends/cuda/active_set_system/global_active_set_manager.h +++ b/src/backends/cuda/active_set_system/global_active_set_manager.h @@ -106,11 +106,12 @@ class GlobalActiveSetManager final : public SimSystem muda::DeviceBuffer non_penetrate_positions; - Float decay_factor, dt; - Float toi_threshold; - Float alpha_lower_bound; - bool energy_enabled; - bool should_discard_friction_candidates = false; + Float decay_factor; + S> dt_attr; + Float toi_threshold; + Float alpha_lower_bound; + bool energy_enabled; + bool should_discard_friction_candidates = false; Float m_reserve_ratio = 1.5; diff --git a/src/backends/cuda/affine_body/abd_linear_subsystem.cu b/src/backends/cuda/affine_body/abd_linear_subsystem.cu index bf292088c..b4f4e4ec9 100644 --- a/src/backends/cuda/affine_body/abd_linear_subsystem.cu +++ b/src/backends/cuda/affine_body/abd_linear_subsystem.cu @@ -38,8 +38,8 @@ void ABDLinearSubsystem::do_build(DiagLinearSubsystem::BuildInfo& info) { m_impl.affine_body_dynamics = require(); m_impl.affine_body_vertex_reporter = require(); - auto attr = world().scene().config().find("dt"); - m_impl.dt = attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); m_impl.dytopo_effect_receiver = find(); } @@ -201,6 +201,8 @@ void ABDLinearSubsystem::Impl::_assemble_kinetic_shape(IndexT& hess_offset, { using namespace muda; + Float dt = dt_attr->view()[0]; + // Collect Kinetic ABDLinearSubsystem::ComputeGradientHessianInfo this_info{ info.gradient_only(), body_id_to_kinetic_gradient, body_id_to_kinetic_hessian, dt}; diff --git a/src/backends/cuda/affine_body/abd_linear_subsystem.h b/src/backends/cuda/affine_body/abd_linear_subsystem.h index b4ba1ea8a..01ff640ae 100644 --- a/src/backends/cuda/affine_body/abd_linear_subsystem.h +++ b/src/backends/cuda/affine_body/abd_linear_subsystem.h @@ -61,9 +61,9 @@ class ABDLinearSubsystem final : public DiagLinearSubsystem private: friend class ABDLinearSubsystem; friend class ABDLinearSubsystemReporter; - SizeT m_gradient_count = 0; - SizeT m_hessian_count = 0; - bool m_gradient_only = false; + SizeT m_gradient_count = 0; + SizeT m_hessian_count = 0; + bool m_gradient_only = false; mutable bool m_gradient_only_checked = false; }; @@ -99,8 +99,8 @@ class ABDLinearSubsystem final : public DiagLinearSubsystem void _assemble_reporters(IndexT& offset, GlobalLinearSystem::DiagInfo& info); void _assemble_dytopo_effect(IndexT& offset, GlobalLinearSystem::DiagInfo& info); - void accuracy_check(GlobalLinearSystem::AccuracyInfo& info); - void retrieve_solution(GlobalLinearSystem::SolutionInfo& info); + void accuracy_check(GlobalLinearSystem::AccuracyInfo& info); + void retrieve_solution(GlobalLinearSystem::SolutionInfo& info); Float diag_norm(); Float mass_norm(); @@ -129,7 +129,7 @@ class ABDLinearSubsystem final : public DiagLinearSubsystem muda::DeviceBuffer block_norm; muda::DeviceVar reduced_norm; - Float dt = 0.0f; // time step, used in assemble + S> dt_attr; }; private: diff --git a/src/backends/cuda/affine_body/abd_tolerance_checker.cu b/src/backends/cuda/affine_body/abd_tolerance_checker.cu index c00ea65b5..b719da172 100644 --- a/src/backends/cuda/affine_body/abd_tolerance_checker.cu +++ b/src/backends/cuda/affine_body/abd_tolerance_checker.cu @@ -1,5 +1,6 @@ #include #include +#include namespace uipc::backend::cuda { @@ -8,21 +9,22 @@ class ABDToleranceChecker final : public NewtonToleranceChecker public: using NewtonToleranceChecker::NewtonToleranceChecker; - SimSystemSlot affine_body_dynamics; - Float abs_tol = 0.0; - muda::DeviceVar success; + SimSystemSlot affine_body_dynamics; + S> dt_attr; + Float transrate_tol = 0.0; + Float abs_tol = 0.0; + muda::DeviceVar success; IndexT h_success = 1; // 1 means success, 0 means failure // Inherited via NewtonToleranceChecker void do_build(BuildInfo& info) override { - affine_body_dynamics = require(); - auto& config = world().scene().config(); - auto dt_attr = config.find("dt"); - Float dt = dt_attr->view()[0]; - auto transrate_tol_attr = config.find("newton/transrate_tol"); - Float transrate_tol = transrate_tol_attr->view()[0]; - abs_tol = transrate_tol * dt; + affine_body_dynamics = require(); + auto& config = world().scene().config(); + dt_attr = config.find("dt"); + UIPC_ASSERT(dt_attr, "Scene config must have a 'dt' attribute."); + auto transrate_tol_attr = config.find("newton/transrate_tol"); + transrate_tol = transrate_tol_attr->view()[0]; } void do_init(InitInfo& info) override {} @@ -31,6 +33,7 @@ class ABDToleranceChecker final : public NewtonToleranceChecker void do_check(CheckResultInfo& info) override { + abs_tol = transrate_tol * dt_attr->view()[0]; auto dqs = affine_body_dynamics->dqs(); using namespace muda; BufferLaunch().fill(success.view(), 1); // reset success flag diff --git a/src/backends/cuda/affine_body/affine_body_animator.cu b/src/backends/cuda/affine_body/affine_body_animator.cu index 442d4e301..6178fd9df 100644 --- a/src/backends/cuda/affine_body/affine_body_animator.cu +++ b/src/backends/cuda/affine_body/affine_body_animator.cu @@ -13,8 +13,8 @@ void AffineBodyAnimator::do_build(BuildInfo& info) { m_impl.affine_body_dynamics = &require(); m_impl.global_animator = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void AffineBodyAnimator::add_constraint(AffineBodyConstraint* constraint) @@ -142,23 +142,21 @@ void AffineBodyAnimator::Impl::step() void AffineBodyAnimator::compute_energy(ABDLineSearchReporter::ComputeEnergyInfo& info) { + Float dt = m_impl.dt_attr->view()[0]; for(auto constraint : m_impl.constraints.view()) { - ComputeEnergyInfo this_info{&m_impl, constraint->m_index, m_impl.dt, info.energies()}; + ComputeEnergyInfo this_info{&m_impl, constraint->m_index, dt, info.energies()}; constraint->compute_energy(this_info); } } void AffineBodyAnimator::compute_gradient_hessian(ABDLinearSubsystem::AssembleInfo& info) { + Float dt = m_impl.dt_attr->view()[0]; for(auto constraint : m_impl.constraints.view()) { - ComputeGradientHessianInfo this_info{&m_impl, - constraint->m_index, - m_impl.dt, - info.gradients(), - info.hessians(), - info.gradient_only()}; + ComputeGradientHessianInfo this_info{ + &m_impl, constraint->m_index, dt, info.gradients(), info.hessians(), info.gradient_only()}; constraint->compute_gradient_hessian(this_info); } } diff --git a/src/backends/cuda/affine_body/affine_body_animator.h b/src/backends/cuda/affine_body/affine_body_animator.h index ba041174d..600da016d 100644 --- a/src/backends/cuda/affine_body/affine_body_animator.h +++ b/src/backends/cuda/affine_body/affine_body_animator.h @@ -90,11 +90,11 @@ class AffineBodyAnimator final : public Animator { public: ComputeGradientHessianInfo(Impl* impl, - SizeT index, - Float dt, - muda::DoubletVectorView gradients, - muda::TripletMatrixView hessians, - bool gradient_only) + SizeT index, + Float dt, + muda::DoubletVectorView gradients, + muda::TripletMatrixView hessians, + bool gradient_only) : BaseInfo(impl, index, dt) , m_gradients(gradients) , m_hessians(hessians) @@ -128,11 +128,11 @@ class AffineBodyAnimator final : public Animator private: friend class AffineBodyAnimator; friend class AffineBodyConstraint; - SizeT m_hessian_block_count = 0; - SizeT m_gradient_segment_count = 0; - SizeT m_energy_count = 0; - bool m_gradient_only = false; - mutable bool m_gradient_only_checked = false; + SizeT m_hessian_block_count = 0; + SizeT m_gradient_segment_count = 0; + SizeT m_energy_count = 0; + bool m_gradient_only = false; + mutable bool m_gradient_only_checked = false; }; class Impl @@ -141,7 +141,7 @@ class AffineBodyAnimator final : public Animator void init(backend::WorldVisitor& world); void step(); - Float dt = 0.0; + S> dt_attr; AffineBodyDynamics* affine_body_dynamics = nullptr; GlobalAnimator* global_animator = nullptr; diff --git a/src/backends/cuda/affine_body/inter_affine_body_animator.cu b/src/backends/cuda/affine_body/inter_affine_body_animator.cu index fa04aa5d4..46ee0b18c 100644 --- a/src/backends/cuda/affine_body/inter_affine_body_animator.cu +++ b/src/backends/cuda/affine_body/inter_affine_body_animator.cu @@ -14,8 +14,8 @@ void InterAffineBodyAnimator::do_build(BuildInfo& info) m_impl.affine_body_dynamics = &require(); m_impl.manager = &require(); m_impl.global_animator = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void InterAffineBodyAnimator::add_constraint(InterAffineBodyConstraint* constraint) @@ -143,24 +143,21 @@ void InterAffineBodyAnimator::Impl::step() void InterAffineBodyAnimator::compute_energy(ABDLineSearchReporter::ComputeEnergyInfo& info) { + Float dt = m_impl.dt_attr->view()[0]; for(auto constraint : m_impl.constraints.view()) { - ComputeEnergyInfo this_info{&m_impl, constraint->m_index, m_impl.dt, info.energies()}; + ComputeEnergyInfo this_info{&m_impl, constraint->m_index, dt, info.energies()}; constraint->compute_energy(this_info); } } void InterAffineBodyAnimator::compute_gradient_hessian(ABDLinearSubsystem::AssembleInfo& info) { + Float dt = m_impl.dt_attr->view()[0]; for(auto constraint : m_impl.constraints.view()) { GradientHessianInfo this_info{ - &m_impl, - constraint->m_index, - m_impl.dt, - info.gradients(), - info.hessians(), - info.gradient_only()}; + &m_impl, constraint->m_index, dt, info.gradients(), info.hessians(), info.gradient_only()}; constraint->compute_gradient_hessian(this_info); } } @@ -304,7 +301,8 @@ class InterAffineBodyAnimatorLinearSubsystemReporter final : public ABDLinearSub gradient_count = animator->m_impl.constraint_gradient_offsets_counts.total_count(); if(!info.gradient_only()) - hessian_count = animator->m_impl.constraint_hessian_offsets_counts.total_count(); + hessian_count = + animator->m_impl.constraint_hessian_offsets_counts.total_count(); info.gradient_count(gradient_count); info.hessian_count(hessian_count); diff --git a/src/backends/cuda/affine_body/inter_affine_body_animator.h b/src/backends/cuda/affine_body/inter_affine_body_animator.h index d7ecaf8e8..525ab3a6a 100644 --- a/src/backends/cuda/affine_body/inter_affine_body_animator.h +++ b/src/backends/cuda/affine_body/inter_affine_body_animator.h @@ -134,11 +134,11 @@ class InterAffineBodyAnimator final : public Animator private: friend class InterAffineBodyAnimator; friend class InterAffineBodyConstraint; - SizeT m_hessian_block_count = 0; - SizeT m_gradient_segment_count = 0; - SizeT m_energy_count = 0; - bool m_gradient_only = false; - mutable bool m_gradient_only_checked = false; + SizeT m_hessian_block_count = 0; + SizeT m_gradient_segment_count = 0; + SizeT m_energy_count = 0; + bool m_gradient_only = false; + mutable bool m_gradient_only_checked = false; }; class Impl @@ -147,7 +147,7 @@ class InterAffineBodyAnimator final : public Animator void init(backend::WorldVisitor& world); void step(); - Float dt = 0.0; + S> dt_attr; AffineBodyDynamics* affine_body_dynamics = nullptr; InterAffineBodyConstitutionManager* manager = nullptr; diff --git a/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.cu b/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.cu index efd9c0053..f45877e00 100644 --- a/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.cu +++ b/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.cu @@ -36,8 +36,8 @@ REGISTER_SIM_SYSTEM(InterAffineBodyConstitutionManager); void InterAffineBodyConstitutionManager::do_build() { m_impl.affine_body_dynamics = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void InterAffineBodyConstitutionManager::Impl::init(SceneVisitor& scene) @@ -65,7 +65,7 @@ void InterAffineBodyConstitutionManager::Impl::init(SceneVisitor& scene) for(auto&& [i, slot] : enumerate(geo_slots)) { - auto& geo = slot->geometry(); + auto& geo = slot->geometry(); auto base_uid = geo.meta().find(builtin::constitution_uid); if(base_uid) @@ -162,7 +162,8 @@ void InterAffineBodyConstitutionManager::Impl::report_energy_extent(ABDLineSearc void InterAffineBodyConstitutionManager::Impl::compute_energy(ABDLineSearchReporter::ComputeEnergyInfo& info) { - auto constitution_view = constitutions.view(); + Float dt = dt_attr->view()[0]; + auto constitution_view = constitutions.view(); for(auto&& [i, c] : enumerate(constitution_view)) { EnergyInfo this_info{this, c->m_index, dt, info.energies()}; @@ -196,7 +197,8 @@ void InterAffineBodyConstitutionManager::Impl::report_gradient_hessian_extent( void InterAffineBodyConstitutionManager::Impl::compute_gradient_hessian(ABDLinearSubsystem::AssembleInfo& info) { - auto constitution_view = constitutions.view(); + Float dt = dt_attr->view()[0]; + auto constitution_view = constitutions.view(); for(auto&& [i, c] : enumerate(constitution_view)) { GradientHessianInfo this_info{ @@ -312,7 +314,7 @@ geometry::SimplicialComplex* InterAffineBodyConstitutionManager::FilteredInfo::b Float InterAffineBodyConstitutionManager::BaseInfo::dt() const noexcept { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } muda::CBufferView InterAffineBodyConstitutionManager::BaseInfo::qs() const noexcept diff --git a/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.h b/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.h index add9ad9ec..0ab5c8f2f 100644 --- a/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.h +++ b/src/backends/cuda/affine_body/inter_affine_body_constitution_manager.h @@ -161,14 +161,14 @@ class InterAffineBodyConstitutionManager final : public SimSystem void report_gradient_hessian_extent(ABDLinearSubsystem::ReportExtentInfo& info); void compute_gradient_hessian(ABDLinearSubsystem::AssembleInfo& info); - Float dt = 0.0; + S> dt_attr; AffineBodyDynamics* affine_body_dynamics = nullptr; SimSystemSlotCollection constitutions; unordered_map uid_to_index; // Base-constitution geometry infos used by animator/constraint pipeline. - vector inter_geo_infos; + vector inter_geo_infos; // Base + extra constitution geometry infos used by constitution filtering. vector constitution_inter_geo_infos; OffsetCountCollection constitution_geo_info_offsets_counts; diff --git a/src/backends/cuda/contact_system/al_simplex_frictional_contact.cu b/src/backends/cuda/contact_system/al_simplex_frictional_contact.cu index 8a4cfd34a..ef89bb640 100644 --- a/src/backends/cuda/contact_system/al_simplex_frictional_contact.cu +++ b/src/backends/cuda/contact_system/al_simplex_frictional_contact.cu @@ -13,8 +13,8 @@ void ALSimplexFrictionalContact::do_build(ContactReporter::BuildInfo& info) m_impl.global_surf_manager = require(); m_impl.global_active_set_manager = require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void ALSimplexFrictionalContact::do_report_energy_extent(GlobalContactManager::EnergyExtentInfo& info) @@ -77,7 +77,7 @@ void ALSimplexFrictionalContact::Impl::do_compute_energy(GlobalContactManager::E contact_ids = global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], PTs = PTs.cviewer().name("PTs"), lambda = PT_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), @@ -114,7 +114,7 @@ void ALSimplexFrictionalContact::Impl::do_compute_energy(GlobalContactManager::E contact_ids = global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], EEs = EEs.cviewer().name("EEs"), lambda = EE_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), @@ -176,7 +176,7 @@ void ALSimplexFrictionalContact::Impl::do_assemble(GlobalContactManager::Gradien contact_ids = global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], PTs = PTs.cviewer().name("PTs"), lambda = PT_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), @@ -223,7 +223,7 @@ void ALSimplexFrictionalContact::Impl::do_assemble(GlobalContactManager::Gradien contact_ids = global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], EEs = EEs.cviewer().name("EEs"), lambda = EE_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), diff --git a/src/backends/cuda/contact_system/al_simplex_frictional_contact.h b/src/backends/cuda/contact_system/al_simplex_frictional_contact.h index f9d42ca9e..54197e368 100644 --- a/src/backends/cuda/contact_system/al_simplex_frictional_contact.h +++ b/src/backends/cuda/contact_system/al_simplex_frictional_contact.h @@ -20,7 +20,7 @@ class ALSimplexFrictionalContact : public ContactReporter SimSystemSlot global_surf_manager; SimSystemSlot global_active_set_manager; - Float dt; + S> dt_attr; void do_compute_energy(GlobalContactManager::EnergyInfo& info); void do_assemble(GlobalContactManager::GradientHessianInfo& info); diff --git a/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.cu b/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.cu index f39f0fa64..ee82365d5 100644 --- a/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.cu +++ b/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.cu @@ -17,8 +17,8 @@ void ALVertexHalfPlaneFrictionalContact::do_build(ContactReporter::BuildInfo& in m_impl.half_plane_vertex_reporter = require(); m_impl.half_plane = require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void ALVertexHalfPlaneFrictionalContact::do_report_energy_extent(GlobalContactManager::EnergyExtentInfo& info) @@ -75,7 +75,7 @@ void ALVertexHalfPlaneFrictionalContact::Impl::do_compute_energy(GlobalContactMa global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), half_plane_vertex_offset = half_plane_vertex_reporter->vertex_offset(), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], PHs = PHs.cviewer().name("PHs"), lambda = PH_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), @@ -124,7 +124,7 @@ void ALVertexHalfPlaneFrictionalContact::Impl::do_assemble(GlobalContactManager: global_vertex_manager->contact_element_ids().cviewer().name("contact_element_ids"), half_plane_vertex_offset = half_plane_vertex_reporter->vertex_offset(), eps_v = global_contact_manager->eps_velocity(), - dt = dt, + dt = dt_attr->view()[0], PHs = PHs.cviewer().name("PHs"), lambda = PH_lambda.cviewer().name("lambda"), x = x.cviewer().name("x"), diff --git a/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.h b/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.h index 6965caa0a..1849ec038 100644 --- a/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.h +++ b/src/backends/cuda/contact_system/al_vertex_half_plane_frictional_contact.h @@ -22,7 +22,7 @@ class ALVertexHalfPlaneFrictionalContact : public ContactReporter SimSystemSlot half_plane_vertex_reporter; SimSystemSlot half_plane; - Float dt; + S> dt_attr; void do_compute_energy(GlobalContactManager::EnergyInfo& info); void do_assemble(GlobalContactManager::GradientHessianInfo& info); diff --git a/src/backends/cuda/contact_system/global_contact_manager.cu b/src/backends/cuda/contact_system/global_contact_manager.cu index 72dcd2ec3..eea4f16f5 100644 --- a/src/backends/cuda/contact_system/global_contact_manager.cu +++ b/src/backends/cuda/contact_system/global_contact_manager.cu @@ -41,8 +41,8 @@ void GlobalContactManager::do_build() auto d_hat_attr = config.find("contact/d_hat"); m_impl.d_hat = d_hat_attr->view()[0]; - auto dt_attr = config.find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = config.find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); auto eps_velocity_attr = config.find("contact/eps_velocity"); m_impl.eps_velocity = eps_velocity_attr->view()[0]; diff --git a/src/backends/cuda/contact_system/global_contact_manager.h b/src/backends/cuda/contact_system/global_contact_manager.h index 08db9dd1e..86661f45e 100644 --- a/src/backends/cuda/contact_system/global_contact_manager.h +++ b/src/backends/cuda/contact_system/global_contact_manager.h @@ -72,10 +72,10 @@ class GlobalContactManager final : public SimSystem muda::DeviceBuffer2D subscene_mask_tabular; Float reserve_ratio = 1.1; - Float d_hat = 0.0; - Float kappa = 0.0; - Float dt = 0.0; - Float eps_velocity = 0.0; + Float d_hat = 0.0; + Float kappa = 0.0; + S> dt_attr; + Float eps_velocity = 0.0; /*********************************************************************** @@ -100,7 +100,6 @@ class GlobalContactManager final : public SimSystem muda::CBuffer2DView subscene_mask_tabular() const noexcept; - protected: virtual void do_build() override; diff --git a/src/backends/cuda/contact_system/simplex_frictional_contact.cu b/src/backends/cuda/contact_system/simplex_frictional_contact.cu index 631f96a1c..e88b4cde9 100644 --- a/src/backends/cuda/contact_system/simplex_frictional_contact.cu +++ b/src/backends/cuda/contact_system/simplex_frictional_contact.cu @@ -17,8 +17,8 @@ void SimplexFrictionalContact::do_build(ContactReporter::BuildInfo& info) m_impl.global_contact_manager = &require(); m_impl.global_vertex_manager = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); @@ -79,7 +79,7 @@ void SimplexFrictionalContact::do_compute_energy(GlobalContactManager::EnergyInf void SimplexFrictionalContact::do_report_gradient_hessian_extent(GlobalContactManager::GradientHessianExtentInfo& info) { - auto& filter = m_impl.simplex_trajectory_filter; + auto& filter = m_impl.simplex_trajectory_filter; bool gradient_only = info.gradient_only(); m_impl.PT_count = filter->friction_PTs().size(); @@ -93,10 +93,9 @@ void SimplexFrictionalContact::do_report_gradient_hessian_extent(GlobalContactMa // expand to hessian3x3 and graident3 SizeT contact_gradient_count = 4 * count_4 + 3 * count_3 + 2 * count_2; - SizeT contact_hessian_count = PTHalfHessianSize * m_impl.PT_count - + EEHalfHessianSize * m_impl.EE_count - + PEHalfHessianSize * m_impl.PE_count - + PPHalfHessianSize * m_impl.PP_count; + SizeT contact_hessian_count = + PTHalfHessianSize * m_impl.PT_count + EEHalfHessianSize * m_impl.EE_count + + PEHalfHessianSize * m_impl.PE_count + PPHalfHessianSize * m_impl.PP_count; info.gradient_count(contact_gradient_count); info.hessian_count(gradient_only ? 0 : contact_hessian_count); @@ -316,7 +315,7 @@ muda::CBufferView SimplexFrictionalContact::BaseInfo::d_hats() const Float SimplexFrictionalContact::BaseInfo::dt() const { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } Float SimplexFrictionalContact::BaseInfo::eps_velocity() const diff --git a/src/backends/cuda/contact_system/simplex_frictional_contact.h b/src/backends/cuda/contact_system/simplex_frictional_contact.h index b0b9e2598..2afc950ca 100644 --- a/src/backends/cuda/contact_system/simplex_frictional_contact.h +++ b/src/backends/cuda/contact_system/simplex_frictional_contact.h @@ -126,11 +126,11 @@ class SimplexFrictionalContact : public ContactReporter SimSystemSlot simplex_trajectory_filter; - SizeT PT_count = 0; - SizeT EE_count = 0; - SizeT PE_count = 0; - SizeT PP_count = 0; - Float dt = 0; + SizeT PT_count = 0; + SizeT EE_count = 0; + SizeT PE_count = 0; + SizeT PP_count = 0; + S> dt_attr; muda::CBufferView PT_energies; muda::CDoubletVectorView PT_gradients; diff --git a/src/backends/cuda/contact_system/simplex_normal_contact.cu b/src/backends/cuda/contact_system/simplex_normal_contact.cu index e115c2f21..9c2b79b97 100644 --- a/src/backends/cuda/contact_system/simplex_normal_contact.cu +++ b/src/backends/cuda/contact_system/simplex_normal_contact.cu @@ -11,8 +11,8 @@ void SimplexNormalContact::do_build(ContactReporter::BuildInfo& info) m_impl.global_trajectory_filter = require(); m_impl.global_contact_manager = require(); m_impl.global_vertex_manager = require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); @@ -72,7 +72,7 @@ void SimplexNormalContact::do_compute_energy(GlobalContactManager::EnergyInfo& i void SimplexNormalContact::do_report_gradient_hessian_extent(GlobalContactManager::GradientHessianExtentInfo& info) { - auto& filter = m_impl.simplex_trajectory_filter; + auto& filter = m_impl.simplex_trajectory_filter; bool gradient_only = info.gradient_only(); m_impl.PT_count = filter->PTs().size(); @@ -310,7 +310,7 @@ muda::CBufferView SimplexNormalContact::BaseInfo::d_hats() const Float SimplexNormalContact::BaseInfo::dt() const { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } Float SimplexNormalContact::BaseInfo::eps_velocity() const diff --git a/src/backends/cuda/contact_system/simplex_normal_contact.h b/src/backends/cuda/contact_system/simplex_normal_contact.h index ae85ce272..7c6044d6f 100644 --- a/src/backends/cuda/contact_system/simplex_normal_contact.h +++ b/src/backends/cuda/contact_system/simplex_normal_contact.h @@ -133,8 +133,8 @@ class SimplexNormalContact : public ContactReporter SizeT PE_count = 0; SizeT PP_count = 0; - Float dt = 0; - muda::DeviceVar selected_count; + S> dt_attr; + muda::DeviceVar selected_count; Float reserve_ratio = 1.1; diff --git a/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.cu b/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.cu index 431c3c708..30a8f3050 100644 --- a/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.cu +++ b/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.cu @@ -9,8 +9,6 @@ void VertexHalfPlaneFrictionalContact::do_build(ContactReporter::BuildInfo& info { auto& config = world().scene().config(); auto enable_attr = config.find("contact/friction/enable"); - auto dt_attr = config.find("dt"); - if(!enable_attr->view()[0]) { throw SimSystemException("Frictional contact is disabled"); @@ -20,7 +18,8 @@ void VertexHalfPlaneFrictionalContact::do_build(ContactReporter::BuildInfo& info m_impl.global_contact_manager = require(); m_impl.global_vertex_manager = require(); m_impl.vertex_reporter = require(); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = config.find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); @@ -135,7 +134,7 @@ muda::CBufferView VertexHalfPlaneFrictionalContact::BaseInfo::d_hats() co Float VertexHalfPlaneFrictionalContact::BaseInfo::dt() const { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } Float VertexHalfPlaneFrictionalContact::BaseInfo::eps_velocity() const diff --git a/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.h b/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.h index 475c4d1c4..d5e8919df 100644 --- a/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.h +++ b/src/backends/cuda/contact_system/vertex_half_plane_frictional_contact.h @@ -94,8 +94,8 @@ class VertexHalfPlaneFrictionalContact : public ContactReporter SimSystemSlot veretx_half_plane_trajectory_filter; SimSystemSlot vertex_reporter; - SizeT PH_count = 0; - Float dt = 0.0; + SizeT PH_count = 0; + S> dt_attr; muda::CBufferView energies; muda::CDoubletVectorView gradients; diff --git a/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.cu b/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.cu index 8ac14e337..eb2303a88 100644 --- a/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.cu +++ b/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.cu @@ -11,8 +11,8 @@ void VertexHalfPlaneNormalContact::do_build(ContactReporter::BuildInfo& info) m_impl.global_contact_manager = require(); m_impl.global_vertex_manager = require(); m_impl.vertex_reporter = require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); @@ -129,7 +129,7 @@ muda::CBufferView VertexHalfPlaneNormalContact::BaseInfo::d_hats() const Float VertexHalfPlaneNormalContact::BaseInfo::dt() const { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } Float VertexHalfPlaneNormalContact::BaseInfo::eps_velocity() const diff --git a/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.h b/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.h index 6fb934831..a97585d40 100644 --- a/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.h +++ b/src/backends/cuda/contact_system/vertex_half_plane_normal_contact.h @@ -95,8 +95,8 @@ class VertexHalfPlaneNormalContact : public ContactReporter SimSystemSlot veretx_half_plane_trajectory_filter; SimSystemSlot vertex_reporter; - SizeT PH_count = 0; - Float dt = 0.0; + SizeT PH_count = 0; + S> dt_attr; muda::CBufferView energies; muda::CDoubletVectorView gradients; diff --git a/src/backends/cuda/finite_element/fem_linear_subsystem.cu b/src/backends/cuda/finite_element/fem_linear_subsystem.cu index 3124ad67b..c95e2ee5e 100644 --- a/src/backends/cuda/finite_element/fem_linear_subsystem.cu +++ b/src/backends/cuda/finite_element/fem_linear_subsystem.cu @@ -30,8 +30,8 @@ void FEMLinearSubsystem::do_build(DiagLinearSubsystem::BuildInfo&) m_impl.finite_element_method = require(); m_impl.finite_element_vertex_reporter = require(); m_impl.sim_engine = &engine(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); m_impl.dytopo_effect_receiver = find(); } @@ -244,7 +244,7 @@ void FEMLinearSubsystem::Impl::_assemble_kinetic(IndexT& hess_offset, auto hessian_view = info.hessians().subview(hess_offset, hess_count); FEMLinearSubsystem::ComputeGradientHessianInfo kinetic_info{ - info.gradient_only(), gradient_view, hessian_view, dt}; + info.gradient_only(), gradient_view, hessian_view, dt_attr->view()[0]}; kinetic->compute_gradient_hessian(kinetic_info); ParallelFor() @@ -497,7 +497,7 @@ muda::TripletMatrixView FEMLinearSubsystem::AssembleInfo::hessians( Float FEMLinearSubsystem::AssembleInfo::dt() const noexcept { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } bool FEMLinearSubsystem::AssembleInfo::gradient_only() const noexcept diff --git a/src/backends/cuda/finite_element/fem_linear_subsystem.h b/src/backends/cuda/finite_element/fem_linear_subsystem.h index 3c8c3109f..be2056d56 100644 --- a/src/backends/cuda/finite_element/fem_linear_subsystem.h +++ b/src/backends/cuda/finite_element/fem_linear_subsystem.h @@ -18,10 +18,10 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem class ComputeGradientHessianInfo { public: - ComputeGradientHessianInfo(bool gradient_only, - muda::DoubletVectorView gradients, + ComputeGradientHessianInfo(bool gradient_only, + muda::DoubletVectorView gradients, muda::TripletMatrixView hessians, - Float dt) noexcept + Float dt) noexcept : m_gradient_only(gradient_only) , m_gradients(gradients) , m_hessians(hessians) @@ -35,7 +35,7 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem auto dt() const noexcept { return m_dt; } private: - bool m_gradient_only = false; + bool m_gradient_only = false; muda::DoubletVectorView m_gradients; muda::TripletMatrixView m_hessians; Float m_dt = 0.0; @@ -58,9 +58,9 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem private: friend class FEMLinearSubsystem; friend class FEMLinearSubsystemReporter; - SizeT m_gradient_count = 0; - SizeT m_hessian_count = 0; - bool m_gradient_only = false; + SizeT m_gradient_count = 0; + SizeT m_hessian_count = 0; + bool m_gradient_only = false; mutable bool m_gradient_only_checked = false; }; @@ -72,7 +72,7 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem AssembleInfo(Impl* impl, IndexT index, muda::TripletMatrixView hessians, - bool gradient_only) noexcept + bool gradient_only) noexcept : m_impl(impl) , m_index(index) , m_hessians(hessians) @@ -88,8 +88,8 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem private: friend class FEMLinearSubsystem; - Impl* m_impl = nullptr; - IndexT m_index = ~0; + Impl* m_impl = nullptr; + IndexT m_index = ~0; muda::TripletMatrixView m_hessians; bool m_gradient_only = false; }; @@ -109,8 +109,8 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem void _assemble_dytopo_effect(IndexT& hess_offset, GlobalLinearSystem::DiagInfo& info); - void accuracy_check(GlobalLinearSystem::AccuracyInfo& info); - void retrieve_solution(GlobalLinearSystem::SolutionInfo& info); + void accuracy_check(GlobalLinearSystem::AccuracyInfo& info); + void retrieve_solution(GlobalLinearSystem::SolutionInfo& info); Float diag_norm(GlobalLinearSystem::DiagNormInfo& info); Float mass_norm(GlobalLinearSystem::DiagNormInfo& info); @@ -130,8 +130,8 @@ class FEMLinearSubsystem final : public DiagLinearSubsystem SimSystemSlot kinetic; - Float dt = 0.0; - Float reserve_ratio = 1.5; + S> dt_attr; + Float reserve_ratio = 1.5; OffsetCountCollection reporter_gradient_offsets_counts; OffsetCountCollection reporter_hessian_offsets_counts; diff --git a/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.cu b/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.cu index 4ff3eb822..313341a8c 100644 --- a/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.cu +++ b/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.cu @@ -4,16 +4,16 @@ namespace uipc::backend::cuda { void FiniteElementDiffDofReporter::do_build(DiffDofReporter::BuildInfo& info) { - m_impl.fem = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.fem = &require(); + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); } void FiniteElementDiffDofReporter::do_assemble(GlobalDiffSimManager::DiffDofInfo& info) { - DiffDofInfo this_info{&m_impl, info, m_impl.dt}; + DiffDofInfo this_info{&m_impl, info, m_impl.dt_attr->view()[0]}; do_assemble(this_info); } diff --git a/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.h b/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.h index 9e8139c26..8b58b5e65 100644 --- a/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.h +++ b/src/backends/cuda/finite_element/finite_element_diff_dof_reporter.h @@ -47,8 +47,8 @@ class FiniteElementDiffDofReporter : public DiffDofReporter class Impl { public: - FiniteElementMethod* fem = nullptr; - Float dt = 0.0; + FiniteElementMethod* fem = nullptr; + S> dt_attr; }; protected: diff --git a/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.cu b/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.cu index d40061de4..fd63eb474 100644 --- a/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.cu +++ b/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.cu @@ -5,16 +5,16 @@ namespace uipc::backend::cuda { void FiniteElementDiffParmReporter::do_build(DiffParmReporter::BuildInfo& info) { - m_impl.fem = &require(); - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.fem = &require(); + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); BuildInfo this_info; do_build(this_info); } void FiniteElementDiffParmReporter::do_assemble(GlobalDiffSimManager::DiffParmInfo& info) { - DiffParmInfo this_info{&m_impl, info, m_impl.dt}; + DiffParmInfo this_info{&m_impl, info, m_impl.dt_attr->view()[0]}; do_assemble(this_info); } @@ -52,6 +52,6 @@ muda::TripletMatrixView FiniteElementDiffParmReporter::DiffParmInfo::p Float FiniteElementDiffParmReporter::DiffParmInfo::dt() const { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } } // namespace uipc::backend::cuda diff --git a/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.h b/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.h index 74b6ed96f..c632c62b4 100644 --- a/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.h +++ b/src/backends/cuda/finite_element/finite_element_diff_parm_reporter.h @@ -47,8 +47,8 @@ class FiniteElementDiffParmReporter : public DiffParmReporter class Impl { public: - FiniteElementMethod* fem = nullptr; - Float dt = 0.0; + FiniteElementMethod* fem = nullptr; + S> dt_attr; }; protected: diff --git a/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.cu b/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.cu index 22476e0f4..af662ecfb 100644 --- a/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.cu +++ b/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.cu @@ -30,8 +30,8 @@ REGISTER_SIM_SYSTEM(InterPrimitiveConstitutionManager); void InterPrimitiveConstitutionManager::do_build(DyTopoEffectReporter::BuildInfo&) { - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); m_impl.global_vertex_manager = require(); } @@ -108,7 +108,8 @@ void InterPrimitiveConstitutionManager::Impl::init(SceneVisitor& scene) void InterPrimitiveConstitutionManager::Impl::compute_energy(GlobalDyTopoEffectManager::EnergyInfo& info) { - auto constitution_view = constitutions.view(); + Float dt = dt_attr->view()[0]; + auto constitution_view = constitutions.view(); for(auto&& [i, c] : enumerate(constitution_view)) { EnergyInfo this_info{this, c->m_index, dt, info.energies()}; @@ -119,7 +120,8 @@ void InterPrimitiveConstitutionManager::Impl::compute_energy(GlobalDyTopoEffectM void InterPrimitiveConstitutionManager::Impl::compute_gradient_hessian( GlobalDyTopoEffectManager::GradientHessianInfo& info) { - auto constitution_view = constitutions.view(); + Float dt = dt_attr->view()[0]; + auto constitution_view = constitutions.view(); for(auto&& [i, c] : enumerate(constitution_view)) { GradientHessianInfo this_info{ @@ -247,7 +249,7 @@ muda::CBufferView InterPrimitiveConstitutionManager::BaseInfo::position Float InterPrimitiveConstitutionManager::BaseInfo::dt() const noexcept { - return m_impl->dt; + return m_impl->dt_attr->view()[0]; } void InterPrimitiveConstitutionManager::GradientHessianExtentInfo::hessian_count(SizeT count) noexcept diff --git a/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.h b/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.h index c474aea49..35800bc50 100644 --- a/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.h +++ b/src/backends/cuda/inter_primitive_effect_system/inter_primitive_constitution_manager.h @@ -153,7 +153,7 @@ class InterPrimitiveConstitutionManager final : public DyTopoEffectReporter void compute_energy(GlobalDyTopoEffectManager::EnergyInfo& info); void compute_gradient_hessian(GlobalDyTopoEffectManager::GradientHessianInfo& info); - Float dt = 0.0; + S> dt_attr; SimSystemSlotCollection constitutions; SimSystemSlot global_vertex_manager; diff --git a/src/backends/cuda/line_search/line_searcher.cu b/src/backends/cuda/line_search/line_searcher.cu index 8bba0f8ca..8555bcad4 100644 --- a/src/backends/cuda/line_search/line_searcher.cu +++ b/src/backends/cuda/line_search/line_searcher.cu @@ -20,8 +20,8 @@ void LineSearcher::init() auto max_iter_attr = scene.config().find("line_search/max_iter"); m_max_iter = max_iter_attr->view()[0]; - auto dt_attr = scene.config().find("dt"); - m_dt = dt_attr->view()[0]; + m_dt_attr = scene.config().find("dt"); + UIPC_ASSERT(m_dt_attr, "Scene config must have a 'dt' attribute."); m_energy_values.resize(m_reporters.view().size(), 0); @@ -111,7 +111,7 @@ LineSearcher::ComputeEnergyInfo::ComputeEnergyInfo(LineSearcher* impl) noexcept Float LineSearcher::ComputeEnergyInfo::dt() noexcept { - return m_impl->m_dt; + return m_impl->m_dt_attr->view()[0]; } void LineSearcher::ComputeEnergyInfo::energy(Float e) noexcept diff --git a/src/backends/cuda/line_search/line_searcher.h b/src/backends/cuda/line_search/line_searcher.h index ee08b10b0..e11229c7f 100644 --- a/src/backends/cuda/line_search/line_searcher.h +++ b/src/backends/cuda/line_search/line_searcher.h @@ -54,10 +54,10 @@ class LineSearcher : public SimSystem SimSystemSlotCollection m_reporters; - vector m_energy_values; - bool m_report_energy = false; - std::stringstream m_report_stream; - Float m_dt = 0.0; - IndexT m_max_iter = 64; + vector m_energy_values; + bool m_report_energy = false; + std::stringstream m_report_stream; + S> m_dt_attr; + IndexT m_max_iter = 64; }; } // namespace uipc::backend::cuda diff --git a/src/backends/cuda/newton_tolerance/max_translation_checker.cu b/src/backends/cuda/newton_tolerance/max_translation_checker.cu index 5dbf6cffb..1c2f37b17 100644 --- a/src/backends/cuda/newton_tolerance/max_translation_checker.cu +++ b/src/backends/cuda/newton_tolerance/max_translation_checker.cu @@ -1,5 +1,6 @@ #include #include +#include namespace uipc::backend::cuda { @@ -8,23 +9,23 @@ class MaxTranslationChecker : public NewtonToleranceChecker public: using NewtonToleranceChecker::NewtonToleranceChecker; - SimSystemSlot vertex_manager; - Float res0 = 0.0; - Float res = 0.0; - Float rel_tol = 0.0; - Float abs_tol = 0.0; - SizeT frame = 0; + SimSystemSlot vertex_manager; + S> dt_attr; + Float newton_velocity_tol = 0.0; + Float res0 = 0.0; + Float res = 0.0; + Float rel_tol = 0.0; + Float abs_tol = 0.0; + SizeT frame = 0; void do_build(BuildInfo& info) override { vertex_manager = require(); auto& config = world().scene().config(); - auto dt_attr = config.find("dt"); - Float dt = dt_attr->view()[0]; + dt_attr = config.find("dt"); + UIPC_ASSERT(dt_attr, "Scene config must have a 'dt' attribute."); auto newton_velocity_tol_attr = config.find("newton/velocity_tol"); - Float newton_velocity_tol = newton_velocity_tol_attr->view()[0]; - - abs_tol = newton_velocity_tol * dt; + newton_velocity_tol = newton_velocity_tol_attr->view()[0]; } void do_init(InitInfo& info) override {} @@ -36,6 +37,7 @@ class MaxTranslationChecker : public NewtonToleranceChecker void do_check(CheckResultInfo& info) override { + abs_tol = newton_velocity_tol * dt_attr->view()[0]; res = vertex_manager->compute_axis_max_displacement(); auto newton_iter = info.newton_iter(); if(newton_iter == 0) diff --git a/src/backends/cuda/time_integrator/time_integrator_manager.cu b/src/backends/cuda/time_integrator/time_integrator_manager.cu index d883405a1..0e9bda4a6 100644 --- a/src/backends/cuda/time_integrator/time_integrator_manager.cu +++ b/src/backends/cuda/time_integrator/time_integrator_manager.cu @@ -7,8 +7,8 @@ REGISTER_SIM_SYSTEM(TimeIntegratorManager); void TimeIntegratorManager::do_build() { - auto dt_attr = world().scene().config().find("dt"); - m_impl.dt = dt_attr->view()[0]; + m_impl.dt_attr = world().scene().config().find("dt"); + UIPC_ASSERT(m_impl.dt_attr, "Scene config must have a 'dt' attribute."); } void TimeIntegratorManager::init() @@ -22,10 +22,11 @@ void TimeIntegratorManager::init() void TimeIntegratorManager::predict_dof() { // Predict the degrees of freedom for each time integrator + Float dt = m_impl.dt_attr->view()[0]; for(auto& integrator : m_impl.time_integrators.view()) { PredictDofInfo info; - info.m_dt = m_impl.dt; + info.m_dt = dt; integrator->predict_dof(info); } } @@ -33,10 +34,11 @@ void TimeIntegratorManager::predict_dof() void TimeIntegratorManager::update_state() { // Update the state for each time integrator + Float dt = m_impl.dt_attr->view()[0]; for(auto& integrator : m_impl.time_integrators.view()) { UpdateVelocityInfo info; - info.m_dt = m_impl.dt; + info.m_dt = dt; integrator->update_state(info); } } diff --git a/src/backends/cuda/time_integrator/time_integrator_manager.h b/src/backends/cuda/time_integrator/time_integrator_manager.h index ca34145aa..d55b418f0 100644 --- a/src/backends/cuda/time_integrator/time_integrator_manager.h +++ b/src/backends/cuda/time_integrator/time_integrator_manager.h @@ -34,7 +34,7 @@ class TimeIntegratorManager final : public SimSystem { public: SimSystemSlotCollection time_integrators; - Float dt = 0.0; + S> dt_attr; }; private: diff --git a/src/core/backend/visitors/scene_visitor.cpp b/src/core/backend/visitors/scene_visitor.cpp index ae43af9dd..81c21b774 100644 --- a/src/core/backend/visitors/scene_visitor.cpp +++ b/src/core/backend/visitors/scene_visitor.cpp @@ -70,6 +70,11 @@ const geometry::AttributeCollection& SceneVisitor::config() const noexcept return m_scene.config(); } +Float SceneVisitor::dt() const noexcept +{ + return m_scene.dt(); +} + const core::ConstitutionTabular& SceneVisitor::constitution_tabular() const noexcept { return m_scene.constitution_tabular();