https://mooseframework.inl.gov
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 
13 void
14 function_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 
21 void
22 function_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 
36 TEST(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 
67 void
68 function_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 
75 void
76 function_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 
83 void
84 function_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 
102 TEST(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  // If there is no solution it should not converge
154  y1 = -2000;
155  y2 = -2000; // no solution
156  try
157  {
159  y1, y2, guess1, guess2, return_x1, return_x2, 1e-8, 1e-8, func1, func3);
160  FAIL();
161  }
162  catch (MooseException &)
163  {
164  }
165 }
void function_g2(Real x1, Real x2, Real &g, Real &dgdx1, Real &dgdx2)
auto exp(const T &)
const double tol
const std::vector< double > y
void function_g1(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 &func, const std::string &caller_name, const unsigned int max_its=100)
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 &func1, const Functor2 &func2, const unsigned int max_its=100)
NewtonSolve2D does a 2D Newton Solve to solve for the x and y such that: f = func1(x, y) and g = func2(x, y).
const std::vector< double > x
Real f(Real x)
Test function for Brents method.
auto log(const T &)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void function_g3(Real x1, Real x2, Real &g, Real &dgdx1, Real &dgdx2)
void function_f2(Real x1, Real x2, Real &z, Real &dzdx1, Real &dzdx2)
TEST(NewtonInversion, NewtonSolve)
Tests the implementation of Newton&#39;s method to find the roots of: a polynomial of x and y...
void function_f1(Real x1, Real x2, Real &z, Real &dzdx1, Real &dzdx2)