42 double comp_time =
timing(t2, t1);
92 for (
size_t i = 0; i < rs.
size(); i++ ) {
93 rs[i].nsubregs = param_globals::imp_region[i].num_IDs;
94 rs[i].subregtags = param_globals::imp_region[i].ID;
95 for (
int j=0;j<rs[i].nsubregs;j++) {
96 if(rs[i].subregtags[j]==-1 && rank==0)
97 log_msg(NULL,3,
ECHO,
"Warning: not all %u IDs provided for imp_region[%u]!\n", rs[i].nsubregs, i);
105 tstart = setup_MIIF(loc_size, param_globals::num_imp_regions, param_globals::imp_region,
106 reg_mask.
data(), param_globals::start_statef, param_globals::num_adjustments,
107 param_globals::adjustment, param_globals::dt, purkfLen > 0);
114 log_msg(
logger, 0, 0,
"Changing simulation start time to %.2lf", tstart);
124 double Ionics::setup_MIIF(
int nnodes,
int nreg, IMPregion* impreg,
int* mask,
125 const char *start_fn,
int numadjust, IMPVariableAdjustment *adjust,
126 double time_step,
bool close)
138 "-----------------------------------\n\n" \
139 "Assigning IMPS to tagged regions:" );
148 if(impreg[i].num_IDs > 0) {
149 for(
int j = 0; j < impreg[i].num_IDs; j++)
158 log_msg(NULL,5,
ECHO,
"Illegal IM specified: %s\n", impreg[i].im );
159 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available models.\n" );
164 if(impreg[i].plugins[0] !=
'\0') {
167 for(
int j = 0; j < impreg[i].num_IDs; j++)
173 log_msg(NULL,5,
ECHO,
"Illegal plugin specified: %s\n", impreg[i].plugins);
174 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available plugins.\n" );
192 if(!
miif->
IIF[i]->cgeom().SVratio)
193 miif->
IIF[i]->cgeom().SVratio = param_globals::imp_region[i].cellSurfVolRatio;
197 remove_char(impreg[i].im_param, strlen(impreg[i].im_param),
' ');
198 miif->
IIF[i]->tune(impreg[i].im_param, impreg[i].plugins, impreg[i].plug_param);
208 if (impreg[i].im_sv_init && strlen(impreg[i].im_sv_init) > 0)
215 if( !start_fn || strlen(start_fn)>0 )
218 for (
int i=0; i<numadjust; i++)
224 bool restrict_to_algebraic =
true;
227 std::map<std::string,std::string> metadata;
231 if(metadata.count(
"grid") && metadata[
"grid"].compare(
"intra") == 0) {
234 read_indices_with_data(indices, values, adjust[i].file, imesh, nbr, restrict_to_algebraic, 1, PETSC_COMM_WORLD);
238 for(
size_t gi = 0; gi < indices.
size(); gi++)
239 indices[gi] = SF::local_nodal_to_local_petsc<mesh_int_t,mesh_real_t>(imesh, rank, indices[gi]);
245 adjPars->
set(indices, values);
249 snprintf(fname,
sizeof fname,
"adj_%s_perm.dat", adjust[i].variable);
255 log_msg(0,3,0,
"%s warning: PETSC_TO_CANONICAL permutation needed registering!", __func__);
259 (*sc)(*adjPars,
true);
260 snprintf(fname,
sizeof fname,
"adj_%s_canonical.dat", adjust[i].variable);
261 adjPars->write_ascii(fname,
false);
265 log_msg(
logger, 0, 0,
"Adjusted %d values for %s", nc, adjust[i].variable);
287 char svs[1024], plgs[1024], plgsvs[1024], fname[1024];
289 strcpy(svs, reg->im_sv_dumps ? reg->im_sv_dumps :
"");
290 strcpy(plgs, reg->plugins ? reg->plugins :
"");
291 strcpy(plgsvs, reg->plug_sv_dumps ? reg->plug_sv_dumps :
"");
293 if( !(strlen(svs)+strlen(plgsvs) ) )
302 strcpy(fname, param_globals::vofile);
305 log_msg(NULL, 5,
ECHO,
"%s: a region name must be specified\n", __func__ );
310 char* ext_start = NULL;
311 ext_start = strstr(fname,
"igb.gz");
312 if(ext_start == NULL) ext_start = strstr(fname,
"igb");
313 if(ext_start == NULL) ext_start = fname + strlen(fname);
314 strcpy(ext_start, reg->name);
330 const char* gridname,
const char* reglist)
332 bool AllTagsExist =
true;
338 for (
size_t reg=0; reg<regspec.
size(); reg++)
340 for (
int k=0; k<regspec[reg].nsubregs; k++) {
343 if(tagset.
count(regspec[reg].subregtags[k])) n++;
348 "Region tag %d in %s[%d] not found in element list for %s grid.\n",
349 regspec[reg].subregtags[k], reglist, reg, gridname);
350 AllTagsExist =
false;
355 log_msg(NULL, 4,
ECHO,
"Missing element tags in element file!\n" 356 "Check region ID specs in input files!\n");
365 if(regspec.
size() == 1)
return;
379 regionIDs.
assign(rIDsize, 0);
384 for (
size_t reg=1; reg < regspec.
size(); reg++) {
386 for (
int k=0; k < regspec[reg].nsubregs; k++) {
387 int curtag = regspec[reg].subregtags[k];
388 if(tag_to_reg.
count(curtag)) err++;
391 log_msg(0,4,0,
"%s warning: Tag idx %d is assigned to multiple regions!\n" 392 "Its final assignment will be to the highest assigned region ID!",
395 tag_to_reg[curtag] = reg;
402 for(
size_t i=0; i<nelem; i++) {
405 if (tag_to_reg.
count(cur_tag))
407 int reg = tag_to_reg[cur_tag];
409 if (mask_elem) regionIDs[i] = reg;
413 for (
int j=0; j < eview.
num_nodes(); j++) {
415 if (cur_tag > mx_tag[n]) mx_tag[n] = cur_tag;
421 if(mask_elem)
return;
423 for(
size_t i=0; i < regionIDs.
size(); i++)
424 if(mx_tag[i] >= 0) regionIDs[i] = tag_to_reg[mx_tag[i]];
435 for(
size_t i=0; i<alg_nod.
size(); i++) {
436 alg_reg[i] = regionIDs[alg_nod[i]];
437 gids[i] = nbr[alg_nod[i]];
442 if(param_globals::dump_imp_region) {
444 write_data_ascii(PETSC_COMM_WORLD, gids, regionIDs, std::string(reglist)+
".dat");
452 double val = std::nan(
"NaN");
466 if (impdata[limpet::Iion] != NULL)
467 impdata[limpet::Iion][n] = 0;
471 imp.
compute(n, n + 1, impdata);
487 int* offset,
int* sz,
int* plugin_idx)
491 if(strcmp(IMP, miif->
iontypes[idx].get().get_name().c_str()) == 0) {
492 return (
void*) miif->
iontypes[idx].get().get_sv_offset(SV, offset, sz);
495 for(
int k=0; k<miif->
numplugs[idx]; k++)
496 if(strcmp(IMP, miif->
plugtypes[idx][k].get().get_name().c_str()) == 0) {
498 return (
void*) miif->
plugtypes[idx][k].get().get_sv_offset(SV, offset, sz);
518 glob_vecs.
nRegs = nRegs;
521 glob_vecs.
vecs.resize(nGVcs);
524 for (
size_t i = 0; i < glob_vecs.
vecs.size(); i++) {
529 gvec.
bogus = prmGVecs[i].bogus;
531 gvec.
imps = (
char**) calloc(nRegs,
sizeof(
char *));
532 gvec.
svNames = (
char**) calloc(nRegs,
sizeof(
char *));
533 gvec.
svSizes = (
int*) calloc(nRegs,
sizeof(
int));
534 gvec.
svOff = (
int*) calloc(nRegs,
sizeof(
int));
537 for (
int j = 0; j < nRegs; j++) {
538 if (strlen(prmGVecs[i].imp)) gvec.
imps[j] =
dupstr(prmGVecs[i].imp);
540 else if (j < param_globals::num_imp_regions)
541 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
543 gvec.
imps[j] =
dupstr(param_globals::PurkIon[j - param_globals::num_imp_regions].im);
545 else if (j < param_globals::num_imp_regions)
546 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
571 int num_purk_regions = 0;
572 int nRegs = param_globals::num_imp_regions + num_purk_regions;
574 alloc_gvec_data(param_globals::num_gvecs, nRegs, param_globals::gvec, GVs);
577 if (GVs->
inclPS) sample_PS_ionSVs(purk);
580 for (
unsigned int i = 0; i < GVs.
vecs.size(); i++) {
584 for (
int j = 0; j < miif->
N_IIF; j++) {
587 if (gv.
getsv[j] == NULL) {
588 log_msg(NULL, 3,
ECHO,
"\tWarning: SV(%s) not found in region %d\n", gv.
svNames[j], j);
600 MULTI_IF* pmiif = &purk->ion;
601 for (
int j = miif->
N_IIF; j < nRegs; j++) {
605 if (gv.
getsv[j] == NULL) {
606 LOG_MSG(NULL, 3,
ECHO,
"\tWarning: state variable \"%s\" not found in region %d\n", gv.
svNames[j], j);
610 RVector_dup(purk->vm_pt, &gv.orderedPS_PS);
613 RVector_dup(purk->vm_pt_over, &gv.orderedPS);
614 initialize_grid_output(grid, NULL, tmo,
intra_elec_msh, GRID_WRITE, 0., 1., gv.
units, gv.orderedPS,
615 1, gv.GVcName, -purk->npt, param_globals::output_level);
620 log_msg(NULL, 5,
ECHO,
"\tError: no state variables found for global vector %d\n", i);
621 log_msg(NULL, 5,
ECHO,
"Run bench --imp=YourModel --imp-info to get a list of all parameters.\\n");
639 for(
size_t i=0; i<gvecs.
vecs.size(); i++ ) {
648 for(
int n = 0; n<miif->
N_IIF; n++ ) {
649 if( !gv.
getsv[n] )
continue;
657 for(
int j=0; j<miif->
N_Nodes[n]; j++ ) {
658 indices[j] = miif->
NodeLists[n][j] + start;
GlobalData_t(* SVgetfcn)(IonIfBase &, int, int)
SF::scattering * get_permutation(const int mesh_id, const int perm_id, const int dpn)
Get the PETSC to canonical permutation scattering for a given mesh and number of dpn.
int ** NodeLists
local partitioned node lists for each IMP stored
int read_sv(MULTI_IF *, int, const char *)
void log_stats(double tm, bool cflg)
float bogus
value indicating sv not in region
vector< T > & get_numbering(SF_nbr nbr_type)
Get the vector defining a certain numbering.
char * dupstr(const char *old_str)
sf_vec * ordered
vector in which to place ordered data
double timer_val(const int timer_id)
figure out current value of a signal linked to a given timer
unsigned int nRegs
number of imp regions
vector< T > tag
element tag
PETSc numbering of nodes.
void sv_dump_add_by_name_list(int, char *, char *, char *, char *, char *, double, double)
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
int * numplugs
number of plugins for each region
Comfort class. Provides getter functions to access the mesh member variables more comfortably...
char ** imps
Name of imp to which sv belongs.
void compute_ionic_current(bool flag_send=1, bool flag_receive=1)
GPU kernel to emulate the add_scaled call made to adjust the Vm values when the update to Vm is not m...
overlapping_layout< T > pl
nodal parallel layout
void reset_timers()
Reset time in timer_manager and then reset registered timers.
int calls
# calls for this interval, this is incremented externally
IIF_Mask_t * IIFmask
region for each node
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false, const bool local=false)=0
void alloc_gvec_data(const int nGVcs, const int nRegs, GVecs *prmGVecs, gvec_data &glob_vecs)
FILE_SPEC logger
The logger of the physic, each physic should have one.
timer_manager * tm_manager
a manager for the various physics timers
std::string name
name for MIIF region
void write_data_ascii(const MPI_Comm comm, const vector< T > &idx, const vector< S > &data, std::string file, short dpn=1)
The nodal numbering of the reference mesh (the one stored on HD).
float restore_state(const char *, opencarp::mesh_t gid, bool)
const char * name
The name of the physic, each physic should have one.
IonTypeList iontypes
type for each region
T * data()
Pointer to the vector's start.
mesh_t
The enum identifying the different meshes we might want to load.
int get_plug_flag(char *plgstr, int *out_num_plugins, IonTypeList &out_plugins)
std::vector< IonTypeList > plugtypes
plugins types for each region
int N_IIF
how many different IIF's
void initialize_currents(double, int)
void remove_char(char *buff, const int buffsize, const char c)
size_t write_ascii(const char *file, bool write_header)
void init_logger(const char *filename)
void init_vector(SF::abstract_vector< T, S > **vec)
SF_nbr
Enumeration encoding the different supported numberings.
void region_mask(mesh_t meshspec, SF::vector< RegionSpecs > ®spec, SF::vector< int > ®ionIDs, bool mask_elem, const char *reglist)
classify elements/points as belonging to a region
std::vector< IonIfBase * > IIF
array of IIF's
void setup(double inp_dt, double inp_start, double inp_end)
Initialize the timer_manager.
const T * end() const
Pointer to the vector's end.
void ** getsv
functions to retrieve sv
void compute_IIF(limpet::IonIfBase &pIF, limpet::GlobalData_t **impdata, int n)
SF::vector< sv_data > vecs
store sv dump indices for global vectors
double tot_time
total time, this is incremented externally
Submesh nodal numbering: The globally ascending sorted reference indices are reindexed.
void assemble_sv_gvec(gvec_data &gvecs, limpet::MULTI_IF *miif)
hm_int count(const K &key) const
Represents the ionic model and plug-in (IMP) data structure.
IonType * get_ion_type(const std::string &name)
char ** svNames
sv names of components forming global vector
void initialize_sv_dumps(limpet::MULTI_IF *pmiif, IMPregion *reg, int id, double t, double dump_dt)
void compute(int start, int end, GlobalData_t **data)
Perform ionic model computation for 1 time step.
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
bool check_tags_in_elems(const SF::vector< int > &tags, SF::vector< RegionSpecs > ®spec, const char *gridname, const char *reglist)
Check whether the tags in the region spec struct matches with an array of tags.
SF::scattering * register_permutation(const int mesh_id, const int perm_id, const int dpn)
Register a permutation between two orderings for a mesh.
generic_timing_stats comp_stats
int * svOff
sv size in bytes
Electrical ionics functions and LIMPET wrappers.
void insert(InputIterator first, InputIterator last)
void register_data(sf_vec *dat, datavec_t d)
Register a data vector in the global registry.
void get_time(double &tm)
void set_elem(size_t eidx)
Set the view to a new element.
ts & get_tstp()
Gets the time stepper.
T num_nodes() const
Getter function for the number of nodes.
void * find_SV_in_IMP(limpet::MULTI_IF *miif, const int idx, const char *IMP, const char *SV, int *offset, int *sz, int *plugin_idx)
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
int * N_Nodes
#nodes for each IMP
V timing(V &t2, const V &t1)
std::string timer_unit(const int timer_id)
figure out units of a signal linked to a given timer
opencarp::sf_vec * gdata[NUM_IMP_DATA_TYPES]
data used by all IMPs
std::string name
the mesh name
hm_int count(const K &key) const
Check if key exists.
void for_each(const std::function< void(IonIfBase &)> &consumer)
Executes the consumer functions on this IMP and each of its plugins.
size_t size() const
The current size of the vector.
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
void init_sv_gvec(gvec_data &GVs, limpet::MULTI_IF *miif, sf_vec &tmpl, igb_output_manager &output_manager)
void read_metadata(const std::string filename, std::map< std::string, std::string > &metadata, MPI_Comm comm)
Read metadata from the header.
std::vector< IonIfBase * > & plugins()
Returns a vector containing the plugins of this IMP.
void reduce(vector< V > &ndat, const char *op) const
Compute a reduction on overlapping data.
size_t l_numpts
local number of points
void update_ts(ts *ptstp)
A vector storing arbitrary data.
virtual void get_ownership_range(T &start, T &stop) const =0
size_t l_numelem
local number of elements
std::vector< Target > targets
target for each region
int numNode
local number of nodes
const T * begin() const
Pointer to the vector's start.
char * name
Name of global composite sv vector.
void register_output(sf_vec *inp_data, const mesh_t inp_meshid, const int dpn, const char *name, const char *units, const SF::vector< mesh_int_t > *idx=NULL, bool elem_data=false)
Register a data vector for output.
void read_indices_with_data(SF::vector< T > &idx, SF::vector< S > &dat, const std::string filename, const hashmap::unordered_map< mesh_int_t, mesh_int_t > &dd_map, const int dpn, MPI_Comm comm)
like read_indices, but with associated data for each index
void assign(InputIterator s, InputIterator e)
Assign a memory range.
std::map< int, std::string > units
const vector< T > & algebraic_nodes() const
Getter function for the local indices forming the local algebraic node set.
std::int32_t SF_int
Use the general std::int32_t as int type.
int * svSizes
sv size in bytes
size_t num_algebraic_idx() const
Retrieve the number of local algebraic indices.
bool extUpdateVm
flag indicating update function for Vm
bool inclPS
include PS if exists
void resize(size_t n)
Resize a vector.
int adjust_MIIF_variables(const char *variable, const SF::vector< SF_int > &indices, const SF::vector< SF_real > &values)
SF::vector< int > plugin_idx
if we use a plugin, its index in the plugins list of the IMP will be stored here, else -1...
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
const T & node(short nidx) const
Access the connectivity information.
Container for a PETSc VecScatter.