From 2f62c612b0cbec2ff8b969ce5ee31b413482c5b3 Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Thu, 14 Nov 2019 10:32:09 +0100
Subject: [PATCH] YAXN: calculate X using dichotomy, update specs; SPP: fix
 calculated parameters

---
 spec/spp.spec.ts           | 16 +++++++---
 spec/yaxn.spec.ts          |  2 +-
 src/child_nub.ts           | 65 ++++++++++++++++++++++++++++++++++++++
 src/structure/structure.ts | 60 ++---------------------------------
 src/yaxn.ts                | 10 +++---
 5 files changed, 85 insertions(+), 68 deletions(-)
 create mode 100644 src/child_nub.ts

diff --git a/spec/spp.spec.ts b/spec/spp.spec.ts
index 8fb66d14..952f79eb 100644
--- a/spec/spp.spec.ts
+++ b/spec/spp.spec.ts
@@ -40,13 +40,13 @@ describe("Class SPP: ", () => {
 
         it("sum([ 3*X^4, 7*1^0 ]) = 55 - X should be 2", () => {
             const nub = new SPP(new SPPParams(55));
-            nub.addChild(new YAXN(new YAXNParams(3, 666, 4)));
+            nub.addChild(new YAXN(new YAXNParams(3, 5, 4)));
             nub.addChild(new YAXN(new YAXNParams(7, 1, 0)));
             nub.operation = SPPOperation.SUM;
             const c = nub.getChildren()[0] as YAXN;
             nub.calculatedParam = c.prms.X;
             nub.CalcSerie();
-            expect(nub.result.vCalc).toBe(2);
+            expect(nub.result.vCalc).toBeCloseTo(2, 3);
         });
 
     });
@@ -55,13 +55,13 @@ describe("Class SPP: ", () => {
 
         it("product([ 3*X^4, 7*1^0 ]) = 336 - X should be 2", () => {
             const nub = new SPP(new SPPParams(336));
-            nub.addChild(new YAXN(new YAXNParams(3, 666, 4)));
+            nub.addChild(new YAXN(new YAXNParams(3, 17, 4)));
             nub.addChild(new YAXN(new YAXNParams(7, 1, 0)));
             nub.operation = SPPOperation.PRODUCT;
             const c = nub.getChildren()[0] as YAXN;
             nub.calculatedParam = c.prms.X;
             nub.CalcSerie();
-            expect(nub.result.vCalc).toBe(2);
+            expect(nub.result.vCalc).toBeCloseTo(2, 3);
         });
 
     });
@@ -99,4 +99,12 @@ describe("Class SPP: ", () => {
 
     });
 
+    it("non-integer exponent with negative coefficient", () => {
+        const spp = new SPP(new SPPParams(-27));
+        const c1 = new YAXN(new YAXNParams(1, 666, 3));
+        spp.addChild(c1);
+        spp.calculatedParam = c1.prms.X;
+        expect(spp.CalcSerie().vCalc).toBeCloseTo(-3, 3);
+    });
+
 });
