First time here? Checkout the FAQ!
x
0 votes
ago by (140 points)
edited ago by

Hello!

I'm trying to run a simulation using openCARP with a spherical mesh. However, when I execute the run.py script, I encounter the following error:

*** Unrecognized keyword elems

*** Error reading parameters

Here is the relevant part of my code:
 

def run(args, job):

    # Mesh configuration

    meshname = "sphere"  # Mesh name

    nodes = "sphere.pts"  # Nodes file

    elems = "sphere.elem"  # Elements file

    # Read mesh element tags

    _, etags, _ = txt.read(elems)

    etags = np.unique(etags)

    IntraTags = etags[etags != 0].tolist()

    ExtraTags = etags.tolist().copy()

    # Configure periodic stimuli

    num_stim = int((args.duration - 20) / 500) + 1  

    stim = ['-num_stim', num_stim]

    for i in range(num_stim):

        stim += [

            f'-stimulus[{i}].name', 'S1',

            f'-stimulus[{i}].stimtype', 0,

            f'-stimulus[{i}].strength', args.S1_strength,

            f'-stimulus[{i}].duration', args.S1_dur,

            f'-stimulus[{i}].start', 20 + i * 500  

        ]

    # Apply stimulus to the spherical surface

    stim += [

        '-stimulus[0].topo', 'sphere_surface',  # Sphere surface

        '-stimulus[0].type', 0,  # Stimulus type (current)

        '-stimulus[0].inside', 1  # Internal or external

    ]

    

    # Generate the CARP command

    cmd = tools.carp_cmd(os.path.join(os.path.dirname(__file__), 'monodomain.par'))

    cmd += ['-simID', job.ID,

            '-meshname', meshname,

            '-nodes', nodes,

            '-elems', elems,  # This is the parameter causing the error

            '-dt', 5,

            '-tend', args.duration]

    cmd += tools.gen_physics_opts(ExtraTags=ExtraTags, IntraTags=IntraTags)

    cmd += stim

    # Visualization option

    if args.visualize:

        cmd += ['-gridout_i', 3, '-gridout_e', 3, '-spacedt', 0.1]

    # Run the simulation

    job.carp(cmd)

    # Visualize results

    if args.visualize and not settings.platform.BATCH:

        geom = os.path.join(job.ID, os.path.basename(meshname) + '_i')

        data = os.path.join(job.ID, 'vm.igb.gz')

        view = os.path.join(os.path.dirname(__file__), 'view_vm.mshz')

        job.meshalyzer(geom, data, view)

I have verified the following:

  • The sphere.elem file is present and contains the expected element data in the correct format.
  • The paths to the sphere.pts and sphere.elem files are correct and accessible.
  • The monodomain.par file is properly configured with no obvious errors.

Has anyone encountered this issue before or knows what might be causing this error?

Thanks in advance for your help!

1 Answer

0 votes
ago by (260 points)
Hey,

you get this error, since there is no such parameter as -elems in openCARP. The same goes for the parameter -nodes.

In openCARP it is sufficient to supply the parameter -meshname with the base name of your mesh files. In your case -meshname sphere. Then, the files sphere.pts, sphere.elem and sphere.lon should be present in the path of you simulation. I don't spot any other obvious errors right now, so the simulation should start if you make those adaptations to your script.

Best,

Tobias
ago by (140 points)

Hello Tobias,

I made some modifications to my code, but I'm still encountering an issue when trying to run the simulation using my spherical mesh. Below is the updated code, and the error I get is:

*** Unrecognized keyword -boundary[0].name

*** Error reading parameters
 

Modified code:
#!/usr/bin/env python
import os
from datetime import date
from carputils import settings
from carputils import tools
from carputils.carpio import txt
import numpy as np
def parser():
    parser = tools.standard_parser()
    group = parser.add_argument_group('experiment specific options')
    group.add_argument('--duration',
                       type=float,
                       default=1000.,  
                       help='Duration of simulation in [ms] (default: 1000.)')
    group.add_argument('--S1-strength',
                       type=float,
                       default=400.,  
                       help='Stimulus strength in [uA/cm^2] (default: 400.)')
    group.add_argument('--S1-dur',
                       type=float,
                       default=2.,  
                       help='Stimulus duration in [ms] (default: 2.)')
    return parser
def jobID(args):
    today = date.today()
    return '{}_monodomain_{}'.format(today.isoformat(), args.duration)
