Example #1
0
// return 0 or -9 if something is not right
// hard coded assumption that the data would be 2D
int read_2d_arrays(StrBuffer *s, Descriptor *des, SimpleDblArray *d, int with_unit, FILE *out) {
  int jj=0;
  int cntr=0;
  char *t;
  double ss;
  if (with_unit) {
    if ( (t=s->Get_ith_Value(des[2]._key, 0 )) == NULL ) {
      if (out) fprintf(out,"Bummer: unable to locate keyword \"%s\" for array on line %d\n", 
		       des[2]._key, s->LineNumber());
      return 0;
    }

    ss = convert_time_scale(t, Time_Descriptor);
    if ( ss < 0 ) {
      if (out) fprintf(out,"Bummer: only accept time scale of SECOND, MINUTE, HOUR for statement on line %d \n", s->LineNumber());
      return 0;
    }

    d->SetScale( ss );
    jj++;  // move to the first one
  }

  for (; jj<s->NumPairs(); jj+=2) {  // jj has been set
    if ( (t=s->Get_ith_Value(des[0]._key, jj))==NULL) {
      if (out) fprintf(out,"Bummer: unable to locate keyword \"%s\" for array on line %d\n", 
		       des[0]._key, s->LineNumber());
      return 0;
    }
    if ( !is_scientific(t) ) {
      if (out) fprintf(out, "Bummer: invalid number found in field \"%s\" on line %d\n",
		       des[0]._key, s->LineNumber());
      return 0;
    } else {
      d->ithX(cntr) = atof(t);
    }

    if ( (t = s->Get_ith_Value(des[1]._key, jj+1))==NULL) {
      if (out) fprintf(out,"Bummer: unable to locate keyword \"%s\" for array on line %d\n", 
		       des[1]._key, s->LineNumber());
      return 0;
    }
    if ( !is_scientific(t) ) {
      if (out) fprintf(out, "Bummer: invalid number found in field \"%s\" on line %d\n",
		       des[1]._key, s->LineNumber());
      return 0;
    } else {
      d->ithY(cntr++) = atof(t);
    }
  }
  return cntr;
}
Example #2
0
// top level function to parse the spt netlist and construct the SUBCATCHMENT object
// as well as modifying the Options and Sgraph objects
int read_spt_from_file(FILE* F, Subcatchment *SUB, NameStore *NODE_NAMES, SMap *HASH, FILE* out) {

  FirstDef rc;
  int r_code;
  int line_num, good, node_index;
  source_id src_id;
  unsigned int n_op,n_node, n_seg, n_junc, n_qs, n_ls, n_bdn;
  StrBuffer *Prime, *Second;
  SimpleDblArray dba;
  double *XX=NULL, *YY=NULL;

  FlexVec<int, SHORT_ARRY_LENGTH>  qsources; // we store index only
  FlexVec<int, SHORT_ARRY_LENGTH>  lsources;
  FlexVec<int, SHORT_ARRY_LENGTH>  asources;
  
  ChkSum   mychk;
  char     chktmp[10];

  Prime = new StrBuffer(1023);  // both arrayes can automatically grow if needed
  Second = new StrBuffer(4095);
  r_code = -1;      // by default, the return code indicates failure
  
  /* we first read the option blocks */
  rc = def_not_found;
  line_num = 0;
  
  n_op = n_node = n_seg = n_junc = n_qs = n_ls = n_bdn = 0;
  while (1) { // first do the tally, and a rough check
    rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, out); 
    switch (rc) {
    case p_options: n_op++; break;
    case p_node:  n_node++; break;
    case p_segment: n_seg++; break;
    case p_junction: n_junc++; break;
    case p_qsource: n_qs++; break;
    case p_lateralsource: n_ls++; break;
    case p_boundarycondition: n_bdn++; break;
    case def_not_found: break;
    case def_error: 
      goto back;
      break;
    default: break;
    }
    if ( rc == def_not_found ) break;
  }
  rewind(F);
  
  if (out) {
    fprintf(out,"[II]: Found %d nodes, %d segmetns, %d junctions, %d q_sources, %d lateral sources, %d bdn condtions, %d options in the netlist\n", 
	    n_node, n_seg, n_junc, n_qs, n_ls, n_bdn, n_op);
  }
  if ( n_node < 2 ) {
    if (out) fprintf(out, "Bummer: not enough node statements, unable to procced\n");
    goto back;
  } else if ( n_seg < 1 ) {
    if (out) fprintf(out, "Bummer: not enough segment statements, unable to procced\n");
    goto back;
  } else if ( n_qs < 1 ) {
    if (out) fprintf(out, "Bummer: not enough Q source statements, unable to procced\n");
    goto back;
  } else if ( n_bdn < 1 ) {
    if (out) fprintf(out, "Bummer: not enough boundary condition statements, unable to procced\n");
    goto back;
  }
  
  // Copy the stat into the STAT object
  STAT.N_Nodes() = n_node;
  STAT.N_Segs() = n_seg;
  STAT.N_Juncs() = n_junc;
  STAT.N_Qsrcs() = n_qs;
  STAT.N_Lsrcs() = n_ls;
  STAT.N_Bnds() = n_bdn;

  // do the memory allocation stuff here
  NODE_NAMES->Init(n_node);
  SUB->InitGraph(n_node, n_seg, n_junc); //Testing

  // allocate memory to store the boundary conditions
  qsources.size(n_node+10);
  lsources.size(n_node+10);
  asources.size(n_node+10);

  for (unsigned int jj=0; jj<n_node+10; jj++) qsources[jj]=-1;
  for (unsigned int jj=0; jj<n_node+10; jj++) lsources[jj]=-1;
  for (unsigned int jj=0; jj<n_node+10; jj++) asources[jj]=-1;

  // we now proess options, otherwise we use default values
  if ( n_op > 0 ) {
    char *tmp;
    double stoptimeunit=1.0, timestepunit=1.0, prtintervalunit=1.0;
    double stoptime=-1.0, timestep=0.0, prtinterval=0.0;
    double prtstartunit = 1.0, prtstart = 0.0;
    double spinuptime = 0.0;

    rewind(F);
    rc = def_not_found;
    line_num = 0;
    while (1) {  
      rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); 
      
      if (rc == def_not_found ) break;
      if (rc != p_options ) continue;
      
      // read the options, in particular UseMetric!     
      good = Prime->Separate(out);
      if (good<0) {
	if (out) fprintf(out,"Bummer: Syntax error in netlist specification at line %d\n", line_num);
	goto back;
      }
      tmp = Prime->Find_Value( Op_Descriptor[0]._key); // USEMETRIC
      if (tmp) {
	OPT.UseMetric() = atoi(tmp)>0 ? 1 : 0;
	if (out) fprintf(out,"[II]: Metric set to %d\n", OPT.UseMetric());
      }

      // we process unit first so that we don't have to worry later
      tmp = Prime->Find_Value( Op_Descriptor[2]._key); // TIMESTEPUNIT
      if (tmp) {
	timestepunit = convert_time_scale(tmp, Time_Descriptor);
      }
      if ( timestepunit < 0 ) {
	if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", 
			 Prime->LineNumber());
	timestepunit = 1.0;
      }
      
      tmp = Prime->Find_Value( Op_Descriptor[1]._key); // TIMESTEP
      if (tmp) timestep = atof(tmp);

      tmp = Prime->Find_Value( Op_Descriptor[4]._key); // STOPTIMEUNIT
      if (tmp) {
	stoptimeunit = convert_time_scale(tmp, Time_Descriptor);
      }
      if ( stoptimeunit < 0 ) {
	if (out) fprintf(out,"Bummer:only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", 
			 Prime->LineNumber());
	stoptimeunit = 1.0;
      }

      tmp = Prime->Find_Value( Op_Descriptor[3]._key); // STOPTIME
      if (tmp) stoptime = atof(tmp);

      // also deal with print interval first
      tmp = Prime->Find_Value( Op_Descriptor[6]._key); // PRTINTERVALUNIT
      if (tmp) {
	prtintervalunit = convert_time_scale(tmp, Time_Descriptor);
      }
      if ( prtintervalunit < 0 ) {
	if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", 
			 Prime->LineNumber());
	prtintervalunit = 1.0;
      }

      
      tmp = Prime->Find_Value( Op_Descriptor[8]._key); // PRTSTARTUNIT
      if (tmp) {
	prtstartunit = convert_time_scale(tmp, Time_Descriptor);
      }
      if ( prtstartunit < 0 ) {
	if (out) fprintf(out,"[WW]: only accept time unit of SECOND, MINUTE, HOUR for statement on line %d. Use default=SECOND. \n", 
			 Prime->LineNumber());
	prtstartunit = 1.0;

      }

      tmp = Prime->Find_Value( Op_Descriptor[7]._key); // PRTSTART
      if (tmp) prtstart = atof(tmp);

      tmp = Prime->Find_Value( Op_Descriptor[5]._key); // PRTINTERVAL
      if (tmp) prtinterval = atof(tmp);
      if ( prtinterval < 0 ) {
	if (out) fprintf(out,"[WW]: negative print interval specified on line %d. Overwritten with zero!\n",
			 Prime->LineNumber());
	prtinterval = 0.0;
      }
      
      tmp = Prime->Find_Value( Op_Descriptor[9]._key); // CHECKONLY
      if (tmp) {
	OPT.CheckOnly() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: CheckOnly set to %d\n", OPT.CheckOnly());
      }
      
      tmp = Prime->Find_Value( Op_Descriptor[10]._key); // SSFILE
      if (tmp) {
	STAT.SetSSFile(tmp);
	if (out) fprintf(out, "[II]: SSFile (SteadyState file) set to \"%s\"\n", tmp);
      }

      tmp = Prime->Find_Value( Op_Descriptor[11]._key); // Lmax
      if (tmp) {
	OPT.LMax() = atof(tmp);
	if (out) fprintf(out,"[II]: LMax set to %.4e\n", OPT.LMax() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[12]._key); // Lmin
      if (tmp) {
	OPT.LMin() = atof(tmp);
	if (out) fprintf(out,"[II]: LMin set to %.4e\n", OPT.LMin() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[13]._key); // PrintDepth
      if (tmp) {
	OPT.PrintD() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: PrtDepth set to %1d\n", OPT.PrintD() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[14]._key); // PrintSurfElev
      if (tmp) {
	OPT.PrintZ() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: PrtSurfElev set to %1d\n", OPT.PrintZ() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[15]._key); // PrintQ
      if (tmp) {
	OPT.PrintQ() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: PrtQ set to %1d\n", OPT.PrintQ() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[16]._key); // PrintA
      if (tmp) {
	OPT.PrintA() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: PrtA set to %1d\n", OPT.PrintA() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[17]._key); // PrintCoord
      if (tmp) {
	OPT.PrintXY() = atoi(tmp) > 0 ? 1 : 0;
	if (out) fprintf(out,"[II]: PrtCoord set to %1d\n", OPT.PrintXY() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[18]._key); // verbose
      if (tmp) {
	OPT.DebugLevel() = atoi(tmp) > 0 ? atoi(tmp) : 0;
	if (out) fprintf(out,"[II]: Verbose set to %1d\n", OPT.DebugLevel() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[19]._key); // epoch
      if (tmp) {
	STAT.SetEpoch(tmp);
	if (out) fprintf(out, "[II]: Epoch is set to %s\n", STAT.Epoch() );
      }

      tmp = Prime->Find_Value( Op_Descriptor[20]._key); // spinup_time
      if (tmp) spinuptime = atof(tmp);
      if ( spinuptime < 0 ) {
	if (out) fprintf(out,"[WW]: negative spin-up time specified on line %d. Use zero instead (disabled)\n",
			 Prime->LineNumber());
	spinuptime = 0.0;
      }
      
    }

    // check if stoptime is specified (by setting default to 0), 
    // do the scaling,
    // reason: we might have multiple option blocks

    if ( timestep < 0 ) {
      if (out) fprintf(out,"[WW]: negative TimeStep specified. Overwritten with zeor!\n");
    } else if (timestep > 0) {
      timestep *= timestepunit;
      OPT.FixedStep() = timestep;
      if (out) fprintf(out,"[II]: TimeStep set to %.3e second.\n", timestep);
    }
    
    if ( prtinterval < 0 ) {
      if (out) fprintf(out,"[WW]: negative PrInterval specified. Overwritten with zero!\n");
    } else if (prtinterval>0) {
      int tt;
      prtinterval *= prtintervalunit;
      tt = (int) round(prtinterval/60.0);
      tt = tt >=0 ? tt : 0;
      OPT.PrintInterval() = tt;
      if (out) fprintf(out,"[II]: PrtInterval set to %d min\n", tt);
    }

    if (prtstart < 0) {
      if (out) fprintf(out,"[WW]: negative PrtStart specified. Overwritten with zero!\n");
    } else if ( prtstart > 0) {
      int tt;
      prtstart *= prtstartunit;
      tt = (int)round(prtstart/60.0);
      tt = tt>=0 ? tt : 0;
      OPT.PrintStart() = tt;
      if (out) fprintf(out, "[II]: PrtStart set to %d min\n", tt);
    }

    if (stoptime > 0 ) {
      stoptime *= stoptimeunit;
      OPT.StopTime() = stoptime;
      if (out) fprintf(out,"[II]: StopTime set to %.3e second\n", stoptime);
    } else {
      if (out) fprintf(out,"Bummer: a positive StopTime is required in order to run the simulation!\n");
      goto back;
    }

    if ( spinuptime > 0 ) {
      int tt = (int)spinuptime;
      const int min_spin = 300;
      if ( tt > min_spin ) {
	OPT.SpinUpTime() = tt;
	if (out) fprintf(out,"[II]: SpinUpTime set to %d second\n", tt);
      } else {
	OPT.SpinUpTime() = 0;
	if (out) fprintf(out,"[WW]: minimal spinup time is %d seconds. Revert back to zero (spinup disabled)\n", min_spin);
      }
    }
  }
  
  
  // add nodes,  check duplicate
  rewind(F);
  rc = def_not_found;
  line_num = 0;
  while (1) {  
    char node_id[MAX_LINE_LENGTH];
    char *tmp;
    double s0, n, h0, z0, width, slope;
    XsecType xtp;
    int   num_pairs;
    double q0=0, a0=0;  // we will deal with them later
    double x=-1.0, y=-1.0;  // not used 

    rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); 
    
    // we don't check on the error flags since we have done it before
    if (rc == def_not_found ) break;   // we added all nodes
    if (rc == def_error ) goto back;  

    width = 0.0;
    slope = 0.0;
    num_pairs = 0;
    switch (rc) {
    case p_node:
      /* intercept and understand node */
      if ( !Second->HasContent()) {
	if (out) fprintf(out,"Bummer: NODE statement on line %d requires a x-section specification\n", Prime->LineNumber() );
	goto back;
      }
      good = Prime->Separate(out);
      good = Second->Separate(out);
      
      if (good <0) {
	if (out) fprintf(out,"Bummer: syntax error in netlist specification in line %d\n", Prime->LineNumber());
	goto back;
      }

      // parse each field one by one
      tmp = Prime->Find_Value( Node_Descriptor[0]._key); // "id"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[0]._key, 
			 Prime->LineNumber());
	goto back;
      }
      // the clean node id is now in node_id;
      strncpy(node_id, tmp, MAX_WORD_LENGTH);
      node_index = HASH->Check(node_id);
      if ( node_index != -1 ) {
	if (out) fprintf(out,"Bummer: duplicated NODE definition of node \"%s\" on line %d\n", node_id, Prime->LineNumber() );
	goto back;
      }
      node_index = HASH->Create(node_id);
      NODE_NAMES->Insert(node_id, node_index);
      
      tmp = Prime->Find_Value( Node_Descriptor[1]._key);  // "sR"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[1]._key, 
			 Prime->LineNumber());
	goto back;
      }
      s0 = atof(tmp);
      if ( s0 < 1e-6 ) {
	if (out) fprintf(out, "[WW]: reference slope sR at location %s is nonpositive with value of %.4e. \n", node_id, s0);
#if 0
	goto back;
#endif
      }

      tmp = Prime->Find_Value( Node_Descriptor[2]._key);  // "n"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[2]._key, 
			 Prime->LineNumber());
	goto back;
      }
      n = atof(tmp);
      if ( n < OPT.MinN() ) {
	if (out) fprintf(out,"[WW]: Manning's N at location %s is %.4e, less than threshold value %.4e. Supercritical flow might occur\n",
			 node_id, n, OPT.MinN());
      }
      
      tmp = Prime->Find_Value( Node_Descriptor[3]._key);  // "zR"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[3]._key, 
			 Prime->LineNumber());
	goto back;
      }
      z0 = atof(tmp);
      
      
      tmp = Prime->Find_Value( Node_Descriptor[4]._key);  // "hR"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the NODE statement on line %d\n", Node_Descriptor[4]._key, 
			 Prime->LineNumber());
	goto back;
      }
      h0 = atof(tmp);
      
      tmp = Prime->Find_Value( Node_Descriptor[5]._key); // "xcoord"
      if (tmp) {
	x = atof(tmp);    // this is optional
      }

      tmp = Prime->Find_Value( Node_Descriptor[6]._key); // "ycoord"
      if (tmp) {
	y = atof(tmp);
      }

      if ( Second->Cmp_Head(Node_Descriptor[7]._key)) {   // "Trapezoidal
	tmp = Second->Find_Value(Trap_Descriptor[0]._key);  // "bottomwidth"
	if (!tmp) {
	  if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[5]._key, 
			   Second->LineNumber(), Trap_Descriptor[0]._key);
	  goto back;
	}
	width = atof(tmp);
	
	tmp = Second->Find_Value(Trap_Descriptor[1]._key);  // "slope"
	if (!tmp) {
	  if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[5]._key, 
			   Second->LineNumber(), Trap_Descriptor[1]._key);
	  goto back;
	} else {
	  slope = atof(tmp);
	}
	xtp = TRAP;
	
      } else if ( Second->Cmp_Head(Node_Descriptor[8]._key)) {  // "Rectangular"
	tmp = Second->Find_Value(Rect_Descriptor[0]._key);  // "bottomwidth"
	if (!tmp) {
	  if (out) fprintf(out, "Bummer: %s x-section on line %d requires field %s\n", Node_Descriptor[6]._key, 
			   Second->LineNumber(), Rect_Descriptor[0]._key);
	  goto back;
	} else {
	  width = atof(tmp);
	}
	xtp = RECT;
	
      } else if ( Second->Cmp_Head(Node_Descriptor[9]._key)) { // "XY"
	if ( Second->NumPairs() % 2 != 0 ) {
	  if (out) fprintf(out,"Bummer: unbalanced XY pairs for %s statement on line %d\n", 
			   Node_Descriptor[7]._key,Second->LineNumber());
	  goto back;
	  
	} else {  // all good, copy the values
	  dba.Reset();
	  num_pairs = read_2d_arrays(Second, XY_Descriptor, &dba, 0, out);
	  
	  if ( num_pairs <= 0 ) {
	    if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() );
	    goto back;
	  }
	}
	xtp = SPLINE;
	
      } else {
	if (out) fprintf(out,"Bummer: NODE statement on line %d requires at least one of the x-section specification: %s, %s or %s\n",
			 Prime->LineNumber(), Node_Descriptor[5]._key, Node_Descriptor[6]._key, Node_Descriptor[7]._key);
	goto back;
      }
      
      // at this point, all variables are ready, create the node
      // use node_idx, s0, n, h0, z0, dba (good)
      // first do scaling based UseMetric()
      XX = dba.X();
      YY = dba.Y();
      if (OPT.UseMetric() == 0 ) {
	if (xtp == SPLINE) {
	  for (int jj=0; jj<num_pairs; jj++) {
	    XX[jj] *= OPT.FtoM();
	    YY[jj] *= OPT.FtoM();
	  }
	} else {  // RECT or TRAP, only change the bottom width, slope is dimensionless
	  width *= OPT.FtoM();
	}
	z0 *= OPT.FtoM();
	h0 *= OPT.FtoM();
      }
      
      if ( xtp == SPLINE ) {
#ifdef DBGSPLINE
	printf("node name %s, id %d\n", node_id, (unsigned int)node_index); 
#endif
	SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, SPLINE, num_pairs, XX, YY);
      } else if (xtp == TRAP) {
	SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, TRAP, width, slope);
      } else if (xtp == RECT) {
	SUB->MakeNode((unsigned int)node_index, s0, n, x, y, q0, a0, z0, h0, RECT, width);
      }
      
      break;

    default: break;

    } // end switch
  }   // while loop, find all nodes


  // make SUB happy
  SUB->AssignNodes();


  // records Qsrc, Lsrc and Bdn's
  rewind(F);
  rc = def_not_found;
  line_num = 0;
  while (1) {  
    char node_id[MAX_LINE_LENGTH];
    char *tmp;
    int   num_pairs;
    int loc_index, bnd_is_area;
    Node *node=NULL;
    //    double geo_scale=1.0;

    rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); 
    
    // we don't check on the error flags since we have done it before
    if (rc == def_not_found ) break;   // we added all nodes
    if (rc == def_error ) goto back;  

    num_pairs = 0;
    switch (rc) {
    case p_qsource:
      if (!Second->HasContent()) {
	if (out) fprintf(out,"Bummer: QSOURCE statement on line %d requires a time series specification\n", Prime->LineNumber() );
	goto back;
      }
      good = Prime->Separate(out);
      good = Second->Separate(out);
      
      if (good<0) {
	if (out) fprintf(out,"Bummer: syntax error in netlist specification in line %d\n", line_num);
	goto back;
      }

      tmp = Prime->Find_Value( Qsource_Descriptor[0]._key); // "location"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the QSOURCE statement on line %d\n", Qsource_Descriptor[0]._key, 
			 Prime->LineNumber());
	goto back;
      }
      if ( !Second->Cmp_Head( Qsource_Descriptor[1]._key) ) { // "timeseries"
	if (out) fprintf(out,"Bummer: QSOURCE statement on line %d requires time series specification: %s\n",
			 Prime->LineNumber(), Qsource_Descriptor[1]._key);
	goto back;
      }

      strncpy(node_id, tmp, MAX_WORD_LENGTH);
      loc_index = HASH->Check(node_id);
      if ( loc_index == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 node_id, Prime->LineNumber());
	goto back;
      }
      
      dba.Reset();
      num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out);
      if ( num_pairs <= 0 ) {
	if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() );
	goto back;
      }

      // ready to insert Q source, with node and time series in dba (good), remember the
      // dba.Scale() field, which is the time scale
      XX = dba.X();
      YY = dba.Y();
      src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F3toM3():1.0) );
      if (src_id<0) {
	if (out) fprintf(out,"Bummer: problem with QSource at node \"%s\" on line %d\n",
			 node_id, Prime->LineNumber());
	goto back;
      }
      
      if ( qsources[ loc_index] > -1 ) {
	if (out) fprintf(out, "Bummer: duplicated definitino of Qsource at node \"%s\"\n",
			 node_id);
	goto back;
      }

      qsources[ loc_index ] = src_id; // store the index
      break;

    case p_lateralsource:
      if (!Second->HasContent()) {
	if (out) fprintf(out,"Bummer: LATERALSOURCE statement on line %d requires a time series specification\n", Prime->LineNumber() );
	goto back;
      }
      good = Prime->Separate(out);
      good = Second->Separate(out);
      
      if (good<0) {
	if (out) fprintf(out,"Bummer: problem with LateralSource on line %d\n",
			 Prime->LineNumber());
	goto back;
      }

      tmp = Prime->Find_Value( Latsource_Descriptor[0]._key); // "location"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the LATERALSOURCE statement on line %d\n", Latsource_Descriptor[0]._key, 
			 Prime->LineNumber());
	goto back;
      }
      if ( !Second->Cmp_Head( Latsource_Descriptor[1]._key) ) { // "timeseries"
	if (out) fprintf(out,"Bummer: LATERALSOURCE statement on line %d requires time series specification: %s\n",
			 Prime->LineNumber(), Latsource_Descriptor[1]._key);
	goto back;
      }

      strncpy(node_id, tmp, MAX_WORD_LENGTH);
      loc_index = HASH->Check(node_id);
      if ( loc_index == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 node_id, Prime->LineNumber());
	goto back;
      }
      
      dba.Reset();
      num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out);
      if ( num_pairs <= 0 ) {
	if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() );
	goto back;
      }
      // ready to insert lateral source, with loc_index and time series in dba (good),
      // remember dba.Scale()
      XX = dba.X();
      YY = dba.Y();
      src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F3toM3():1.0) );
      if (src_id<0) {
	if (out) fprintf(out,"Bummer: problem with LATERALSOURCE at node \"%s\" on line %d\n",
			 node_id, Prime->LineNumber());
	goto back;
      }

      if ( lsources[ loc_index ] > -1 ) {
	if (out) fprintf(out, "Bummer: duplicated definitino of LATERALSOURCE at node \"%s\"\n",
			 node_id);
	goto back;
      }
      lsources[ loc_index ] = src_id;

      break;

    case p_boundarycondition:

      if (!Second->HasContent()) {
	if (out) fprintf(out,"Bummer: BOUNDARYCONDITION statement on line %d requires a time series specification\n", Prime->LineNumber() );
	goto back;
      }
      good = Prime->Separate(out);
      good = Second->Separate(out);
      if (good<0) {
	if (out) fprintf(out,"Bummer: syntax error in BoundaryCondition Statement in line %d\n", Prime->LineNumber());
	goto back;
      }

      tmp = Prime->Find_Value( Bdn_Descriptor[1]._key); // "type" 
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the BOUNDARYCONDITION statement on line %d\n", Bdn_Descriptor[1]._key, 
			 Prime->LineNumber());
	goto back;
      }
      if ( cmp_string(tmp, BdnType_Descriptor[0]._key) ) { // "AREA"
	bnd_is_area = 1;
      } else if (cmp_string(tmp, BdnType_Descriptor[1]._key) ) { // "DEPTH"
	bnd_is_area = 0;
      } else {
	if (out) fprintf(out, "Bummer: BoundaryCondition has to be either \"%s\" or \"%s\" for statement on line %d\n",
			 BdnType_Descriptor[0]._key, 
			 BdnType_Descriptor[1]._key,
			 Prime->LineNumber() );
	goto back;
      }
      
      tmp = Prime->Find_Value( Bdn_Descriptor[0]._key); // "location"
      if (!tmp) {
	if (out) fprintf(out, "Bummer: unable to locate field %s for the BOUNDARYCONDITION statement on line %d\n", Bdn_Descriptor[0]._key, 
			 Prime->LineNumber());
	goto back;
      }

      strncpy(node_id, tmp, MAX_WORD_LENGTH);
      loc_index = HASH->Check(node_id);
      if ( loc_index == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 node_id, Prime->LineNumber());
	goto back;
      }
      
      if ( !Second->Cmp_Head( Bdn_Descriptor[2]._key) ) { // "timeseries"
	if (out) fprintf(out,"Bummer: BOUNDARYCONDITION statement on line %d requires time series specification: %s\n",
			 Prime->LineNumber(), Bdn_Descriptor[2]._key);
	goto back;
      }

      dba.Reset();
      num_pairs = read_2d_arrays(Second, TS_Descriptor, &dba, 1, out);
      if ( num_pairs <= 0 ) {
	if (out) fprintf(out,"Bummer: error reading 2D data specified on line %d\n", Second->LineNumber() );
	goto back;
      }

      // ready to insert Bdn condition, with loc_index and time series in dba (good),
      // remember dba.Scale()
      XX = dba.X();
      YY = dba.Y();
      if ( bnd_is_area == 0 ) {
	node = SUB->GetNode( loc_index );
	if ( !node ) {
	  if (out) fprintf(out, "Bummer: node \"%s\" not yet defined!\n", node_id);
	  goto back;
	}
      }
      if ( bnd_is_area) {
	src_id = SUB->MakeSource(num_pairs, &XX[0], &YY[0], dba.Scale(), (OPT.UseMetric()==0?OPT.F2toM2():1.0) );
      } else {
	FlexVec<double> tmp;
	tmp.size(num_pairs);
	node = SUB->GetNode( loc_index);
	for (int jj=0; jj<num_pairs;jj++) { 
	  tmp[jj]= node->GetAbyDepth( YY[jj]*(OPT.UseMetric()==0?OPT.FtoM():1.0) );
	}
	src_id = SUB->MakeSource(num_pairs, &XX[0], &tmp[0], dba.Scale(), 1.0);
      }

      if (src_id < 0) {
	if (out) fprintf(out, "Bummer: problem with BoundaryCondition definition on line %d\n", Prime->LineNumber() );
	goto back;
      }
      if ( asources[ loc_index] >-1 ) {
	if (out) fprintf(out, "Bummer: duplicated definitino of BOUNDARYCONDITION at node \"%s\"\n",
			 node_id);
	goto back;
      }
      asources[ loc_index ] = src_id;
      break;

    default: break;

    } // end switch
  }   // while loop, found all qsource, lsources and asources

  // process the rest, segments, junctions
  rc = def_not_found;
  rewind(F);
  line_num = 0;
  while (1) {  
    int up_idx, down_idx;
    int up1_idx, up2_idx;
    double length, coef1, coef2;
    char *tmp;
    Node *fp, *tp;

    rc = search_block(F, &line_num, Spt_Descriptor, DES_SIZE(Spt_Descriptor), Prime, Second, NULL); 
    
    if (rc == def_error) goto back;
    if (rc == def_not_found) break;

    switch ( rc ) {
    case p_segment:
      good = Prime->Separate(out);
      if (good<0) {
	if (out) fprintf(out,"Bummer: syntax error in netlist specification at line %d\n", Prime->LineNumber());
	goto back;
      }

      tmp = Prime->Find_Value( Segment_Descriptor[0]._key); // "up" 
      if ( !tmp) {
	if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n",
			 Prime->LineNumber(), Segment_Descriptor[0]._key);
	goto back;
      }
      up_idx = HASH->Check(tmp);
      if ( up_idx == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 tmp, Prime->LineNumber());
	goto back;
      }

      tmp = Prime->Find_Value( Segment_Descriptor[1]._key); // "down:
      if ( !tmp) {
	if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n",
			 Prime->LineNumber(), Segment_Descriptor[1]._key);
	goto back;
      }
      down_idx = HASH->Check(tmp);
      if ( down_idx == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 tmp, Prime->LineNumber());
	goto back;
      }
      tmp = Prime->Find_Value( Segment_Descriptor[2]._key); // "length"
      if ( !tmp ) {
	if (out) fprintf(out, "Bummer: SEGMENT statement on line %d requires the \"%s\" field.\n",
			 Prime->LineNumber(), Segment_Descriptor[2]._key);
	goto back;
      }
      if ( !is_scientific( tmp ) ) {
	if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber());
	goto back;
      }
      length = atof(tmp);

      // ready to insert segment, use up_idx, down_idx, length, check length > 0!
      if ( length <= 0.0 ) {
	if (out) fprintf(out,"Bummer: found negative or zero length on line %d\n", Prime->LineNumber() );
	goto back;
      }
      if ( length <= OPT.LMin() ) {
	if (out) fprintf(out,"[WW]: segment length on line %d is %.4e, less than preferred minimal %.4e\n",
			 Prime->LineNumber(), length, OPT.LMin());
      }
      if ( length >= OPT.LMax() ) {
	if (out) fprintf(out,"[WW]: segment length on line %d is %.4e, larger than preferred maxium %.4e\n",
			 Prime->LineNumber(), length, OPT.LMax());
      }

      if (OPT.UseMetric() == 0 ) length *= OPT.FtoM();

      fp = SUB->GetNode( up_idx );
      tp = SUB->GetNode( down_idx );
      if (fp == NULL) {
	if (out) fprintf(out,"Bummer: internal error, unable to locate node at index %d for statement on line %d\n", 
			 up_idx, Prime->LineNumber());
	goto back;
      }      
      if (tp == NULL) {
	if (out) fprintf(out,"Bummer: internal error, unable to locate node at index %d for statement on line %d\n", 
			 down_idx, Prime->LineNumber());
	goto back;
      }

      // in case we have a lateral source
      src_id = lsources[up_idx];
      SUB->MakeStvEquation( up_idx, down_idx, length, src_id );

      break;

    case p_junction:
      good = Prime->Separate(out);
      if (good<0) {
	if (out) fprintf(out,"Bummer: syntax error in netlist specification at line %d\n", Prime->LineNumber());
	goto back;
      }
      
      tmp = Prime->Find_Value( Junc_Descriptor[0]._key); // "up1" 
      if (tmp) {
	up1_idx = HASH->Check(tmp);
	if ( up1_idx == -1 ) {
	  if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			   tmp, Prime->LineNumber());
	  goto back;
	}
      } else up1_idx = -1;


      tmp = Prime->Find_Value( Junc_Descriptor[1]._key); // "up2:
      if (tmp) {
	up2_idx = HASH->Check(tmp);
	if ( up2_idx == -1 ) {
	  if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			   tmp, Prime->LineNumber());
	  goto back;
	}
      } else up2_idx = -1;


      tmp = Prime->Find_Value( Junc_Descriptor[2]._key); // "down"
      if ( !tmp) {
	if (out) fprintf(out, "Bummer: JUNCTION statement on line %d requires the \"%s\" field.\n",
			 Prime->LineNumber(), Junc_Descriptor[2]._key);
	goto back;
      }
      down_idx = HASH->Check(tmp);
      if ( down_idx == -1 ) {
	if (out) fprintf(out, "Bummer: cannot find node \"%s\" specified on line %d\n",
			 tmp, Prime->LineNumber());
	goto back;
      }

      tmp = Prime->Find_Value( Junc_Descriptor[3]._key); // "coeff1"
      if (tmp) {
	if ( !is_scientific( tmp ) ) {
	  if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber());
	  goto back;
	}
	coef1 = atof(tmp);
	if ( coef1 <= 0.0 ) {
	  if (out) fprintf(out, "Bummer: coefficient should be positive on line %d\n",Prime->LineNumber());
	  goto back;
	}
      } else coef1 = -1.0;

      tmp = Prime->Find_Value( Junc_Descriptor[4]._key); // "coeff2"
      if ( tmp) {
	if ( !is_scientific( tmp ) ) {
	  if (out) fprintf(out, "Bummer: invalid real value specification on line %d\n",Prime->LineNumber());
	  goto back;
	}
	coef2 = atof(tmp);
	if ( coef2 <= 0.0 ) {
	  if (out) fprintf(out, "Bummer: coefficient should be positive on line %d\n",Prime->LineNumber());
	  goto back;
	}
      } else coef2 = -1.0;

      // ready to insert junction, use up1_idx, up2_idx, down_idx, coef1, coef2, check
      if ( up1_idx == -1 && up2_idx == -1 ) {
	if (out) fprintf(out,"Bummer: at least one upstream nodes has to be specified on line %d\n",
			 Prime->LineNumber() );
	goto back;
      }

      if ( coef1 < 0 && coef2 < 0 ) {
	if (out) fprintf(out,"Bummer: at least one upstream coefficients has to be specified on line %d\n",
			 Prime->LineNumber() );
	goto back;
      }

      if ( (up1_idx > 0 && coef1 < 0) || ( up2_idx>0 && coef2<0 ) ) {
	if (out) fprintf(out,"Bummer: mismatch in upstream node and coefficient specifications on line %d\n",
			 Prime->LineNumber());
	goto back;
      }

      /* To add: 
	 distance check among three nodes, use X() and Y() of each node 
       */
      int nn[2];
      double rr[2];

      if ( up1_idx > 0 && up2_idx > 0 ) {  // both
	nn[0] = up1_idx; 
	nn[1] = up2_idx;
	rr[0] = coef1;
	rr[1] = coef2;
	SUB->MakeDepEquation( down_idx, 2, &nn[0], &rr[0]);

      } else if ( up1_idx > 0 ) {    // up1 only
	nn[0] = up1_idx;
	rr[0] = coef1;
	SUB->MakeDepEquation( down_idx, 1, &nn[0], &rr[0]);

      } else {    // up2 only
	nn[0] = up2_idx;
	rr[0] = coef2;
	SUB->MakeDepEquation( down_idx, 1, &nn[0], &rr[0]);

      }

      break;

    default:
      break;
    }
  }
  
  // insert Qsrc, lateral source and Bdn
  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    if ( qsources[jj] > -1) {
      if ( SUB->GetSource( qsources[jj])->GetParent() >= 0 ) {
	if (out) fprintf(out, "Bummer: trying to re-use qsource at node index %d\n",jj);
	goto back;
      }
      SUB->MakeQrSrcEquation( jj, qsources[jj] );
    }
  }

  
  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    if ( asources[jj] > -1 ) {
      if ( SUB->GetSource( asources[jj] )->GetParent() >= 0 ) {
	if (out) fprintf(out, "Bummer: trying to re-use asource at node index %d\n",jj);
	goto back;
      }
      SUB->MakeArSrcEquation( jj, asources[jj]);
      break;    // we assume there is only ONE BdnCondition
    }
  }

  r_code = 0; // only at this point we indicate everything is clean

  // calculate the chksum in case we are going to load something from the data
  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    mychk.add_string( NODE_NAMES->Get(jj) );
  }

  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    if ( qsources[jj] > -1 ) {
      Source *s = (Source*)SUB->GetSource( qsources[jj] );
      sprintf(chktmp, "%+.1e", s->Evaluate(0.0));
      mychk.add_string(chktmp);
    }
  }
  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    if ( asources[jj] > -1 ) {
      Source *s = (Source*)SUB->GetSource( asources[jj]);
      sprintf(chktmp, "%+.1e", s->Evaluate(0.0));
      mychk.add_string(chktmp);
    }
  }
  for (int jj=0; jj<STAT.N_Nodes(); jj++) {
    if ( lsources[jj] > -1 ) {
      Source *s = (Source*)SUB->GetSource( lsources[jj] );
      sprintf(chktmp, "%+.1e", s->Evaluate(0.0));
      mychk.add_string(chktmp);
    }
  }
  
  STAT.SetChkSum( mychk.HexCode() );

 back:
  if (Prime) delete Prime;
  if (Second) delete Second;

  return r_code;
}
Example #3
0
/* Analizzatore lessicale */
TokenTypeEnum GetNextToken(const char *str, Token *token, BOOL bIsInfix)
{
    int i;
    char strToken[MAXOP];

    while ( 1 )
    {
        while ( str[nNextPos++] == ' ' )
            ;
        --nNextPos;

        if ( str[nNextPos] == '\0' )
        {
            token->Type = EOL;
            strcpy(token->str, "\n");
            nNextPos = 0;
            PreviousTokenType = EOL;
            return EOL;
        }
        else if ( is_scientific(str[nNextPos]) )
        {
            i = 0;
            while ( is_scientific(strToken[i++] = str[nNextPos++]) )
                if (strToken[i-1] == 'd' || strToken[i-1] == 'D') strToken[i-1] = 'e';
            if ( str[nNextPos - 1] == '.' )
            {
                while ( is_scientific(strToken[i++] = str[nNextPos++]) )
                if (strToken[i-1] == 'd' || strToken[i-1] == 'D') strToken[i-1] = 'e';
                strToken[i - 1] = '\0';
                --nNextPos;
                token->Type = VALUE;
                strcpy(token->str, strToken);
                token->Value = atof(strToken);
                return VALUE;
            }
            else
            {
                strToken[i - 1] = '\0';
                --nNextPos;
                token->Type = VALUE;
                strcpy(token->str, strToken);
                token->Value = atof(strToken);
                return VALUE;
            }
        }
        else if ( str[nNextPos] == '.' )
        {
            i = 0;
            strToken[i++] = str[nNextPos++];
            while ( is_scientific(strToken[i++] = str[nNextPos++]) )
                if (strToken[i-1] == 'd' || strToken[i-1] == 'D') strToken[i-1] = 'e';
            strToken[i - 1] = '\0';
            --nNextPos;
            token->Type = VALUE;
            strcpy(token->str, strToken);
            token->Value = atof(strToken);
            return VALUE;
        }
        else if ( str[nNextPos] == '(' )
        {
            token->Type = OPAREN;
            strcpy(token->str, "(");
            ++nNextPos;
            return OPAREN;
        }
        else if ( str[nNextPos] == ')' )
        {
            token->Type = CPAREN;
            strcpy(token->str, ")");
            ++nNextPos;
            return CPAREN;
        }
        else if ( str[nNextPos] == '+' )
        {
            strcpy(token->str, "+");
            ++nNextPos;
            if ( !bIsInfix )
            {
                token->Type = PLUS;
                return PLUS;
            }
            else
            {
                if ( PreviousTokenType == CPAREN || PreviousTokenType == VALUE )
                {
                    token->Type = PLUS;
                    return PLUS;
                }
                else
                {
                    token->Type = UPLUS;
                    return UPLUS;
                }
            }
        }
        else if ( str[nNextPos] == '-' )
        {
            strcpy(token->str, "-");
            ++nNextPos;
            if ( !bIsInfix )
            {
                token->Type = MINUS;
                return MINUS;
            }
            else
            {
                if ( PreviousTokenType == CPAREN || PreviousTokenType == VALUE )
                {
                    token->Type = MINUS;
                    return MINUS;
                }
                else
                {
                    token->Type = UMINUS;
                    return UMINUS;
                }
            }
        }
        else if ( str[nNextPos] == '~' )
        {
            strcpy(token->str, "~");
            ++nNextPos;
            if ( !bIsInfix )
            {
                token->Type = UMINUS;
                return UMINUS;
            }
            else
            {
                token->Type = UNKNOWN;
                return UNKNOWN;
            }
        }
        else if ( str[nNextPos] == '*' )
        {
            token->Type = MULT;
            strcpy(token->str, "*");
            ++nNextPos;
            return MULT;
        }
        else if ( str[nNextPos] == '/' )
        {
            token->Type = DIV;
            strcpy(token->str, "/");
            ++nNextPos;
            return DIV;
        }
        else if ( str[nNextPos] == '^' )
        {
            token->Type = EXP;
            strcpy(token->str, "^");
            ++nNextPos;
            return EXP;
        }
        else
        {
            token->Type = UNKNOWN;
            token->str[0] = str[nNextPos];
            token->str[1] = '\0';
            ++nNextPos;
            return UNKNOWN;
        }
    }

    return EOL;
}