#include "lengthgroup.h" #include "errorhandler.h" #include "gadget.h" #include "global.h" #include "mathfunc.h" //Constructor for length division with even increments LengthGroupDivision::LengthGroupDivision(double MinL, double MaxL, double DL) : error(0), Dl(DL) { if ((MaxL < MinL) || (MinL < 0.0) || (Dl < verysmall)) { error = 1; return; } int i; minlen = MinL; maxlen = MaxL; double tmp = (maxlen - minlen) / Dl; size = int(tmp + rathersmall); if (size == 0) { error = 1; return; } meanlength.resize(size, 0.0); minlength.resize(size, 0.0); for (i = 0; i < size; i++) { minlength[i] = minlen + (Dl * i); meanlength[i] = minlength[i] + (Dl * 0.5); } } //Constructor for length division with uneven increments LengthGroupDivision::LengthGroupDivision(const DoubleVector& Breaks) : error(0), Dl(0.0) { if ((Breaks.Size() < 2) || (Breaks[0] < 0.0)) { error = 1; return; } int i; size = Breaks.Size() - 1; minlen = Breaks[0]; maxlen = Breaks[size]; Dl = Breaks[1] - Breaks[0]; meanlength.resize(size, 0.0); minlength.resize(size, 0.0); for (i = 0; i < size; i++) { //JMB first some error checks ... if ((Breaks[i] > Breaks[i + 1]) || (isEqual(Breaks[i], Breaks[i + 1]))) { error = 1; return; } //... and check to see if the step lengths are actually equal if (!isZero(Dl) && !isSmall(Breaks[i + 1] - Breaks[i] - Dl)) Dl = 0.0; } //finally store the mean and minimum lengths for the length division if (isZero(Dl)) { for (i = 0; i < size; i++) { minlength[i] = Breaks[i]; meanlength[i] = 0.5 * (Breaks[i] + Breaks[i + 1]); } } else { for (i = 0; i < size; i++) { minlength[i] = minlen + (Dl * i); meanlength[i] = minlength[i] + (Dl * 0.5); } } } LengthGroupDivision::LengthGroupDivision(const LengthGroupDivision& l) : error(l.error), size(l.size), Dl(l.Dl), minlen(l.minlen), maxlen(l.maxlen), meanlength(l.meanlength), minlength(l.minlength) { } int LengthGroupDivision::numLengthGroup(double len) const { //check if len equals the minimum length if (isSmall(minlen - len)) return 0; //check if len equals the maximum length if (isSmall(maxlen - len)) return size - 1; int i; for (i = 0; i < size; i++) if ((isSmall(minlength[i] - len)) || ((minlength[i] < len) && (len < this->maxLength(i)))) return i; //failed to find length group that matches len return -1; } double LengthGroupDivision::minLength(int i) const { if (i >= size) return minlength[size - 1]; return minlength[i]; } double LengthGroupDivision::maxLength(int i) const { if (i >= (size - 1)) return maxlen; return minlength[i + 1]; } int LengthGroupDivision::Combine(const LengthGroupDivision* const addition) { if ((minlen > addition->minLength(addition->numLengthGroups() - 1)) || (this->minLength(size - 1) < addition->minLength())) return 0; int i, j; i = j = 0; if (((minlen < addition->minLength()) || (isEqual(minlen, addition->minLength()))) && ((this->minLength(size - 1) > addition->minLength(addition->numLengthGroups() - 1)) || (isEqual(this->minLength(size - 1), addition->minLength(addition->numLengthGroups() - 1))))) { //only check if the divisions are the same in the overlapping region. while (this->minLength(i) < addition->minLength()) i++; for (j = 0; j < addition->numLengthGroups(); j++) { if (!(isEqual(this->minLength(i + j), addition->minLength(j)))) { error = 1; return 0; } } return 1; } double tempmin = min(minlen, addition->minLength()); double tempmax = max(maxlen, addition->maxLength()); DoubleVector lower, middle; if ((minlen > addition->minLength()) || (isEqual(minlen, addition->minLength()))) { for (; minlen > addition->minLength(i); i++) { lower.resize(1, addition->minLength(i)); middle.resize(1, addition->meanLength(i)); } for (; j - i < size && j < addition->numLengthGroups(); j++) { if (!(isEqual(this->minLength(j - i), addition->minLength(j)))) { error = 1; return 0; } lower.resize(1, this->minLength(j - i)); middle.resize(1, this->meanLength(j - i)); } if (j - i >= size) { for (; j < addition->numLengthGroups(); j++) { lower.resize(1, addition->minLength(j)); middle.resize(1, addition->meanLength(j)); } } else { for (; j - i < size; j++) { lower.resize(1, this->minLength(j - i)); middle.resize(1, this->meanLength(j - i)); } } } else { for (; this->minLength(i) < addition->minLength(); i++) { lower.resize(1, this->minLength(i)); middle.resize(1, this->meanLength(i)); } for (j = 0; j < addition->numLengthGroups(); j++) { lower.resize(1, addition->minLength(j)); middle.resize(1, addition->meanLength(j)); } } //set this to the new division if (!(isEqual(Dl, addition->dl()))) Dl = 0.0; for (i = 0; i < size; i++) { minlength[i] = lower[i]; meanlength[i] = middle[i]; } size = lower.Size(); for (; i < size; i++) { minlength.resize(1, lower[i]); meanlength.resize(1, middle[i]); } minlen = tempmin; maxlen = tempmax; return 1; } void LengthGroupDivision::Print(ofstream& outfile) const { int i; outfile << "Length group division with " << size << " length groups from " << minlen << " up to " << maxlen << endl << TAB; for (i = 0; i < size; i++) outfile << minlength[i] << sep; outfile << maxlen << endl; } void LengthGroupDivision::printError() const { handle.logMessage(LOGWARN, "Minimum length of length group division is", this->minLength()); handle.logMessage(LOGWARN, "Maximum length of length group division is", this->maxLength()); } int checkLengthGroupStructure(const LengthGroupDivision* finer, const LengthGroupDivision* coarser) { int c, f; double minlength, maxlength; //check to see if the intersection is empty minlength = max(coarser->minLength(), finer->minLength()); maxlength = min(coarser->maxLength(), finer->maxLength()); if ((minlength > maxlength) || isSmall(maxlength - minlength)) { handle.logMessage(LOGWARN, "Error when checking length structure - empty intersection"); finer->printError(); coarser->printError(); return 0; } //if the length groups have the same dl then no need to check any further if (isSmall(finer->dl() - coarser->dl())) return 1; //now we need to check the length grouping for the intersection for (f = finer->numLengthGroup(minlength); f < finer->numLengthGroup(maxlength); f++) { c = coarser->numLengthGroup(finer->minLength(f)); if (c == -1) { handle.logMessage(LOGWARN, "Error when checking length structure for the following lengthgroups"); finer->printError(); coarser->printError(); return 0; } if ((coarser->minLength(c) > (finer->minLength(f) + rathersmall)) || (finer->maxLength(f) > (coarser->maxLength(c) + rathersmall))) { handle.logMessage(LOGWARN, "Error when checking length structure for length group", f); finer->printError(); coarser->printError(); return 0; } } return 1; } double* const LengthGroupDivision::meanlengthvecPow_initilize( int maxlengthgroupgrowth, double tmpPower) const { double * meanlength_vectorPow = new double[size + maxlengthgroupgrowth]; double aux; int lgroup; for (lgroup = 0; lgroup < size; lgroup++) meanlength_vectorPow[lgroup] = pow(meanLength(lgroup), tmpPower); aux = meanlength_vectorPow[size-1]; for (lgroup = size; lgroup < size+maxlengthgroupgrowth; lgroup++) meanlength_vectorPow[lgroup] = aux; return meanlength_vectorPow; }