-
Notifications
You must be signed in to change notification settings - Fork 15
WIP: framework for gaussian heat source #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
colemanjs
wants to merge
9
commits into
adamantine-sim:master
Choose a base branch
from
colemanjs:gaussian-heat-source
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
646ac8d
framework for gaussian heat source
colemanjs eb5203f
implemented heat source
colemanjs 7874bb4
fixup
colemanjs 4471c66
fixup
colemanjs b0c0b2a
fixup: add to thermal physics check
colemanjs 3d74514
Rebase from main
colemanjs e13f63e
Update copyright in source/GaussianHeatSource.cc
colemanjs 8415c9e
Update copyright in source/GaussianHeatSource.hh
colemanjs 2b3443a
fix-up for half-space normalization from z = [-depth, 0]
colemanjs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,211 @@ | ||
| /* SPDX-FileCopyrightText: Copyright (c) 2026, the adamantine authors. | ||
| * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| */ | ||
|
|
||
| #include <GaussianHeatSource.hh> | ||
| #include <instantiation.hh> | ||
| #include <types.hh> | ||
|
|
||
| #include <deal.II/base/utilities.h> | ||
|
|
||
| namespace adamantine | ||
| { | ||
|
|
||
| template <int dim> | ||
| GaussianHeatSource<dim>::GaussianHeatSource( | ||
| boost::property_tree::ptree const &beam_database, | ||
| boost::optional<boost::property_tree::ptree const &> const | ||
| &units_optional_database) | ||
| : HeatSource<dim>(beam_database, units_optional_database), | ||
| _five_axis(this->_scan_path.is_five_axis()) | ||
| { | ||
| _A = beam_database.get<double>("A"); | ||
| _B = beam_database.get<double>("B"); | ||
| } | ||
|
|
||
| template <int dim> | ||
| void GaussianHeatSource<dim>::update_time(double time) | ||
| { | ||
| double const segment_power_modifier = | ||
| this->_scan_path.get_power_modifier(time); | ||
| this->_source_on = (segment_power_modifier > 0.0); | ||
|
|
||
| dealii::Point<3> const &path = this->_scan_path.value(time); | ||
| _quaternion = this->_scan_path.get_current_quaternion(); | ||
|
|
||
| for (unsigned int d = 0; d < 3; ++d) | ||
| { | ||
| _beam_center(d) = path(d); | ||
| } | ||
|
|
||
| _depth = this->_beam.depth; | ||
| _radius_squared = this->_beam.radius_squared; | ||
|
|
||
| double const aspect_ratio = std::max(1.0, _depth[0] / this->_beam.radius); | ||
| double const n = | ||
| std::min(std::max(0.0, _A * std::log2(aspect_ratio) + _B), 9.0); | ||
| _k = std::pow(2.0, n); | ||
|
|
||
| double const V0 = | ||
| 0.5 * dealii::numbers::PI * _radius_squared[0] * _depth[0] * | ||
| std::tgamma(1.0 / _k) / (_k * std::pow(3.0, 1.0 / _k)); | ||
|
|
||
| double const effective_power = | ||
| this->_beam.absorption_efficiency * this->_beam.max_power * | ||
| segment_power_modifier; | ||
|
|
||
| _alpha = effective_power / V0; | ||
| } | ||
|
|
||
| template <int dim> | ||
| double GaussianHeatSource<dim>::value(dealii::Point<dim> const &point) const | ||
| { | ||
| dealii::Point<dim> rotated_point; | ||
| if constexpr (dim == 2) | ||
| { | ||
| rotated_point = point; | ||
| } | ||
| else | ||
| { | ||
| rotated_point = _five_axis ? _quaternion.rotate(point) : point; | ||
| } | ||
|
|
||
| double const z = rotated_point[axis<dim>::z] - _beam_center[axis<dim>::z][0]; | ||
|
|
||
| if (z > 0. || z < -_depth[0]) | ||
| { | ||
| return 0.; | ||
| } | ||
|
|
||
| double xpy_squared = dealii::Utilities::fixed_power<2>( | ||
| rotated_point[axis<dim>::x] - _beam_center[axis<dim>::x][0]); | ||
| if constexpr (dim == 3) | ||
| { | ||
| xpy_squared += dealii::Utilities::fixed_power<2>( | ||
| rotated_point[axis<dim>::y] - _beam_center[axis<dim>::y][0]); | ||
| } | ||
|
|
||
| if (xpy_squared > 5. * _radius_squared[0]) | ||
| { | ||
| return 0.; | ||
| } | ||
|
|
||
| double const radial_component = | ||
| std::exp(-2.0 * xpy_squared / _radius_squared[0]); | ||
|
|
||
| double const depth_component = | ||
| std::exp(-3.0 * std::pow(std::abs(z / _depth[0]), _k)); | ||
|
|
||
| return _alpha[0] * radial_component * depth_component; | ||
| } | ||
|
|
||
| template <int dim> | ||
| dealii::VectorizedArray<double> GaussianHeatSource<dim>::value( | ||
| dealii::Point<dim, dealii::VectorizedArray<double>> const &points) const | ||
| { | ||
| dealii::Point<dim, dealii::VectorizedArray<double>> rotated_points; | ||
| if constexpr (dim == 2) | ||
| { | ||
| rotated_points = points; | ||
| } | ||
| else | ||
| { | ||
| rotated_points = _five_axis ? _quaternion.rotate(points) : points; | ||
| } | ||
|
|
||
| auto const z = rotated_points[axis<dim>::z] - _beam_center[axis<dim>::z]; | ||
|
|
||
| dealii::VectorizedArray<double> depth_mask; | ||
| for (unsigned int i = 0; i < depth_mask.size(); ++i) | ||
| { | ||
| depth_mask[i] = (z[i] > 0. || z[i] < -_depth[i]) ? 0. : 1.; | ||
| } | ||
| if (depth_mask.sum() == 0) | ||
| { | ||
| return depth_mask; | ||
| } | ||
|
|
||
| auto xpy_squared = dealii::Utilities::fixed_power<2>( | ||
| rotated_points[axis<dim>::x] - _beam_center[axis<dim>::x]); | ||
| if constexpr (dim == 3) | ||
| { | ||
| auto const y_squared = dealii::Utilities::fixed_power<2>( | ||
| rotated_points[axis<dim>::y] - _beam_center[axis<dim>::y]); | ||
| xpy_squared += y_squared; | ||
| } | ||
|
|
||
| auto const xpy_area = 5. * _radius_squared - xpy_squared; | ||
| dealii::VectorizedArray<double> xpy_mask; | ||
| for (unsigned int i = 0; i < xpy_mask.size(); ++i) | ||
| { | ||
| xpy_mask[i] = xpy_area[i] < 0. ? 0. : 1.; | ||
| } | ||
| if (xpy_mask.sum() == 0) | ||
| { | ||
| return xpy_mask; | ||
| } | ||
|
|
||
| dealii::VectorizedArray<double> shape = _k; | ||
|
|
||
| auto const radial_component = | ||
| std::exp(-2.0 * xpy_squared / _radius_squared); | ||
|
|
||
| auto const depth_component = | ||
| std::exp(-3.0 * std::pow(std::abs(z / _depth), shape)); | ||
|
|
||
| return depth_mask * _alpha * radial_component * depth_component; | ||
| } | ||
|
|
||
| template <int dim> | ||
| dealii::BoundingBox<dim> | ||
| GaussianHeatSource<dim>::get_bounding_box(double const time, | ||
| double const scaling_factor) const | ||
| { | ||
| dealii::Point<3> const &beam_center = this->_scan_path.value(time, false); | ||
| if constexpr (dim == 2) | ||
| { | ||
| return {{{beam_center[axis<dim>::x] - scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::z] - scaling_factor * this->_beam.depth}, | ||
| {beam_center[axis<dim>::x] + scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::z]}}}; | ||
| } | ||
| else | ||
| { | ||
| dealii::Point<3> max_corner( | ||
| beam_center[axis<dim>::x] + scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::y] + scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::z]); | ||
| dealii::Point<3> min_corner( | ||
| beam_center[axis<dim>::x] - scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::y] - scaling_factor * this->_beam.radius, | ||
| beam_center[axis<dim>::z] - scaling_factor * this->_beam.depth); | ||
|
|
||
| if (this->_scan_path.is_five_axis()) | ||
| { | ||
| dealii::Point<3> rotated_max_corner = | ||
| this->_scan_path.rotate(time, max_corner); | ||
| dealii::Point<3> rotated_min_corner = | ||
| this->_scan_path.rotate(time, min_corner); | ||
|
|
||
| dealii::Point<3> new_max_corner; | ||
| dealii::Point<3> new_min_corner; | ||
| for (int d = 0; d < 3; ++d) | ||
| { | ||
| new_max_corner[d] = | ||
| std::max(rotated_max_corner[d], rotated_min_corner[d]); | ||
| new_min_corner[d] = | ||
| std::min(rotated_max_corner[d], rotated_min_corner[d]); | ||
| } | ||
|
|
||
| return {{new_min_corner, new_max_corner}}; | ||
| } | ||
| else | ||
| { | ||
| return {{min_corner, max_corner}}; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } // namespace adamantine | ||
|
|
||
| INSTANTIATE_DIM(GaussianHeatSource) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* SPDX-FileCopyrightText: Copyright (c) 2026, the adamantine authors. | ||
| * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| */ | ||
|
|
||
| #ifndef GAUSSIAN_HEAT_SOURCE_HH | ||
| #define GAUSSIAN_HEAT_SOURCE_HH | ||
|
|
||
| #include <HeatSource.hh> | ||
| #include <Quaternion.hh> | ||
|
|
||
| #include <limits> | ||
|
|
||
| namespace adamantine | ||
| { | ||
| /** | ||
| * A derived class from HeatSource for the Gaussian model of a laser heat source. | ||
| */ | ||
| template <int dim> | ||
| class GaussianHeatSource final : public HeatSource<dim> | ||
| { | ||
| public: | ||
| /** | ||
| * Constructor. | ||
| * \param[in] beam_database requires the following entries: | ||
| * - <B>absorption_efficiency</B>: double in \f$[0,1]\f$ | ||
| * - <B>depth</B>: double in \f$[0,\infty)\f$ | ||
| * - <B>diameter</B>: double in \f$[0,\infty)\f$ | ||
| * - <B>max_power</B>: double in \f$[0, \infty)\f$ | ||
| * - <B>scan_path_file</B>: name of the file that contains the scan path | ||
| * segments | ||
| * - <B>scan_path_file_format</B>: format of the scan path file | ||
| * - <B>A</B>: double, empirical coefficient for the model | ||
| * - <B>B</B>: double, empirical coefficient for the model | ||
| * \param[in] units_optional_database may contain the following entries: | ||
| * - <B>heat_source.dimension</B> | ||
| * - <B>heat_source.power</B> | ||
| */ | ||
| GaussianHeatSource( | ||
| boost::property_tree::ptree const &beam_database, | ||
| boost::optional<boost::property_tree::ptree const &> const | ||
| &units_optional_database); | ||
|
|
||
| /** | ||
| * Set the time variable. This updates the beam position and recalculates | ||
| * the shape factor (_k) and normalization constant (_alpha). | ||
| */ | ||
| void update_time(double time) final; | ||
|
|
||
| /** | ||
| * Returns the value of a Gaussian heat source at a specified point. | ||
| */ | ||
| double value(dealii::Point<dim> const &point) const final; | ||
|
|
||
| /** | ||
| * Same function as above but it uses vectorized data. | ||
| */ | ||
| dealii::VectorizedArray<double> | ||
| value(dealii::Point<dim, dealii::VectorizedArray<double>> const &points) | ||
| const final; | ||
|
|
||
| /** | ||
| * Returns the bounding box of the heat source at a given time. | ||
| */ | ||
| dealii::BoundingBox<dim> | ||
| get_bounding_box(double time, double const scaling_factor) const final; | ||
|
|
||
| private: | ||
| double _A; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a comment here. I have no idea what are A and B |
||
| double _B; | ||
|
|
||
| bool const _five_axis; | ||
| Quaternion _quaternion; | ||
|
|
||
| dealii::Point<3, dealii::VectorizedArray<double>> _beam_center; | ||
| dealii::VectorizedArray<double> _depth = | ||
| std::numeric_limits<double>::signaling_NaN(); | ||
| dealii::VectorizedArray<double> _radius_squared = | ||
| std::numeric_limits<double>::signaling_NaN(); | ||
|
|
||
| dealii::VectorizedArray<double> _alpha = | ||
| std::numeric_limits<double>::signaling_NaN(); | ||
|
|
||
| double _k = std::numeric_limits<double>::signaling_NaN(); | ||
| }; | ||
| } // namespace adamantine | ||
|
|
||
| #endif | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you read an input from the property tree, add a comment like:
I use that to grep the code and make sure that the documentation is up-to-date