https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NewtonInversionTest.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "gtest/gtest.h"
11#include "NewtonInversion.h"
12
13void
14function_f1(Real x1, Real x2, Real & z, Real & dzdx1, Real & dzdx2)
15{
16 z = x2 * x2 - 3 * x2 + 4 * x1 + 2;
17 dzdx1 = 4;
18 dzdx2 = 2 * x2 - 3;
19}
20
21void
22function_f2(Real x1, Real x2, Real & z, Real & dzdx1, Real & dzdx2)
23{
24 z = exp(x1 * x2) + x2 * log(x2);
25 dzdx1 = x2 * exp(x1 * x2);
26 dzdx2 = x1 * exp(x1 * x2) + log(x2) + 1;
27}
28
36TEST(NewtonInversion, NewtonSolve)
37{
38 // Test 2nd degree polynomial with two roots (f1)
39 // x is kept constant when calling f_1(x, y)
40 Real x = 0;
41 // we seek y such that f(x1, x2) = z
42 Real z = 0;
43 Real initial_guess = 11;
44 auto func = [&](Real x1, Real x2, Real & z, Real & dzdx1, Real & dzdx2)
45 { function_f1(x1, x2, z, dzdx1, dzdx2); };
46
47 // Solve z = f(x, y) with x constant
48 Real y = FluidPropertiesUtils::NewtonSolve(x, z, initial_guess, 1e-8, func, "unit").first;
49
50 // Check solution found
51 Real tol = 1e-7;
52 Real soln = 2;
53 EXPECT_NEAR(y, soln, tol);
54
55 // Test nonlinear function (f2)
56 auto func2 = [&](Real x1, Real x2, Real & z, Real & dzdx1, Real & dzdx2)
57 { function_f2(x1, x2, z, dzdx1, dzdx2); };
58
59 x = 1;
60 z = 0.8749124087762432;
61 soln = 0.1;
62 initial_guess = 0.1;
63 y = FluidPropertiesUtils::NewtonSolve(x, z, initial_guess, 1e-8, func2, "unit").first;
64 EXPECT_NEAR(y, soln, tol);
65}
66
67void
68function_g1(Real x1, Real x2, Real & g, Real & dgdx1, Real & dgdx2)
69{
70 g = x2 - 2 * x1;
71 dgdx1 = -2;
72 dgdx2 = 1;
73}
74
75void
76function_g2(Real x1, Real x2, Real & g, Real & dgdx1, Real & dgdx2)
77{
78 g = x1 * x1 + x2 * x2 - 4 * x1 * x2 + 2;
79 dgdx1 = 2 * x1 - 4 * x2;
80 dgdx2 = 2 * x2 - 4 * x1;
81}
82
83void
84function_g3(Real x1, Real x2, Real & g, Real & dgdx1, Real & dgdx2)
85{
86 g = exp(x2) + x1 * log(x1);
87 dgdx1 = 1 + log(x1);
88 dgdx2 = exp(x2);
89}
90
102TEST(NewtonInversion, NewtonSolve2D)
103{
104 // Initial guess
105 Real guess1 = 2;
106 Real guess2 = 10;
107
108 // Target values
109 Real y1 = -3;
110 Real y2 = -37;
111
112 // Roots of the problem obtained by Newton's method
113 Real return_x1;
114 Real return_x2;
115
116 // Known solution for the first problem
117 Real x1_soln = -4;
118 Real x2_soln = -11;
119
120 auto func1 = [&](Real x, Real y, Real & f, Real & dfdx, Real & dfdy)
121 { function_g1(x, y, f, dfdx, dfdy); };
122 auto func2 = [&](Real x, Real y, Real & g, Real & dgdx, Real & dgdy)
123 { function_g2(x, y, g, dgdx, dgdy); };
124 auto func3 = [&](Real x, Real y, Real & g, Real & dgdx, Real & dgdy)
125 { function_g3(x, y, g, dgdx, dgdy); };
127 y1, y2, guess1, guess2, return_x1, return_x2, 1e-8, 1e-8, func1, func2);
128
129 // Check values
130 Real tol = 1e-6;
131 EXPECT_NEAR(return_x1, x1_soln, tol);
132 EXPECT_NEAR(return_x2, x2_soln, tol);
133
134 // Try other combinations of g functions
135 y1 = 0.1;
136 y2 = 1.1196002982765987;
138 y1, y2, guess1, guess2, return_x1, return_x2, 1e-8, 1e-8, func1, func3);
139 x1_soln = 0.1;
140 x2_soln = 0.3;
141 EXPECT_NEAR(return_x1, x1_soln, tol);
142 EXPECT_NEAR(return_x2, x2_soln, tol);
143
144 y1 = 1.98;
145 y2 = 1.1196002982765987;
147 y1, y2, guess1, guess2, return_x1, return_x2, 1e-8, 1e-8, func2, func3);
148 x1_soln = 0.1;
149 x2_soln = 0.3;
150 EXPECT_NEAR(return_x1, x1_soln, tol);
151 EXPECT_NEAR(return_x2, x2_soln, tol);
152
153 // First problem again
154 // Try a degenerate case where the second function has 0 derivative
155 y1 = -3;
156 y2 = -37;
157 x1_soln = -4;
158 x2_soln = -11;
159 auto func2_with_cte = [&](Real x, Real y, Real & g, Real & dgdx, Real & dgdy)
160 {
161 function_g2(x, y, g, dgdx, dgdy);
162 // creates an empty row in the Jacobian
163 dgdy = 0;
164 dgdx = 0;
165 };
167 y1, y2, guess1, x2_soln, return_x1, return_x2, 1e-8, 1e-8, func1, func2_with_cte);
168 EXPECT_NEAR(return_x1, x1_soln, tol);
169 EXPECT_NEAR(return_x2, x2_soln, tol);
170
171 // If there is no solution it should not converge
172 y1 = -2000;
173 y2 = -2000; // no solution
174 try
175 {
177 y1, y2, guess1, guess2, return_x1, return_x2, 1e-8, 1e-8, func1, func3);
178 FAIL();
179 }
180 catch (MooseException &)
181 {
182 }
183}
Real f(Real x)
Test function for Brents method.
const std::vector< double > y
const double tol
const std::vector< double > x
void function_g2(Real x1, Real x2, Real &g, Real &dgdx1, Real &dgdx2)
void function_g1(Real x1, Real x2, Real &g, Real &dgdx1, Real &dgdx2)
void function_f1(Real x1, Real x2, Real &z, Real &dzdx1, Real &dzdx2)
void function_f2(Real x1, Real x2, Real &z, Real &dzdx1, Real &dzdx2)
TEST(NewtonInversion, NewtonSolve)
Tests the implementation of Newton's method to find the roots of: a polynomial of x and y,...
void function_g3(Real x1, Real x2, Real &g, Real &dgdx1, Real &dgdx2)
std::pair< T, T > NewtonSolve(const T &x, const T &y, const Real z_initial_guess, const Real tolerance, const Functor &y_from_x_z, const std::string &caller_name, const unsigned int max_its=100, const bool verbose=false)
NewtonSolve does a 1D Newton Solve to solve the equation y = f(x, z) for variable z.
void NewtonSolve2D(const T &f, const T &g, const Real x0, const Real y0, T &x_final, T &y_final, const Real f_tol, const Real g_tol, const Functor1 &f_from_x_y, const Functor2 &g_from_x_y, const std::string &caller_name="", const unsigned int max_its=100, bool debug=false)
NewtonSolve2D does a 2D Newton Solve to solve for the x and y such that: f = f_from_x_y(x,...