/*
 * 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;
}
Example #10
0
/*
 * 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;
  }
}
Example #13
0
/*
 * 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);
}
Example #15
0
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);
  }

}
Example #19
0
/*
 * 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;
}
Example #20
0
/*
  * 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;
  }
}
Example #21
0
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);
  }
}