cellml / libcellml

Repository for libCellML development.
https://libcellml.org
Apache License 2.0
16 stars 21 forks source link

Cyclic units exist #1166

Closed WeiweiAi closed 1 year ago

WeiweiAi commented 1 year ago

libcellml==0.4.0

I attach the Python script which shows the validator finds Cyclic units exist. After I flatten the model, the validation passed. I have checked the units definition but I could not find the cause of why the error occurred. Could you please help me with it? Thanks.

from libcellml import Component, Generator, GeneratorProfile, Model, Units,  Variable, ImportSource, Printer, Analyser,Importer, Validator
from pathlib import PurePath,Path
import os
BUILTIN_UNITS = {'ampere':Units.StandardUnit.AMPERE, 'becquerel':Units.StandardUnit.BECQUEREL, 'candela':Units.StandardUnit.CANDELA, 'coulomb':Units.StandardUnit.COULOMB, 'dimensionless':Units.StandardUnit.DIMENSIONLESS, 
                 'farad':Units.StandardUnit.FARAD, 'gram':Units.StandardUnit.GRAM, 'gray':Units.StandardUnit.GRAY, 'henry':Units.StandardUnit.HENRY, 'hertz':Units.StandardUnit.HERTZ, 'joule':Units.StandardUnit.JOULE,
                   'katal':Units.StandardUnit.KATAL, 'kelvin':Units.StandardUnit.KELVIN, 'kilogram':Units.StandardUnit.KILOGRAM, 'liter':Units.StandardUnit.LITRE, 'litre':Units.StandardUnit.LITRE, 
                   'lumen':Units.StandardUnit.LUMEN, 'lux':Units.StandardUnit.LUX, 'metre':Units.StandardUnit.METRE, 'meter':Units.StandardUnit.METRE, 'mole':Units.StandardUnit.MOLE, 'newton':Units.StandardUnit.NEWTON, 
                   'ohm':Units.StandardUnit.OHM, 'pascal':Units.StandardUnit.PASCAL, 'radian':Units.StandardUnit.RADIAN, 'second':Units.StandardUnit.SECOND, 'siemens':Units.StandardUnit.SIEMENS, 'sievert':Units.StandardUnit.SIEVERT, 
                   'steradian':Units.StandardUnit.STERADIAN, 'tesla':Units.StandardUnit.TESLA, 'volt':Units.StandardUnit.VOLT, 'watt':Units.StandardUnit.WATT, 'weber':Units.StandardUnit.WEBER}

# Write a model to cellml file, input: directory, model, output: cellml file
def writeCellML(full_path, model):   
    printer = Printer()
    serialised_model = printer.printModel(model)    
    write_file = open(full_path, "w")
    write_file.write(serialised_model)
    write_file.close()
def _dump_issues(source_method_name, logger):
    if logger.issueCount() > 0:
        print('The method "{}" found {} issues:'.format(source_method_name, logger.issueCount()))
        for i in range(0, logger.issueCount()):
            print('    - {}'.format(logger.issue(i).description()))
def analyse_model(model):
    analyser = Analyser()
    analyser.analyseModel(model)
    a = analyser.model()
    _dump_issues("analyse_model", analyser)
    return a
def validate_model(model):
    validator = Validator()
    validator.validateModel(model)
    _dump_issues("validate_model", validator)
    return validator.issueCount()
def resolve_imports(model, base_dir, strict_mode):
    importer = Importer(strict_mode)
    importer.resolveImports(model, base_dir)
    _dump_issues("resolve_imports", importer)
    if model.hasUnresolvedImports():
        print("unresolved imports?")
    else:
        print("no unresolved imports.")
    return importer

def writePythonCode(full_path, model,strict_mode=True):
    base_dir = PurePath(full_path).parent.as_posix()
    importer = resolve_imports(model, base_dir, strict_mode)
    flatModel = importer.flattenModel(model)
    a = analyse_model(flatModel)              
    generator = Generator()
    generator.setModel(a)
    profile = GeneratorProfile(GeneratorProfile.Profile.PYTHON)
    generator.setProfile(profile)
    implementation_code_python = generator.implementationCode()                   
    # Save the python file in the same directory as the CellML file
    with open(full_path, "w") as f:
        f.write(implementation_code_python)

