LMCAS
Lamina Computer Algebra System
载入中...
搜索中...
未找到
vector_calculus_directional.cpp
浏览该文件的文档.
4#include <stdexcept>
5
6namespace LMCAS {
7
8using namespace vector_calculus_detail;
9
10static std::shared_ptr<SymbolicExpr> vector_calculus_magnitude_squared(
11 const VectorField& v,
12 detail::RewriteBudget& transform_budget)
13{
14 std::shared_ptr<SymbolicExpr> sum = nullptr;
15 for (const auto& comp : v) {
16 if (!comp) {
17 continue;
18 }
19 auto sq = SymbolicExpr::power(comp, SymbolicExpr::number(2));
21 if (!sum) {
22 sum = sq;
23 } else {
24 sum = SymbolicExpr::add(sum, sq);
26 }
27 }
28 if (!sum) {
29 return SymbolicExpr::number(0);
30 }
32}
33
34static std::shared_ptr<SymbolicExpr> vector_calculus_single_dir_deriv(
35 const std::shared_ptr<SymbolicExpr>& f,
36 const std::vector<std::string>& vars,
37 const VectorField& unit_dir,
38 detail::RewriteBudget& transform_budget)
39{
40 std::shared_ptr<SymbolicExpr> sum = nullptr;
41 for (size_t i = 0; i < vars.size(); ++i) {
42 auto partial = detail::make_expression_ptr(detail::differentiate_node(detail::node(f), vars[i], transform_budget));
43 if (!partial) {
44 continue;
45 }
46 partial = detail::make_expression_ptr(detail::normalize_node(detail::node(partial), transform_budget));
47 auto term = SymbolicExpr::multiply(partial, unit_dir[i]);
49 if (!sum) {
50 sum = term;
51 } else {
52 sum = SymbolicExpr::add(sum, term);
54 }
55 }
56 if (!sum) {
57 return SymbolicExpr::number(0);
58 }
60}
61
63 const std::shared_ptr<SymbolicExpr>& f,
64 const std::vector<std::string>& vars,
66 int order,
68{
69 detail::RewriteBudget transform_budget(context, context.limits().max_recursion_depth,
70 context.limits().max_ast_nodes, "directional_derivative");
71 const std::string operation = "directional_derivative";
72 auto valid = vector_calculus_validate_expr_vars(f, vars, context, operation);
73 if (!valid) {
74 return VectorCalculusExprResult::failure(valid.error());
75 }
76 auto dir_valid = vector_calculus_validate_field_vars(direction, vars, context, operation);
77 if (!dir_valid) {
78 return VectorCalculusExprResult::failure(dir_valid.error());
79 }
80 if (order < 1) {
82 "directional derivative order must be positive",
83 operation);
84 }
85 try {
86 auto mag_sq = vector_calculus_magnitude_squared(direction, transform_budget);
87 if (!mag_sq || !LMCAS::detail::node(mag_sq)) {
90 "direction magnitude construction failed",
91 operation);
92 }
93 if (mag_sq->is_zero()) {
95 "direction vector cannot be zero",
96 operation);
97 }
98 auto step = context.consume_steps(vars.size() * static_cast<std::size_t>(order),
99 operation);
100 if (!step) {
101 return VectorCalculusExprResult::failure(step.error());
102 }
104 directional_derivative_impl(f, vars, direction, order, transform_budget), operation);
105 } catch (const CasError& error) {
107 } catch (const std::bad_alloc&) {
109 "vector calculus allocation failed",
110 operation);
111 } catch (const std::length_error& error) {
112 return VectorCalculusExprResult::failure(CasErrc::ResourceLimit, error.what(), operation);
113 } catch (const std::exception& e) {
115 }
116}
117
119 const std::shared_ptr<SymbolicExpr>& f,
120 const std::vector<std::string>& vars,
121 const VectorField& direction,
122 int order)
123{
126}
127
129 const std::shared_ptr<SymbolicExpr>& f, const std::vector<std::string>& vars,
130 const VectorField& direction, int order,
131 detail::RewriteBudget& transform_budget)
132{
133 if (!f) {
134 throw std::invalid_argument("directional_derivative: f must not be null");
135 }
136 if (direction.size() != vars.size()) {
137 throw std::invalid_argument(
138 "directional_derivative: direction and vars must have the same dimension");
139 }
140 if (order < 1) {
141 throw std::invalid_argument(
142 "directional_derivative: order must be >= 1");
143 }
144
145 auto mag_sq = vector_calculus_magnitude_squared(direction, transform_budget);
146 if (!mag_sq || mag_sq->is_zero()) {
147 return nullptr;
148 }
149
150 auto magnitude = SymbolicExpr::sqrt(mag_sq);
151 magnitude = detail::make_expression_ptr(detail::normalize_node(detail::node(magnitude), transform_budget));
152 VectorField unit_dir;
153 unit_dir.reserve(direction.size());
154 for (const auto& comp : direction) {
155 if (!comp || comp->is_zero()) {
156 unit_dir.push_back(SymbolicExpr::number(0));
157 } else {
158 auto u_comp = SymbolicExpr::multiply(
159 comp,
160 SymbolicExpr::power(magnitude, SymbolicExpr::number(-1)));
161 u_comp = detail::make_expression_ptr(detail::normalize_node(detail::node(u_comp), transform_budget));
162 unit_dir.push_back(u_comp);
163 }
164 }
165
166 auto result = f;
167 for (int k = 0; k < order; ++k) {
168 result = vector_calculus_single_dir_deriv(result, vars, unit_dir, transform_budget);
169 if (!result) {
170 return SymbolicExpr::number(0);
171 }
172 }
173
174 return result;
175}
176
177
178std::shared_ptr<SymbolicExpr> directional_derivative(
179 const std::shared_ptr<SymbolicExpr>& f, const std::vector<std::string>& vars,
180 const VectorField& direction, int order)
181{
183 detail::RewriteBudget transform_budget(context, context.limits().max_recursion_depth,
184 context.limits().max_ast_nodes, "directional_derivative");
185 return directional_derivative_impl(f, vars, direction, order, transform_budget);
186}
187
188}
static Result failure(CasErrc code, std::string message, std::string operation={})
SymbolicNodePtr differentiate_node(const SymbolicNodePtr &node, const std::string &variable, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
Result< void > vector_calculus_validate_expr_vars(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation)
std::shared_ptr< SymbolicExpr > directional_derivative_impl(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, const VectorField &direction, int order, detail::RewriteBudget &transform_budget)
VectorCalculusExprResult vector_calculus_wrap_expr(std::shared_ptr< SymbolicExpr > expr, const std::string &operation)
Result< void > vector_calculus_validate_field_vars(const VectorField &field, const std::vector< std::string > &vars, ComputationContext &context, const std::string &operation)
ExprResult e()
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
__attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorCalculusFieldResult gradient_checked(const std __attribute__((visibility("default"))) VectorField gradient(const std const std::vector< std::string > & vars
const std::vector< FGLMPoly > const MonomialOrder & order
const std::string const LimitExprPtr LimitDirection direction
std::shared_ptr< SymbolicExpr > directional_derivative(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, const VectorField &direction, int order)
static std::shared_ptr< SymbolicExpr > vector_calculus_magnitude_squared(const VectorField &v, detail::RewriteBudget &transform_budget)
static std::shared_ptr< SymbolicExpr > vector_calculus_single_dir_deriv(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, const VectorField &unit_dir, detail::RewriteBudget &transform_budget)
std::vector< std::shared_ptr< SymbolicExpr > > VectorField
向量场由标量表达式组成。
Result< std::shared_ptr< SymbolicExpr > > VectorCalculusExprResult
VectorCalculusExprResult directional_derivative_checked(const std::shared_ptr< SymbolicExpr > &f, const std::vector< std::string > &vars, const VectorField &direction, int order, ComputationContext &context)