Assigning GIDs to netcon without cell object
Posted: Tue Aug 27, 2024 1:12 pm
Hello, I am new to Neuron and I have been working on getting and existing model to work on GPU. I have been following the ringtest repository to understand how the GPU implementation works and how I should initialize the model to work with parallel context.
The model consists of k cells (motor neurons), each with one soma and four dendrites. I also want to play vectors into each of the dendrites of the cell. However, the cell I create is composed of h.SectionList() and not a neuron cell() object. As a result I am not able to use the cell().connect2target() function and I create NetCon objects separately to link with the GIDs I assign to each of the sections.
When I run simulation by using parallelcontext.psolve() I encounter the following error:
This made me suspect that the GIDs I have assigned to the various sections in my model are not behaving as I expect them to. When I use the gid2cell() or gid2obj() functions they return "None" for my model. For the ringtest repo these functions return the cell object from which the cell was initialized leading me to think there is an issue with how I am initializing the NetCon() or how I am linking the GIDs. The GIDs are assigned to the device and gid_exists() function does return value 2, indicating the GID was assigned and made to not communicate the spikes across machines.
These errors do not show up when I use a while loop to run simulation with h.fadvance() and integrate the simulation step by step. However, when I use psolve() then I get the aforementioned error.
Here is a minimal script to reproduce the error I am encountering and model initialization
Following is the output of the print statement in model initialization.
I am trying to determine what could be the source for the error with the psolve() and the gid2obj() function returning "None". Please let me know if I can provide any additional information to help understand this issue.
Thank you!
The model consists of k cells (motor neurons), each with one soma and four dendrites. I also want to play vectors into each of the dendrites of the cell. However, the cell I create is composed of h.SectionList() and not a neuron cell() object. As a result I am not able to use the cell().connect2target() function and I create NetCon objects separately to link with the GIDs I assign to each of the sections.
When I run simulation by using parallelcontext.psolve() I encounter the following error:
Code: Select all
~/nrn/src/coreneuron/io/phase1.cpp:108: Assertion 'neg_gid2out[nt.id].find(gid) == neg_gid2out[nt.id].end()' failed.
These errors do not show up when I use a while loop to run simulation with h.fadvance() and integrate the simulation step by step. However, when I use psolve() then I get the aforementioned error.
Here is a minimal script to reproduce the error I am encountering and model initialization
Code: Select all
from neuron import h
import settings
from neuron import coreneuron
from neuron.units import mV
import numpy as np
pc = h.ParallelContext()
h.CVode().cache_efficient(1)
h.nrnmpi_init()
def spike_record(): # from ringtest repo
global tvec, idvec
tvec = h.Vector(1000000)
idvec = h.Vector(1000000)
pc.spike_record(-1, tvec, idvec)
def spikeout(): # from ringtest repo
global tvec, idvec
rank = int(pc.id())
nhost = int(pc.nhost())
pc.barrier()
return tvec, idvec
class MNPool(object): # based on ringtest repo
counter = 0
def __init__(self, ncell, gidstart = 1, nsoma = 1, ndend = 4):
self.gids = []
self.delay = 1
self.ncell = int(ncell)
self.gidstart = gidstart
self.mkcells(self.ncell, nsoma = 1, ndend = 4)
MNPool.counter += 1
def mkcells(self, ncell, nsoma = 1, ndend = 4): # creates ncell motor neuron with 4 dendrites
self.all_MNs = []
ctr = 0
for i in range(self.gidstart, (ncell*(nsoma+ndend)) + self.gidstart,nsoma+ndend): # creates single MN
self.gids.append([i+x for x in range(nsoma+ndend)])
soma = h.Section(name='soma') # Define soma section
d1 = h.Section(name='d1') # Define dend section
d2 = h.Section(name='d2') # Define dend section
d3 = h.Section(name='d3') # Define dend section
d4 = h.Section(name='d4') # Define dend section
dend = h.SectionList()
dend.append(sec=d1)
dend.append(sec=d2)
dend.append(sec=d3)
dend.append(sec=d4)
# Connect dendrites to soma
d1.connect(soma(1), 0)
d2.connect(soma(1), 0)
d3.connect(soma(0), 0)
d4.connect(soma(0), 0)
MN_parts = {'soma':[soma],
'dend':[d1,d2,d3,d4]}
self.all_MNs.append(MN_parts)
for part in self.all_MNs[ctr].keys():
if part == 'dend':
for section in self.all_MNs[ctr][part]:
section.insert('Gfluctdv') # inserts the mechanism on all 4 dendrites
# This is based on ringtest repo
cell_ctr = 0
for part in MN_parts.keys(): # loop over both soma and dend dict
for section in MN_parts[part]: # from each dict loop over the sections
settings.pc.set_gid2node(i+cell_ctr, settings.rank) # Assign GID for that section
nc = h.NetCon(section(0.5)._ref_v, None, sec = section) # Since the MN is not a cell objcet init a NetCon
settings.pc.cell(i+cell_ctr, nc, 0) # link netcon and GID
print("MN: ",ctr, # print statement to determine GIDs assigned to each MN and section
", section: ", section,
", GID for section: ", i+cell_ctr,
", pc.gid_exists(): ", settings.pc.gid_exists(i+cell_ctr), # expected to return 2 (assigned GID but not communicating spikes)
", pc.gid2obj(): ", settings.pc.gid2obj(i+cell_ctr) # expected to return the section or something similar but returns None
)
cell_ctr+=1
ctr+=1
def main():
num_MN = 2
settings.init(num_MN)
MN_model = MNPool(num_MN,nsoma=1, ndend= 4) # init model
spike_record() # init spike recording
playvect_dict = {
"rn_vec" : [],
}
sim_duration = 30000
excitatory_time = np.arange(0, sim_duration, 1)
target_time = h.Vector(excitatory_time)
noise_vect_w = np.random.normal(0,1,(len(MN_model.all_MNs),len(target_time))) # noise vector for the mechanism
for ctr, MN in enumerate(MN_model.all_MNs):
for num_dend, sec in enumerate(MN["dend"]):
for seg in sec:
rn_vec = h.Vector(noise_vect_w[ctr,:])
rn_vec.play(seg._ref_rand_Gfluctdv,target_time) # play noise vector into each of the MN mechanisms
playvect_dict['rn_vec'].append(rn_vec)
coreneuron.enable = True
coreneuron.gpu = True
pc.set_maxstep(10)
h.dt = 0.025 # unit: ms
h.finitialize(-70 * mV)
h.fcurrent()
pc.psolve(sim_duration)
"""
pc.psolve() raises the following error
int nrnthread_dat2_vecplay(int, std::vector<int, std::allocator<int>> &): Assertion `0' failed.
"""
while h.t < float(sim_duration):
h.fadvance()
if round(h.t, 2) % 10000.00 == 0.00:
print(f'simulation time: {h.t:.1f}', 'ms',)
"""
h.fadvance() works without error
"""
tvec, idvec = spikeout()
if __name__ == "__main__":
main()
Code: Select all
MN: 0 , section: soma , GID for section: 1 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 0 , section: d1 , GID for section: 2 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 0 , section: d2 , GID for section: 3 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 0 , section: d3 , GID for section: 4 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 0 , section: d4 , GID for section: 5 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 1 , section: soma , GID for section: 6 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 1 , section: d1 , GID for section: 7 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 1 , section: d2 , GID for section: 8 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 1 , section: d3 , GID for section: 9 , pc.gid_exists(): 2 , pc.gid2obj(): None
MN: 1 , section: d4 , GID for section: 10 , pc.gid_exists(): 2 , pc.gid2obj(): None
Thank you!