def defineUnits(iunitsName,unitName, prefix, exponent, multiplier):
    iunits = Units(iunitsName) 
    if exponent != '':
        exponent = float(exponent)
    else:
        exponent = 1.0
    if multiplier != '':
        multiplier = float(multiplier)
    else:
        multiplier = 1.0   
    if prefix == '':
        prefix = 1   
    if unitName in BUILTIN_UNITS:
        iunits.addUnit(BUILTIN_UNITS[unitName], prefix, exponent, multiplier)
    else:
        iunits.addUnit(unitName,prefix, exponent, multiplier)                
    return iunits
# Define the units and write to cellml file
units_model = Model('units_def')
iunits = defineUnits('per_sec', 'second', '', '-1', '')
units_model.addUnits(iunits)
iunits = defineUnits('fmol', 'mole', 'femto', '', '')
units_model.addUnits(iunits)
iunits = defineUnits('per_fmol', 'fmol', '', '-1', '')
units_model.addUnits(iunits)
u=Units('per_sec_fmol')
u.addUnit('per_sec', '1')
u.addUnit('per_fmol', '1')
units_model.addUnits(u)
full_path = units_model.name()+'.cellml'
writeCellML('units_def.cellml', units_model)
# Define the model to use the units and write to cellml file
model= Model('model_cyclicUnits')
c=Component(model.name())
model.addComponent(c)
var1=Variable('var1')
var1.setUnits('fmol')
c.addVariable(var1)

model_path=Path.cwd().as_posix()
units_to_import=['fmol']

relative_path_os = os.path.relpath(full_path, model_path)
relative_path=PurePath(relative_path_os).as_posix()
importSource = ImportSource()
importSource.setUrl(relative_path)
importSource.setModel(units_model)

for unit in units_to_import:
    u = Units(unit) 
    u.setImportSource(importSource)
    u.setImportReference(unit)
    model.addUnits(u)    

importer = resolve_imports(model, model_path, True)
print("Validating the model")
validate_model(model)
flatModel = importer.flattenModel(model)
print("Validating the flat model")
validate_model(flatModel)
model_full_path = model.name()+'.cellml'
writeCellML(model_full_path, model)
hsorby commented 1 year ago

What output do you get when you run this script?

hsorby commented 1 year ago

When I run it with the latest development codebase I get the following output:

no unresolved imports.
Validating the model
Validating the flat model
WeiweiAi commented 1 year ago

I got the following output:

no unresolved imports.
Validating the model
The method "validate_model" found 1 issues:
    - Cyclic units exist: 'fmol' -> 'fmol'.
Validating the flat model
hsorby commented 1 year ago

I think we have demonstrated that this issue will be resolved with the next release.

WeiweiAi commented 1 year ago

When I run the Python code using the new built bindings, I got the following error:

PS C:\Users\wai484\Documents\BG2CellML\test> python CyclicUnits_test1.py no unresolved imports. Validating the model Validating the flat model swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Model > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Units > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Units > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Model > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Component > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Variable > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::ImportSource > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Importer > ', no destructor found. swig/python detected a memory leak of type 'std::shared_ptr< libcellml::Model > *', no destructor found.

Not sure if this happens because something is wrong with the building process or relevant to the libcellml functions.

Best regards, Weiwei

On Wed, 10 May 2023 at 16:38, Hugh Sorby @.***> wrote:

I think we have demonstrated that this issue will be resolved with the next release.

— Reply to this email directly, view it on GitHub https://github.com/cellml/libcellml/issues/1166#issuecomment-1541340771, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADRVM44CGCLHCO6NIFAWYQDXFMLSXANCNFSM6AAAAAAX4EBX2E . You are receiving this because you authored the thread.Message ID: @.***>

hsorby commented 1 year ago

This is a separate issue and it has been reported here: https://github.com/cellml/libcellml/issues/1129 Still a work in progress at this point.