/* * Converts a Watt Unit into the corresponding UnitDefinition * consisting only of SI units. * If the given unit does not have the correct kind, a NULL pointer is * returned. * It is up to the receiver to free the memory of the returned * UnitDefinition. * @param const Unit& unit * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::convertWattToSI(const Unit& unit) { UnitKind_t uKind = unit.getKind(); if (uKind != UNIT_KIND_WATT) return NULL; UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); Unit* pU = new Unit(unit); pU->setOffset(0.0); pU->setKind(UNIT_KIND_KILOGRAM); pU->setExponent(unit.getExponent()); pUdef->addUnit(pU); delete pU; pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); pU->setKind(UNIT_KIND_METER); pU->setExponent(2*unit.getExponent()); pUdef->addUnit(pU); delete pU; pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); pU->setKind(UNIT_KIND_SECOND); pU->setExponent(-3*unit.getExponent()); pUdef->addUnit(pU); delete pU; return pUdef; }
END_TEST START_TEST(test_unitdefinition_areIdentical2) { UnitDefinition* ud = new UnitDefinition(2, 2); UnitDefinition* ud1 = new UnitDefinition(2, 2); Unit* u = new Unit(2, 2); u->setKind(UNIT_KIND_JOULE); Unit* u1 = new Unit(2, 2); u1->setKind(UNIT_KIND_NEWTON); ud->addUnit(u); ud->addUnit(u1); ud1->addUnit(u); ud1->addUnit(u1); int identical = UnitDefinition::areIdentical(ud, ud1); fail_unless(identical == 1); delete u; delete u1; delete ud; delete ud1; }
END_TEST START_TEST(test_unitdefinition_convert_SI) { UnitDefinition* ud = new UnitDefinition(2, 4); UnitDefinition* ud1 = new UnitDefinition(2, 4); Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_JOULE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_NEWTON); u1->setExponent(-1); ud->addUnit(u); ud->addUnit(u1); ud1 = UnitDefinition::convertToSI(ud); fail_unless(ud1->getNumUnits() == 1); fail_unless(ud1->getUnit(0)->getKind() == UNIT_KIND_METRE); /* NULL case*/ ud = NULL; ud1 = UnitDefinition::convertToSI(ud); fail_unless(ud1 == NULL); delete u; delete u1; delete ud; delete ud1; }
END_TEST START_TEST(test_unitdefinition_areEquivalent) { UnitDefinition* ud = new UnitDefinition(2, 4); UnitDefinition* ud1 = new UnitDefinition(2, 4); Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_JOULE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_NEWTON); Unit* u2 = new Unit(2, 4); u->setKind(UNIT_KIND_METRE); u1->setExponent(-1); ud->addUnit(u); ud->addUnit(u1); ud1->addUnit(u2); int equivalent = UnitDefinition::areEquivalent(ud, ud1); //fail_unless(equivalent == 1); ud->addUnit(u2); equivalent = UnitDefinition::areEquivalent(ud, ud1); fail_unless(equivalent == 0); /* NULL case*/ ud = NULL; equivalent = UnitDefinition::areEquivalent(ud, ud1); fail_unless(equivalent == 0); equivalent = UnitDefinition::areEquivalent(ud1, ud); fail_unless(equivalent == 0); ud1 = NULL; equivalent = UnitDefinition::areEquivalent(ud, ud1); fail_unless(equivalent == 1); delete u; delete u1; delete u2; delete ud; delete ud1; }
END_TEST START_TEST(test_unitdefinition_areIdentical) { UnitDefinition* ud = new UnitDefinition(2, 4); UnitDefinition* ud1 = new UnitDefinition(2, 4); Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_JOULE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_NEWTON); Unit* u2 = new Unit(2, 4); u2->setKind(UNIT_KIND_METRE); ud->addUnit(u); ud->addUnit(u1); ud1->addUnit(u); ud1->addUnit(u1); int identical = UnitDefinition::areIdentical(ud, ud1); fail_unless(identical == 1); ud->addUnit(u2); identical = UnitDefinition::areIdentical(ud, ud1); fail_unless(identical == 0); /* NULL case*/ ud = NULL; identical = UnitDefinition::areIdentical(ud, ud1);; fail_unless(identical == 0); identical = UnitDefinition::areIdentical(ud1, ud);; fail_unless(identical == 0); ud1 = NULL; identical = UnitDefinition::areIdentical(ud, ud1);; fail_unless(identical == 1); delete u; delete u1; delete u2; delete ud; delete ud1; }
END_TEST START_TEST(test_unitdefinition_divide1) { UnitDefinition* ud = new UnitDefinition(2, 1); UnitDefinition* ud1 = new UnitDefinition(2, 2); UnitDefinition* udTemp; Unit* u = new Unit(2, 1); u->setKind(UNIT_KIND_METRE); Unit* u1 = new Unit(2, 2); u1->setKind(UNIT_KIND_MOLE); ud->addUnit(u); ud1->addUnit(u1); udTemp = UnitDefinition::divide(ud, ud1); fail_unless(udTemp == 0); delete u; delete ud1; delete u1; delete ud; }
/** * Checks that the units of the arguments * of the function are dimensionless * and that there is only one argument * * If inconsistent units are found, an error message is logged. */ void ArgumentsUnitsCheckWarnings::checkDimensionlessArgs (const Model& m, const ASTNode& node, const SBase & sb, bool inKL, int reactNo) { /* check that node has children */ if (node.getNumChildren() == 0) { return; } UnitDefinition *dim = new UnitDefinition(m.getSBMLNamespaces()); Unit *unit = new Unit(m.getSBMLNamespaces()); unit->setKind(UNIT_KIND_DIMENSIONLESS); unit->initDefaults(); UnitDefinition * tempUD; dim->addUnit(unit); UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m); tempUD = unitFormat->getUnitDefinition(node.getChild(0), inKL, reactNo); if (tempUD->getNumUnits() != 0 && !UnitDefinition::areEquivalent(dim, tempUD)) { logInconsistentDimensionless(node, sb); } delete tempUD; delete dim; delete unit; delete unitFormat; }
/* * Converts a Coulomb Unit into the corresponding UnitDefinition * consisting only of SI units. * If the given unit does not have the correct kind, a NULL pointer is * returned. * It is up to the receiver to free the memory of the returned * UnitDefinition. * @param const Unit& unit * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::convertCoulombToSI(const Unit& unit) { UnitKind_t uKind = unit.getKind(); if (uKind != UNIT_KIND_COULOMB) return NULL; UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); Unit* pU = new Unit(unit); pU->setKind(UNIT_KIND_AMPERE); pU->setOffset(0.0); pUdef->addUnit(pU); delete pU; pU = new Unit(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); pU->setKind(UNIT_KIND_SECOND); pU->setExponent(unit.getExponent()); pUdef->addUnit(pU); delete pU; return pUdef; }
/* * Eliminate all dimensionless units from the given UnitDefinition. * A new UnitDefinition without the dimensionless units is returned. * The scale and multiplier are preserved. If the UnitDefinition has only * one unit the is a dimensionless, it is not deleted. * @param UnitDefinition* pUdef * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::eliminateDimensionless(UnitDefinition* pUdef) { unsigned int maxUnits = pUdef->getNumUnits(); UnitDefinition* pTmpUdef = NULL; Unit* pU = NULL; if (maxUnits > 1) { int scale = 0; double multiplier = 1.0; unsigned int i = 0; pTmpUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); while (i < maxUnits) { pU = new Unit(*(pUdef->getUnit(i))); if (pU->getKind() != UNIT_KIND_DIMENSIONLESS) { pTmpUdef->addUnit(pU); } else { // conserve scale and multiplier scale = scale + pU->getScale(); multiplier = multiplier * pU->getMultiplier(); } delete pU; ++i; } i = pTmpUdef->getNumUnits(); if (i > 0 && i < maxUnits) { pTmpUdef->setName(pUdef->getName()); pTmpUdef->setId(pUdef->getId()); pU = pTmpUdef->getUnit(0); pU->setScale(pU->getScale() + scale); pU->setMultiplier(pU->getMultiplier()*multiplier); } else { delete pTmpUdef; pTmpUdef = NULL; } } return pTmpUdef; }
/* * Converts a Mole Unit into the corresponding UnitDefinition * consisting only of SI units. * If the given unit does not have the correct kind, a NULL pointer is * returned. * It is up to the receiver to free the memory of the returned * UnitDefinition. * @param const Unit& unit * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::convertMoleToSI(const Unit& unit) { UnitKind_t uKind = unit.getKind(); if (uKind != UNIT_KIND_MOLE) return NULL; UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); Unit* pU = new Unit(unit); pU->setOffset(0.0); pUdef->addUnit(pU); delete pU; return pUdef; }
END_TEST START_TEST(test_unitdefinition_order) { UnitDefinition* ud = new UnitDefinition(2, 4); Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_METRE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_AMPERE); Unit* u2 = new Unit(2, 4); u2->setKind(UNIT_KIND_HERTZ); ud->addUnit(u); ud->addUnit(u1); ud->addUnit(u2); UnitDefinition::reorder(ud); fail_unless(ud->getNumUnits() == 3); fail_unless(ud->getUnit(0)->getKind() == UNIT_KIND_AMPERE); fail_unless(ud->getUnit(1)->getKind() == UNIT_KIND_HERTZ); fail_unless(ud->getUnit(2)->getKind() == UNIT_KIND_METRE); /* NULL case*/ ud = NULL; UnitDefinition::reorder(ud); fail_unless(ud == NULL); delete u; delete u1; delete u2; delete ud; }
/* * Constructs and returns a UnitDefinition that expresses the units of this * LocalParameter. */ UnitDefinition * LocalParameter::getDerivedUnitDefinition() { /* if we have the whole model but it is not in a document * it is still possible to determine the units */ Model * m = static_cast <Model *> (getAncestorOfType(SBML_MODEL)); if (m != NULL) { if (!m->isPopulatedListFormulaUnitsData()) { m->populateListFormulaUnitsData(); } UnitDefinition *ud = NULL; const char * units = getUnits().c_str(); if (!strcmp(units, "")) { ud = new UnitDefinition(getSBMLNamespaces()); return ud; } else { if (UnitKind_isValidUnitKindString(units, getLevel(), getVersion())) { Unit * unit = new Unit(getSBMLNamespaces()); unit->setKind(UnitKind_forName(units)); unit->initDefaults(); ud = new UnitDefinition(getSBMLNamespaces()); ud->addUnit(unit); delete unit; } else { /* must be a unit definition */ ud = static_cast <Model *> (getAncestorOfType(SBML_MODEL))->getUnitDefinition(units); } return ud; } } else { return NULL; } }
/* * Converts a "Dimensionless" Unit into the corresponding UnitDefinition * consisting only of SI units. This would include e.g. the Radian unit. * If the given unit does not have the correct kind, a NULL pointer is * returned. * It is up to the receiver to free the memory of the returned * UnitDefinition. * @param const Unit& unit * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::convertDimensionlessToSI(const Unit& unit) { UnitKind_t uKind = unit.getKind(); if (uKind != UNIT_KIND_DIMENSIONLESS && uKind != UNIT_KIND_ITEM && uKind != UNIT_KIND_RADIAN && uKind != UNIT_KIND_STERADIAN) return NULL; UnitDefinition* pUdef = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); Unit* pU = new Unit(unit); pU->setKind(UNIT_KIND_DIMENSIONLESS); pU->setOffset(0.0); pUdef->addUnit(pU); delete pU; return pUdef; }
/* * Checks that the units of the delay function are consistent * * If inconsistent units are found, an error message is logged. */ void ArgumentsUnitsCheck::checkUnitsFromDelay (const Model& m, const ASTNode& node, const SBase & sb, bool inKL, int reactNo) { /* check that node has two children */ if (node.getNumChildren() != 2) { return; } if (!m.getSBMLNamespaces()->getNamespaces()) { #if 0 cout << "[DEBUG] XMLNS IS NULL" << endl; #endif } /* delay(x, t) * no restrictions on units of x * but t must have units of time */ UnitDefinition *time = new UnitDefinition(m.getSBMLNamespaces()); Unit *unit = new Unit(m.getSBMLNamespaces()); unit->setKind(UNIT_KIND_SECOND); unit->initDefaults(); UnitDefinition * tempUD; time->addUnit(unit); UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m); tempUD = unitFormat->getUnitDefinition(node.getRightChild(), inKL, reactNo); if (!unitFormat->getContainsUndeclaredUnits()) { if (!UnitDefinition::areEquivalent(time, tempUD)) { logInconsistentDelay(node, sb); } } delete time; delete tempUD; delete unit; delete unitFormat; checkUnits(m, *node.getLeftChild(), sb, inKL, reactNo); }
void Model::dealWithModelUnits() { UnitRefsFilter filter; List * elements = getAllElements(&filter); unsigned int n = 0; unsigned int num = elements->getSize(); if (isSetVolumeUnits()) { std::string volume = getVolumeUnits(); // if in an L3 model a user used volume as an id of a UnitDefinition // but they declared the volume units of teh model to be something // else then the UD with id volume is nothing to do with the // L2 interpretation of volume // so replace that UD and all references to it if (volume != "volume") { UnitDefinition * existingUD = removeUnitDefinition("volume"); if (existingUD != NULL) { std::string newSubsName = "volumeFromOriginal"; existingUD->setId(newSubsName); SBase* obj; for (n = 0; n < num; n++) { obj = (SBase*)(elements->get(n)); obj->renameUnitSIdRefs("volume", newSubsName); } addUnitDefinition(existingUD); } } UnitDefinition * ud = getUnitDefinition(volume) != NULL ? getUnitDefinition(volume)->clone() : NULL; if (ud != NULL) { ud->setId("volume"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(volume.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("volume"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetAreaUnits()) { std::string area = getAreaUnits(); // if in an L3 model a user used area as an id of a UnitDefinition // but they declared the area units of teh model to be something // else then the UD with id area is nothing to do with the // L2 interpretation of area // so replace that UD and all references to it if (area != "area") { UnitDefinition * existingUD = removeUnitDefinition("area"); if (existingUD != NULL) { std::string newSubsName = "areaFromOriginal"; existingUD->setId(newSubsName); SBase* obj; for (n = 0; n < num; n++) { obj = (SBase*)(elements->get(n)); obj->renameUnitSIdRefs("area", newSubsName); } addUnitDefinition(existingUD); } } UnitDefinition * ud = getUnitDefinition(area) != NULL ? getUnitDefinition(area)->clone() : NULL; if (ud != NULL) { ud->setId("area"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(area.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("area"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetLengthUnits()) { std::string length = getLengthUnits(); // if in an L3 model a user used length as an id of a UnitDefinition // but they declared the length units of teh model to be something // else then the UD with id length is nothing to do with the // L2 interpretation of length // so replace that UD and all references to it if (length != "length") { UnitDefinition * existingUD = removeUnitDefinition("length"); if (existingUD != NULL) { std::string newSubsName = "lengthFromOriginal"; existingUD->setId(newSubsName); SBase* obj; for (n = 0; n < num; n++) { obj = (SBase*)(elements->get(n)); obj->renameUnitSIdRefs("length", newSubsName); } addUnitDefinition(existingUD); } } UnitDefinition * ud = getUnitDefinition(length) != NULL ? getUnitDefinition(length)->clone() : NULL; if (ud != NULL) { ud->setId("length"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(length.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("length"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetSubstanceUnits()) { std::string substance = getSubstanceUnits(); // if in an L3 model a user used substance as an id of a UnitDefinition // but they declared the substance units of teh model to be something // else then the UD with id substance is nothing to do with the // L2 interpretation of substance // so replace that UD and all references to it if (substance != "substance") { UnitDefinition * existingUD = removeUnitDefinition("substance"); if (existingUD != NULL) { std::string newSubsName = "substanceFromOriginal"; existingUD->setId(newSubsName); SBase* obj; for (n = 0; n < num; n++) { obj = (SBase*)(elements->get(n)); obj->renameUnitSIdRefs("substance", newSubsName); } addUnitDefinition(existingUD); } } UnitDefinition * ud = getUnitDefinition(substance) != NULL ? getUnitDefinition(substance)->clone() : NULL; if (ud != NULL) { ud->setId("substance"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(substance.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("substance"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetTimeUnits()) { std::string time = getTimeUnits(); // if in an L3 model a user used time as an id of a UnitDefinition // but they declared the time units of teh model to be something // else then the UD with id time is nothing to do with the // L2 interpretation of time // so replace that UD and all references to it if (time != "time") { UnitDefinition * existingUD = removeUnitDefinition("time"); if (existingUD != NULL) { std::string newSubsName = "timeFromOriginal"; existingUD->setId(newSubsName); SBase* obj; for (n = 0; n < num; n++) { obj = (SBase*)(elements->get(n)); obj->renameUnitSIdRefs("time", newSubsName); } addUnitDefinition(existingUD); } } UnitDefinition * ud = getUnitDefinition(time) != NULL ? getUnitDefinition(time)->clone() : NULL; if (ud != NULL) { ud->setId("time"); } else { ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("time"); Unit *u = ud->createUnit(); u->initDefaults(); u->setKind(UnitKind_forName(time.c_str())); } addUnitDefinition(ud); } }
LIBSBML_CPP_NAMESPACE_USE BEGIN_C_DECLS START_TEST(test_unitdefinition_simplify) { UnitDefinition* ud = new UnitDefinition(2, 4); Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_METRE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_DIMENSIONLESS); Unit* u2 = new Unit(2, 4); u2->setKind(UNIT_KIND_METRE); u2->setExponent(2); Unit* u3 = new Unit(2, 4); u3->setKind(UNIT_KIND_METRE); u3->setExponent(-3); /* case with only one unit */ ud->addUnit(u); UnitDefinition::simplify(ud); fail_unless(ud->getNumUnits() == 1); fail_unless(ud->getUnit(0)->getKind() == UNIT_KIND_METRE); /* case with one unit plus a dimensionless unit */ ud->addUnit(u1); UnitDefinition::simplify(ud); fail_unless(ud->getNumUnits() == 1); fail_unless(ud->getUnit(0)->getKind() == UNIT_KIND_METRE); /* case with two units of same kind */ ud->addUnit(u2); UnitDefinition::simplify(ud); fail_unless(ud->getNumUnits() == 1); fail_unless(ud->getUnit(0)->getKind() == UNIT_KIND_METRE); fail_unless(ud->getUnit(0)->getExponent() == 3); /* case with two units of same kind that cancel*/ ud->addUnit(u3); UnitDefinition::simplify(ud); fail_unless(ud->getNumUnits() == 1); fail_unless(ud->getUnit(0)->getKind() == UNIT_KIND_DIMENSIONLESS); /* NULL case*/ ud = NULL; UnitDefinition::simplify(ud); fail_unless(ud == NULL); delete u; delete u1; delete u2; delete u3; delete ud; }
END_TEST START_TEST(test_unitdefinition_divide) { UnitDefinition* ud = new UnitDefinition(2, 4); UnitDefinition* ud1 = new UnitDefinition(2, 4); UnitDefinition* udTemp; Unit* u = new Unit(2, 4); u->setKind(UNIT_KIND_METRE); Unit* u1 = new Unit(2, 4); u1->setKind(UNIT_KIND_MOLE); Unit* u2 = new Unit(2, 4); u2->setKind(UNIT_KIND_SECOND); u2->setExponent(2); ud->addUnit(u); ud1->addUnit(u1); udTemp = UnitDefinition::divide(ud, ud1); fail_unless(udTemp->getNumUnits() == 2); fail_unless(udTemp->getUnit(0)->getKind() == UNIT_KIND_METRE); fail_unless(udTemp->getUnit(1)->getKind() == UNIT_KIND_MOLE); fail_unless(udTemp->getUnit(1)->getExponent() == -1); /* case with two units of same kind */ ud1->addUnit(u2); udTemp = UnitDefinition::divide(udTemp, ud1); fail_unless(udTemp->getNumUnits() == 3); fail_unless(udTemp->getUnit(0)->getKind() == UNIT_KIND_METRE); fail_unless(udTemp->getUnit(1)->getKind() == UNIT_KIND_MOLE); fail_unless(udTemp->getUnit(1)->getExponent() == -2); fail_unless(udTemp->getUnit(2)->getKind() == UNIT_KIND_SECOND); fail_unless(udTemp->getUnit(2)->getExponent() == -2); /* NULL case*/ ud = NULL; udTemp = UnitDefinition::divide(ud, ud1); fail_unless(udTemp->getNumUnits() == 2); fail_unless(udTemp->getUnit(0)->getKind() == UNIT_KIND_MOLE); fail_unless(udTemp->getUnit(0)->getExponent() == -1); fail_unless(udTemp->getUnit(1)->getKind() == UNIT_KIND_SECOND); fail_unless(udTemp->getUnit(1)->getExponent() == -2); udTemp = UnitDefinition::divide(ud1, ud); fail_unless(udTemp->getNumUnits() == 2); fail_unless(udTemp->getUnit(0)->getKind() == UNIT_KIND_MOLE); fail_unless(udTemp->getUnit(1)->getKind() == UNIT_KIND_SECOND); fail_unless(udTemp->getUnit(1)->getExponent() == 2); ud1 = NULL; udTemp = UnitDefinition::divide(ud1, ud); fail_unless(udTemp == NULL); delete u; delete ud1; delete u1; delete u2; delete ud; }
/* * Checks that the units of the piecewise function are consistent * * If inconsistent units are found, an error message is logged. */ void ArgumentsUnitsCheck::checkUnitsFromPiecewise (const Model& m, const ASTNode& node, const SBase & sb, bool inKL, int reactNo) { /* check that node has children */ if (node.getNumChildren() == 0) { return; } /* piecewise(a0, a1, a2, a3, ...) * a0 and a2, a(n_even) must have same units * a1, a3, a(n_odd) must be dimensionless */ unsigned int n; UnitDefinition *dim = new UnitDefinition(m.getSBMLNamespaces()); Unit *unit = new Unit(m.getSBMLNamespaces()); unit->setKind(UNIT_KIND_DIMENSIONLESS); unit->initDefaults(); UnitDefinition * tempUD; UnitDefinition * tempUD1 = NULL; dim->addUnit(unit); UnitFormulaFormatter *unitFormat = new UnitFormulaFormatter(&m); tempUD = unitFormat->getUnitDefinition(node.getChild(0), inKL, reactNo); for(n = 2; n < node.getNumChildren(); n+=2) { tempUD1 = unitFormat->getUnitDefinition(node.getChild(n), inKL, reactNo); if (!unitFormat->getContainsUndeclaredUnits()) { if (!UnitDefinition::areEquivalent(tempUD, tempUD1)) { logInconsistentPiecewise(node, sb); } } delete tempUD1; } delete tempUD; for(n = 1; n < node.getNumChildren(); n+=2) { tempUD = unitFormat->getUnitDefinition(node.getChild(n), inKL, reactNo); if (!UnitDefinition::areEquivalent(tempUD, dim)) { logInconsistentPiecewiseCondition(node, sb); } delete tempUD; } delete dim; delete unit; delete unitFormat; for(n = 0; n < node.getNumChildren(); n++) { checkUnits(m, *node.getChild(n), sb, inKL, reactNo); } }
/* * Combines two UnitDefinitions by combining the equivalent units from * both UnitDefinitions. * A new UnitDefinition containing the combination is returned. * If two eqivalent units have a different offset, the function returns a * NULL pointer. * It is up to the receiver to free the memory of the returned UnitDefinition. * @param const UnitDefinition& uDef1 * @param const UnitDefinition& uDef2 * @return UnitDefinition* result */ LIBSBML_EXTERN UnitDefinition* UnitConversionFactory::combine(const UnitDefinition& uDef1, const UnitDefinition& uDef2) { // take all Units from the first UnitDefinition make copies and put them into the new UnitDefinition // go through all Units in the second UnitDefinition, if the same unit already exists in the new // UnitDefinition combine them, else add a copy of the Unit to the new UnitDefinition UnitDefinition* pResult = new UnitDefinition(UnitConversionFactory::SBML_LEVEL, UnitConversionFactory::SBML_VERSION); unsigned int maxUnits = uDef1.getNumUnits(); unsigned int i; for (i = 0; i < maxUnits; ++i) { const Unit* pSrcUnit = uDef1.getUnit(i); unsigned int maxUnits2 = pResult->getNumUnits(); unsigned int j; bool exists = false; for (j = 0; j < maxUnits2; ++j) { Unit* pResultUnit = pResult->getUnit(j); if (pResultUnit->getKind() == pSrcUnit->getKind()) { exists = true; // if the offsets are different, we can not combine the units if (pResultUnit->getOffset() != pSrcUnit->getOffset()) { delete pResult; return NULL; } pResultUnit->setMultiplier(pResultUnit->getMultiplier()*pSrcUnit->getMultiplier()*pow(10.0, pResultUnit->getScale() - pSrcUnit->getScale())); pResultUnit->setExponent(pResultUnit->getExponent() + pSrcUnit->getExponent()); // if the resulting scale is 0, the units have canceled each other out // and we set the kind to dimensionless so that it can be eliminated // later on if (pResultUnit->getExponent() == 0) { pResultUnit->setKind(UNIT_KIND_DIMENSIONLESS); } } } if (!exists) { Unit* tmpUnit = new Unit(*pSrcUnit); pResult->addUnit(tmpUnit); delete tmpUnit; } } maxUnits = uDef2.getNumUnits(); for (i = 0; i < maxUnits; ++i) { const Unit* pSrcUnit = uDef2.getUnit(i); unsigned int maxUnits2 = pResult->getNumUnits(); unsigned int j; bool exists = false; for (j = 0; j < maxUnits2; ++j) { Unit* pResultUnit = pResult->getUnit(j); if (pResultUnit->getKind() == pSrcUnit->getKind()) { exists = true; // if the offsets are different, we can not combine the units if (pResultUnit->getOffset() != pSrcUnit->getOffset()) { delete pResult; return NULL; } pResultUnit->setMultiplier(pResultUnit->getMultiplier()*pSrcUnit->getMultiplier()*pow(10.0, pResultUnit->getScale() - pSrcUnit->getScale())); pResultUnit->setExponent(pResultUnit->getExponent() + pSrcUnit->getExponent()); // if the resulting scale is 0, the units have canceled each other out // and we set the kind to dimensionless so that it can be eliminated // later on if (pResultUnit->getExponent() == 0) { pResultUnit->setKind(UNIT_KIND_DIMENSIONLESS); } } } if (!exists) { Unit* tmpUnit = new Unit(*pSrcUnit); pResult->addUnit(tmpUnit); delete tmpUnit; } } UnitDefinition* pTmp = UnitConversionFactory::eliminateDimensionless(pResult); if (pTmp) { delete pResult; pResult = pTmp; } return pResult; }
/* * Constructs and returns a UnitDefinition that expresses the units of this * Parameter. */ UnitDefinition * Parameter::getDerivedUnitDefinition() { /* if we have the whole model but it is not in a document * it is still possible to determine the units */ Model * m = static_cast <Model *> (getAncestorOfType(SBML_MODEL)); if (m != NULL) { if (!m->isPopulatedListFormulaUnitsData()) { m->populateListFormulaUnitsData(); } /* need to distinguish between a global and local parameter * for a global parameter a unit definition will have been created * for a local parameter need to create one based on the units field */ bool globalParameter = false; SBase *parent = getParentSBMLObject(); SBase *pparent = (parent) ? parent->getParentSBMLObject() : NULL; if (pparent != NULL && dynamic_cast<Model*>(pparent) != 0) globalParameter = true; if (globalParameter) { if (m->getFormulaUnitsData(getId(), getTypeCode()) != NULL) { return m->getFormulaUnitsData(getId(), getTypeCode()) ->getUnitDefinition(); } else { return NULL; } } else { UnitDefinition *ud = NULL; const char * units = getUnits().c_str(); if (!strcmp(units, "")) { ud = new UnitDefinition(getSBMLNamespaces()); return ud; } else { if (UnitKind_isValidUnitKindString(units, getLevel(), getVersion())) { Unit * unit = new Unit(getSBMLNamespaces()); unit->setKind(UnitKind_forName(units)); unit->initDefaults(); ud = new UnitDefinition(getSBMLNamespaces()); ud->addUnit(unit); delete unit; } else { /* must be a unit definition */ ud = static_cast <Model *> (getAncestorOfType(SBML_MODEL))->getUnitDefinition(units); } return ud; } } } else { return NULL; } }
void Model::dealWithModelUnits() { if (isSetVolumeUnits()) { std::string volume = getVolumeUnits(); UnitDefinition * ud = removeUnitDefinition(volume); if (ud != NULL) { ud->setId("volume"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(volume.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("volume"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetAreaUnits()) { std::string area = getAreaUnits(); UnitDefinition * ud = removeUnitDefinition(area); if (ud != NULL) { ud->setId("area"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(area.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("area"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetLengthUnits()) { std::string length = getLengthUnits(); UnitDefinition * ud = removeUnitDefinition(length); if (ud != NULL) { ud->setId("length"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(length.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("length"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetSubstanceUnits()) { std::string substance = getSubstanceUnits(); UnitDefinition * ud = removeUnitDefinition(substance); if (ud != NULL) { ud->setId("substance"); } else { Unit *u = new Unit(getSBMLNamespaces()); u->initDefaults(); u->setKind(UnitKind_forName(substance.c_str())); ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("substance"); ud->addUnit(u); } addUnitDefinition(ud); } if (isSetTimeUnits()) { std::string time = getTimeUnits(); UnitDefinition * ud = removeUnitDefinition(time); if (ud != NULL) { ud->setId("time"); } else { ud = new UnitDefinition(getSBMLNamespaces()); ud->setId("time"); Unit *u = ud->createUnit(); u->initDefaults(); u->setKind(UnitKind_forName(time.c_str())); } addUnitDefinition(ud); } }