diff --git a/spec/yaxn.spec.ts b/spec/yaxn.spec.ts
index b061589b..4d5a54ca 100644
--- a/spec/yaxn.spec.ts
+++ b/spec/yaxn.spec.ts
@@ -14,7 +14,7 @@ describe("Class YAXN: ", () => {
         const nub = new YAXN(new YAXNParams(4.2, 666, 3, 65.625));
         nub.calculatedParam = nub.prms.X;
         nub.CalcSerie();
-        expect(nub.result.vCalc).toBe(2.5);
+        expect(nub.result.vCalc).toBeCloseTo(2.5, 3);
     });
 
     it("non-integer N should trigger error", () => {
diff --git a/src/child_nub.ts b/src/child_nub.ts
new file mode 100644
index 00000000..adef909a
--- /dev/null
+++ b/src/child_nub.ts
@@ -0,0 +1,65 @@
+import { Nub } from "./nub";
+import { ParamDefinition } from "./param/param-definition";
+
+/**
+ * A Nub that is meant to exist within a parent only
+ */
+export abstract class ChildNub extends Nub {
+
+    /**
+     * Forwards to parent, that has vsibility over
+     * all the parameters, including the Structure ones
+     */
+    public unsetCalculatedParam(except: ParamDefinition) {
+        if (this.parent) {
+            this.parent.unsetCalculatedParam(except);
+        }
+    }
+
+    /**
+     * Forwards to parent, that has vsibility over
+     * all the parameters, including the Structure ones
+     */
+    public get calculatedParam(): ParamDefinition {
+        if (this.parent) {
+            return this.parent.calculatedParam;
+        }
+        // For testing purpose without ParallelStructure
+        return this._calculatedParam;
+    }
+
+    /**
+     * Forwards to parent, that has vsibility over
+     * all the parameters, including the Structure ones
+     */
+    public set calculatedParam(p: ParamDefinition) {
+        if (this.parent) {
+            this.parent.calculatedParam = p;
+        } else {
+            // For testing purpose without ParallelStructure
+            this._calculatedParam = p;
+        }
+    }
+
+    /**
+     * Forwards to parent, that has vsibility over
+     * all the parameters, including the Structure ones
+     */
+    public findFirstCalculableParameter(otherThan?: ParamDefinition) {
+        if (this.parent) {
+            return this.parent.findFirstCalculableParameter(otherThan);
+        }
+        return undefined;
+    }
+
+    /**
+     * Forwards to parent, that has visibility over
+     * all the parameters, including the Structure ones
+     */
+    public resetDefaultCalculatedParam(requirer?: ParamDefinition) {
+        if (this.parent) {
+            this.parent.resetDefaultCalculatedParam(requirer);
+        }
+    }
+
+}
diff --git a/src/structure/structure.ts b/src/structure/structure.ts
index 84a4b8c2..e4a37bf4 100644
--- a/src/structure/structure.ts
+++ b/src/structure/structure.ts
@@ -1,5 +1,5 @@
+import { ChildNub } from "../child_nub";
 import { CalculatorType } from "../compute-node";
-import { Nub } from "../nub";
 import { ParamCalculability, ParamDefinition } from "../param/param-definition";
 import { Props } from "../props";
 import { Message, MessageCode } from "../util/message";
@@ -48,7 +48,7 @@ export enum StructureJetType {
 /**
  * classe de calcul sur la conduite distributrice
  */
-export abstract class Structure extends Nub {
+export abstract class Structure extends ChildNub {
 
     /**
      * Test générique si VarCalc="Q" pour l'utilisation de Equation
@@ -125,62 +125,6 @@ export abstract class Structure extends Nub {
         return undefined;
     }
 
-    /**
-     * Forwards to parent, that has vsibility over
-     * all the parameters, including the Structure ones
-     */
-    public unsetCalculatedParam(except: ParamDefinition) {
-        if (this.parent) {
-            this.parent.unsetCalculatedParam(except);
-        }
-    }
-
-    /**
-     * Forwards to parent, that has vsibility over
-     * all the parameters, including the Structure ones
-     */
-    public get calculatedParam(): ParamDefinition {
-        if (this.parent) {
-            return this.parent.calculatedParam;
-        }
-        // For testing purpose without ParallelStructure
-        return this._calculatedParam;
-    }
-
-    /**
-     * Forwards to parent, that has vsibility over
-     * all the parameters, including the Structure ones
-     */
-    public set calculatedParam(p: ParamDefinition) {
-        if (this.parent) {
-            this.parent.calculatedParam = p;
-        } else {
-            // For testing purpose without ParallelStructure
-            this._calculatedParam = p;
-        }
-    }
-
-    /**
-     * Forwards to parent, that has vsibility over
-     * all the parameters, including the Structure ones
-     */
-    public findFirstCalculableParameter(otherThan?: ParamDefinition) {
-        if (this.parent) {
-            return this.parent.findFirstCalculableParameter(otherThan);
-        }
-        return undefined;
-    }
-
-    /**
-     * Forwards to parent, that has visibility over
-     * all the parameters, including the Structure ones
-     */
-    public resetDefaultCalculatedParam(requirer?: ParamDefinition) {
-        if (this.parent) {
-            this.parent.resetDefaultCalculatedParam(requirer);
-        }
-    }
-
     /**
      * Calcul de l'aire d'écoulement sur le seuil ou dans l'orifice
      */
diff --git a/src/yaxn.ts b/src/yaxn.ts
index 90fc7f55..fc1cb4fb 100644
--- a/src/yaxn.ts
+++ b/src/yaxn.ts
@@ -1,5 +1,5 @@
+import { ChildNub } from "./child_nub";
 import { CalculatorType } from "./compute-node";
-import { Nub } from "./nub";
 import { ParamCalculability } from "./param/param-definition";
 import { Message, MessageCode } from "./util/message";
 import { Result } from "./util/result";
@@ -8,7 +8,7 @@ import { YAXNParams } from "./yaxn_params";
 /**
  * Y = A.X^N
  */
-export class YAXN extends Nub {
+export class YAXN extends ChildNub {
 
     constructor(prms: YAXNParams, dbg: boolean = false) {
         super(prms, dbg);
@@ -30,7 +30,7 @@ export class YAXN extends Nub {
                 v = this.prms.A.v * Math.pow(this.prms.X.v, this.prms.N.v);
                 break;
 
-            case "X":
+            /* case "X":
                 // X = (Y/A)^(1/N)
                 if (this.prms.A.v === 0) {
                     const m = new Message(MessageCode.ERROR_DIVISION_BY_ZERO);
@@ -44,7 +44,7 @@ export class YAXN extends Nub {
                 }
                 v = Math.pow((this.prms.Y.v / this.prms.A.v), (1 / this.prms.N.v));
                 break;
-
+ */
             default:
                 throw new Error("YAXN.Equation() : invalid variable name " + sVarCalc);
         }
@@ -55,7 +55,7 @@ export class YAXN extends Nub {
     /** paramétrage de la calculabilité des paramètres */
     protected setParametersCalculability() {
         this.prms.Y.calculability = ParamCalculability.EQUATION;
-        this.prms.X.calculability = ParamCalculability.EQUATION;
+        this.prms.X.calculability = ParamCalculability.DICHO;
     }
 
 }
-- 
GitLab