/**
   * 构造下列形函数中的一个: N1 = L1 = r N2 = L2 = s N3 = L3 = t
   *
   * @param funID = 1,2,3
   */
  public void Create(int funID, double coef) {
    funIndex = funID - 1;
    if (funID < 1 || 3 < funID) {
      throw new FutureyeException("ERROR: funID should be 1,2 or 3.");
    }

    this.varNames = new String[] {"r", "s", "t"};
    innerVarNames = new ObjList<String>("x", "y");

    // Compose function: r = r(x,y), s = s(x,y), t = t(x,y)
    Map<String, MathFunc> fInners = new HashMap<String, MathFunc>();
    final String varName = varNames[funIndex];
    fInners.put(
        varName,
        new AbstractMathFunc(innerVarNames.toList()) {
          public MathFunc diff(String var) {
            if (area < 0.0) {
              throw new FutureyeException("Check nodes order: area < 0.0");
            } else {
              if (varName.equals("r")) { // r对应三角形高h的负倒数
                if (var.equals("x")) return new FC(b[0] / (2 * area));
                if (var.equals("y")) return new FC(c[0] / (2 * area));
              } else if (varName.equals("s")) { // s对应三角形高h的负倒数
                if (var.equals("x")) return new FC(b[1] / (2 * area));
                if (var.equals("y")) return new FC(c[1] / (2 * area));
              } else if (varName.equals("t")) { // t对应三角形高h的负倒数
                if (var.equals("x")) return new FC(b[2] / (2 * area));
                if (var.equals("y")) return new FC(c[2] / (2 * area));
              }
            }
            return null;
          }

          @Override
          public double apply(double... args) {
            throw new UnsupportedOperationException();
          }
        });

    // 使用复合函数构造形函数
    funOuter = new SF123();
    this.coef = coef;
    funCompose = FC.c(this.coef).M(funOuter.compose(fInners));
    funCompose.setActiveVarNames(funOuter.getVarNames());
  }
  /**
   * 构造下列形函数中的一个: Ni = (1+r*ri)*(1+s*si)*(1+t*ti)/8 where (ri,si,ti),i=1,...,8 are vertices
   * coordinate of the hexahedron
   *
   * @param funID = 1,...,8
   */
  public void Create(int funID, double coef) {
    funIndex = funID - 1;
    if (funID < 1 || funID > 8) {
      System.out.println("ERROR: funID should be 1,...,8.");
      return;
    }

    varNames.add("r");
    varNames.add("s");
    varNames.add("t");
    innerVarNames = new ObjList<String>("x", "y", "z");

    // 复合函数
    Map<String, MathFunc> fInners = new HashMap<String, MathFunc>(4);

    for (final String varName : varNames) {
      fInners.put(
          varName,
          new AbstractMathFunc(innerVarNames.toList()) {

            // r_x,r_y,r_z, s_x,s_y,s_z, t_x,t_y,t_z
            public MathFunc diff(String var) {
              /**
               * f(x,y,z) = g(r,s,t) f_x = g_r*r_x + g_s*s_x + g_t*t_x ---(1) f_y = g_r*r_y +
               * g_s*s_y + g_t*t_y ---(2) f_z = g_r*r_z + g_s*s_z + g_t*t_z ---(3)
               *
               * <p>for (1) let f=x,f=y,f=z we get 3 equations, solve them: (x_r x_s x_t) (r_x) (1)
               * (y_r y_s y_z) * (s_x) = (0) (z_r z_s z_t) (t_x) (0)
               *
               * <p>similarly, for (2): (x_r x_s x_t) (r_y) (0) (y_r y_s y_z) * (s_y) = (1) (z_r z_s
               * z_t) (t_y) (0)
               *
               * <p>for (3): (x_r x_s x_t) (r_z) (0) (y_r y_s y_z) * (s_z) = (0) (z_r z_s z_t) (t_z)
               * (1)
               *
               * <p>(x_r x_s x_t) Let J = (y_r y_s y_z) (z_r z_s z_t)
               *
               * <p>from the above 9 equations, we have: (r_x r_y r_z) (s_x s_y s_z) = inv(J) (t_x
               * t_y t_z)
               */
              return new InvJ(varName, var);
            }

            @Override
            public double apply(Variable v) {
              // TODO Auto-generated method stub
              return 0;
            }
          });
    }

    //		funOuter = new FAxpb("r",vt[funIndex][0]/2.0,0.5).M(
    //				   new FAxpb("s",vt[funIndex][1]/2.0,0.5)).M(
    //				   new FAxpb("t",vt[funIndex][2]/2.0,0.5));
    // 速度提高1倍
    funOuter = new FOuter(varNames, funIndex);

    // 使用复合函数构造形函数
    this.coef = coef;
    funCompose = FC.c(this.coef).M(funOuter.compose(fInners));
  }