def sphere_boundary_condition(nodes, center, radius, label):
    """
    Generates a boundary condition for a spherical surface.
    
    Args:
        nodes: np.array with the coordinates of the mesh nodes.
        center: Center of the sphere [x, y, z].
        radius: Radius of the sphere.
        label: Label for the boundary condition.
    
    Returns:
        List of commands to define the boundary condition.
    """
    boundary_nodes = []
    for i, node in enumerate(nodes):
        dist = np.linalg.norm(node - np.array(center))
        if np.isclose(dist, radius, atol=1e-3):  # Tolerance to find the surface
            boundary_nodes.append(i)
    
    condition = []
    for i, node_id in enumerate(boundary_nodes):
        condition += [
            f'-boundary[{i}].name', label,
            f'-boundary[{i}].type', 1,  # Type 1: Stimulus
            f'-boundary[{i}].nodes', node_id
        ]
    return condition
@tools.carpexample(parser, jobID)
def run(args, job):
    # Mesh setup
    meshname = "sphere"  # Mesh name
    nodes = np.loadtxt(meshname + ".pts", skiprows=1)  # Read mesh nodes ignoring the first row
    _, etags, _ = txt.read(meshname + '.elem')
    etags = np.unique(etags)
    IntraTags = etags[etags != 0].tolist()
    ExtraTags = etags.tolist().copy()
    # Sphere parameters
    center = [0, 0, 0]  # Center of the sphere
    radius = 1.0        # Radius of the sphere
    # Generate the boundary condition for the spherical surface
    electrode = sphere_boundary_condition(nodes, center, radius, 'stimulus')
    # Calculate number of stimuli
    num_stim = int((args.duration - 20) / 500) + 1  # Includes the initial stimulus at 20 ms
    # Create stimulus configuration
    stim = ['-num_stim', num_stim]
    for i in range(num_stim):
        stim += [
            f'-stimulus[{i}].name', 'S1',
            f'-stimulus[{i}].stimtype', 0,
            f'-stimulus[{i}].strength', args.S1_strength,
            f'-stimulus[{i}].duration', args.S1_dur,
            f'-stimulus[{i}].start', 20 + i * 500  # Stimulus every 500 ms starting from 20 ms
        ]
    # Generate CARP command
    cmd = tools.carp_cmd(os.path.join(os.path.dirname(__file__), 'monodomain.par'))
    cmd += ['-simID', job.ID,
            '-meshname', meshname,
            '-dt', 5,
            '-tend', args.duration]
    cmd += tools.gen_physics_opts(ExtraTags=ExtraTags, IntraTags=IntraTags)
    cmd += stim + electrode
    if args.visualize:
        cmd += ['-gridout_i', 3, '-gridout_e', 3, '-spacedt', 0.1]
    # Run simulation
    job.carp(cmd)
if __name__ == '__main__':
    run()

It seems like the -boundary[0].name keyword is unrecognized by OpenCARP. I've tried different ways of specifying the boundary condition, but I still get this error. I believe it might be related to how I am defining the boundary conditions for the spherical surface.

Could you suggest what might be wrong with the boundary condition syntax, or if there is a better way to define the boundary for a spherical mesh in OpenCARP?

Thanks again for your help 

ago by (260 points)

Hey,

you are right that the parameter -boundary does not exist. I am not really sure what you intend to do with the function sphere_boundary_condition,  but all the parameters you set there do not exist. 

The part where you define the stimulus is missing some information as well. First, I would suggest to switch to the new "stim" parameter, since "stimulus" is deprecated. According to your script, the following should be what you are looking for:

stim[0].name = S1
stim[0].crct.type = 0
stim[0].ptcl.start = 20
stim[0].ptcl.duration = args.S1_dur
stim[0].ptcl.bcl = 500
stim[0].pulse.strength = args.S1_strength

The only thing left is to set the electrode geometry. You can do this using the stim.elec parameter. Either you define it using a vertex file (stim.elec.vtx_file) or you define it using stim.elec.geom_type and its associated parameters. Please study the user manual of openCARP or use the website https://opencarp.org/documentation/opencarp-parameters#master to learn about the parameter settings. The above notation is for the direct use in the parameter file. Adapt for carputils/python accordingly.

If anything is unclear, feel free to ask again!

Welcome to openCARP Q&A. Ask questions and receive answers from other members of the community. For best support, please use appropriate TAGS!
architecture, carputils, documentation, experiments, installation-containers-packages, limpet, slimfem, website, governance
...