27 double comp_time =
timing(t2, t1);
80 for (
size_t i = 0; i < rs.
size(); i++ ) {
81 rs[i].nsubregs = param_globals::imp_region[i].num_IDs;
82 rs[i].subregtags = param_globals::imp_region[i].ID;
83 for (
int j=0;j<rs[i].nsubregs;j++) {
84 if(rs[i].subregtags[j]==-1 && rank==0)
85 log_msg(NULL,3,
ECHO,
"Warning: not all %u IDs provided for imp_region[%u]!\n", rs[i].nsubregs, i);
93 tstart = setup_MIIF(loc_size, param_globals::num_imp_regions, param_globals::imp_region,
94 reg_mask.
data(), param_globals::start_statef, param_globals::num_adjustments,
95 param_globals::adjustment, param_globals::dt, purkfLen > 0);
102 log_msg(
logger, 0, 0,
"Changing simulation start time to %.2lf", tstart);
113 const char *start_fn,
int numadjust, IMPVariableAdjustment *adjust,
114 double time_step,
bool close)
126 "-----------------------------------\n\n" \
127 "Assigning IMPS to tagged regions:" );
136 if(impreg[i].num_IDs > 0) {
137 for(
int j = 0; j < impreg[i].num_IDs; j++)
146 log_msg(NULL,5,
ECHO,
"Illegal IM specified: %s\n", impreg[i].im );
147 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available models.\n" );
152 if(impreg[i].plugins[0] !=
'\0') {
155 for(
int j = 0; j < impreg[i].num_IDs; j++)
161 log_msg(NULL,5,
ECHO,
"Illegal plugin specified: %s\n", impreg[i].plugins);
162 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available plugins.\n" );
180 if(!
miif->
IIF[i]->cgeom().SVratio)
181 miif->
IIF[i]->cgeom().SVratio = param_globals::imp_region[i].cellSurfVolRatio;
185 remove_char(impreg[i].im_param, strlen(impreg[i].im_param),
' ');
186 miif->
IIF[i]->tune(impreg[i].im_param, impreg[i].plugins, impreg[i].plug_param);
196 if (impreg[i].im_sv_init && strlen(impreg[i].im_sv_init) > 0)
203 if( !start_fn || strlen(start_fn)>0 )
206 for (
int i=0; i<numadjust; i++)
212 bool restrict_to_algebraic =
true;
215 std::map<std::string,std::string> metadata;
219 if(metadata.count(
"grid") && metadata[
"grid"].compare(
"intra") == 0) {
222 read_indices_with_data(indices, values, adjust[i].file, imesh, nbr, restrict_to_algebraic, 1, PETSC_COMM_WORLD);
226 for(
size_t gi = 0; gi < indices.
size(); gi++)
227 indices[gi] = SF::local_nodal_to_local_petsc<mesh_int_t,mesh_real_t>(imesh, rank, indices[gi]);
233 adjPars->set(indices, values,
false,
true);
237 snprintf(fname,
sizeof fname,
"adj_%s_perm.dat", adjust[i].variable);
238 adjPars->write_ascii(fname,
false);
243 log_msg(0,3,0,
"%s warning: PETSC_TO_CANONICAL permutation needed registering!", __func__);
247 (*sc)(*adjPars,
true);
248 snprintf(fname,
sizeof fname,
"adj_%s_canonical.dat", adjust[i].variable);
249 adjPars->write_ascii(fname,
false);
253 log_msg(
logger, 0, 0,
"Adjusted %d values for %s", nc, adjust[i].variable);
275 char svs[1024], plgs[1024], plgsvs[1024], fname[1024];
277 strcpy(svs, reg->im_sv_dumps ? reg->im_sv_dumps :
"");
278 strcpy(plgs, reg->plugins ? reg->plugins :
"");
279 strcpy(plgsvs, reg->plug_sv_dumps ? reg->plug_sv_dumps :
"");
281 if( !(strlen(svs)+strlen(plgsvs) ) )
290 strcpy(fname, param_globals::vofile);
293 log_msg(NULL, 5,
ECHO,
"%s: a region name must be specified\n", __func__ );
298 size_t fname_len = strlen(fname);
299 char* ext_start = fname + fname_len;
300 if(fname_len >= 4 && strcmp(ext_start - 4,
".igb") == 0) ext_start -= 3;
301 strcpy(ext_start, reg->name);
317 const char* gridname,
const char* reglist)
319 bool AllTagsExist =
true;
325 for (
size_t reg=0; reg<regspec.
size(); reg++)
327 for (
int k=0; k<regspec[reg].nsubregs; k++) {
330 if(tagset.
count(regspec[reg].subregtags[k])) n++;
334 if(strcmp(reglist,
"gregion_vol"))
336 "%s[%d] references tag %d, but no element in the %s grid carries this tag — region will have no elements.\n",
337 reglist, reg, regspec[reg].subregtags[k], gridname);
338 AllTagsExist =
false;
343 log_msg(NULL, 4,
ECHO,
"One or more configured regions are empty. Check that region tag IDs match the tags in your mesh or tagfile.\n");
350 const char* gridname,
const char* reglist,
351 bool warn_on_default_tags)
353 if(!warn_on_default_tags)
return;
357 for (
size_t reg = 1; reg < regspec.
size(); reg++)
358 for (
int k = 0; k < regspec[reg].nsubregs; k++)
359 configured.
insert(regspec[reg].subregtags[k]);
362 long int n_defaulted = 0;
364 if (!configured.
count(t)) {
370 n_defaulted =
get_global(n_defaulted, MPI_SUM);
371 if (!n_defaulted)
return;
380 for (
size_t i = 0; i < unmatched.
size(); i++) {
381 if (i) taglist +=
", ";
382 taglist += std::to_string(unmatched[i]);
386 "%s: %ld element(s) in %s grid carry tags {%s} not assigned to any "
387 "%s region; these elements default to region 0.\n",
388 __func__, n_defaulted, gridname, taglist.c_str(), reglist);
393 bool warn_on_default_tags)
395 if(regspec.
size() == 1)
return;
410 regionIDs.
assign(rIDsize, 0);
415 for (
size_t reg=1; reg < regspec.
size(); reg++) {
417 for (
int k=0; k < regspec[reg].nsubregs; k++) {
418 int curtag = regspec[reg].subregtags[k];
419 if(tag_to_reg.
count(curtag)) err++;
422 log_msg(0,4,0,
"%s warning: Tag idx %d is assigned to multiple regions!\n"
423 "Its final assignment will be to the highest assigned region ID!",
426 tag_to_reg[curtag] = reg;
433 for(
size_t i=0; i<nelem; i++) {
436 if (tag_to_reg.
count(cur_tag))
438 int reg = tag_to_reg[cur_tag];
440 if (mask_elem) regionIDs[i] = reg;
444 for (
int j=0; j < eview.
num_nodes(); j++) {
446 if (cur_tag > mx_tag[n]) mx_tag[n] = cur_tag;
452 if(mask_elem)
return;
458 mesh.
pl.reduce(mx_tag,
"max");
460 for(
size_t i=0; i < regionIDs.
size(); i++)
461 if(mx_tag[i] >= 0) regionIDs[i] = tag_to_reg[mx_tag[i]];
469 for(
size_t i=0; i<alg_nod.
size(); i++) {
470 alg_reg[i] = regionIDs[alg_nod[i]];
471 gids[i] = nbr[alg_nod[i]];
476 if(param_globals::dump_imp_region) {
478 write_data_ascii(PETSC_COMM_WORLD, gids, regionIDs, std::string(reglist)+
".dat");
486 double val = std::nan(
"NaN");
500 if (impdata[limpet::Iion] != NULL)
501 impdata[limpet::Iion][n] = 0;
505 imp.
compute(n, n + 1, impdata);
521 int* offset,
int* sz,
int* plugin_idx)
525 if(strcmp(IMP, miif->
iontypes[idx].get().get_name().c_str()) == 0) {
526 return (
void*) miif->
iontypes[idx].get().get_sv_offset(SV, offset, sz);
529 for(
int k=0; k<miif->
numplugs[idx]; k++)
530 if(strcmp(IMP, miif->
plugtypes[idx][k].get().get_name().c_str()) == 0) {
532 return (
void*) miif->
plugtypes[idx][k].get().get_sv_offset(SV, offset, sz);
552 glob_vecs.
nRegs = nRegs;
555 glob_vecs.
vecs.resize(nGVcs);
558 for (
size_t i = 0; i < glob_vecs.
vecs.size(); i++) {
563 gvec.
bogus = prmGVecs[i].bogus;
565 gvec.
imps = (
char**) calloc(nRegs,
sizeof(
char *));
566 gvec.
svNames = (
char**) calloc(nRegs,
sizeof(
char *));
567 gvec.
svSizes = (
int*) calloc(nRegs,
sizeof(
int));
568 gvec.
svOff = (
int*) calloc(nRegs,
sizeof(
int));
571 for (
int j = 0; j < nRegs; j++) {
572 if (strlen(prmGVecs[i].imp)) gvec.
imps[j] =
dupstr(prmGVecs[i].imp);
574 else if (j < param_globals::num_imp_regions)
575 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
577 gvec.
imps[j] =
dupstr(param_globals::PurkIon[j - param_globals::num_imp_regions].im);
579 else if (j < param_globals::num_imp_regions)
580 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
605 int num_purk_regions = 0;
606 int nRegs = param_globals::num_imp_regions + num_purk_regions;
608 alloc_gvec_data(param_globals::num_gvecs, nRegs, param_globals::gvec, GVs);
611 if (GVs->
inclPS) sample_PS_ionSVs(purk);
614 for (
unsigned int i = 0; i < GVs.
vecs.size(); i++) {
618 for (
int j = 0; j < miif->
N_IIF; j++) {
621 if (gv.
getsv[j] == NULL) {
622 log_msg(NULL, 3,
ECHO,
"\tWarning: SV(%s) not found in region %d\n", gv.
svNames[j], j);
634 MULTI_IF* pmiif = &purk->ion;
635 for (
int j = miif->
N_IIF; j < nRegs; j++) {
639 if (gv.
getsv[j] == NULL) {
640 LOG_MSG(NULL, 3,
ECHO,
"\tWarning: state variable \"%s\" not found in region %d\n", gv.
svNames[j], j);
644 RVector_dup(purk->vm_pt, &gv.orderedPS_PS);
647 RVector_dup(purk->vm_pt_over, &gv.orderedPS);
648 initialize_grid_output(grid, NULL, tmo,
intra_elec_msh, GRID_WRITE, 0., 1., gv.
units, gv.orderedPS,
649 1, gv.GVcName, -purk->npt, param_globals::output_level);
654 log_msg(NULL, 5,
ECHO,
"\tError: no state variables found for global vector %d\n", i);
655 log_msg(NULL, 5,
ECHO,
"Run bench --imp=YourModel --imp-info to get a list of all parameters.\\n");
673 for(
size_t i=0; i<gvecs.
vecs.size(); i++ ) {
682 for(
int n = 0; n<miif->
N_IIF; n++ ) {
683 if( !gv.
getsv[n] )
continue;
692 indices[j] = miif->
NodeLists[n][j] + start;
opencarp::local_index_t mesh_int_t
opencarp::global_index_t SF_int
Global algebraic index type.
virtual void get_ownership_range(T &start, T &stop) const =0
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false, const bool local=false)=0
Comfort class. Provides getter functions to access the mesh member variables more comfortably.
const T & node(short nidx) const
Access the connectivity information.
void set_elem(size_t eidx)
Set the view to a new element.
T num_nodes() const
Getter function for the number of nodes.
overlapping_layout< T > pl
nodal parallel layout
size_t l_numelem
local number of elements
std::string name
the mesh name
size_t l_numpts
local number of points
vector< T > & get_numbering(SF_nbr nbr_type)
Get the vector defining a certain numbering.
vector< T > tag
element tag
Container for a PETSc VecScatter.
A vector storing arbitrary data.
size_t size() const
The current size of the vector.
void resize(size_t n)
Resize a vector.
const T * end() const
Pointer to the vector's end.
void assign(InputIterator s, InputIterator e)
Assign a memory range.
const T * begin() const
Pointer to the vector's start.
T * data()
Pointer to the vector's start.
hm_int count(const K &key) const
Check if key exists.
Custom unordered_set implementation.
hm_int count(const K &key) const
void insert(InputIterator first, InputIterator last)
Represents the ionic model and plug-in (IMP) data structure.
std::vector< IonIfBase * > & plugins()
Returns a vector containing the plugins of this IMP.
void compute(node_index_t start, node_index_t end, GlobalData_t **data)
Perform ionic model computation for 1 time step.
ts & get_tstp()
Gets the time stepper.
void for_each(const std::function< void(IonIfBase &)> &consumer)
Executes the consumer functions on this IMP and each of its plugins.
bool extUpdateVm
flag indicating update function for Vm
std::vector< IonIfBase * > IIF
array of IIF's
opencarp::sf_vec * gdata[NUM_IMP_DATA_TYPES]
data used by all IMPs
void sv_dump_add_by_name_list(int, char *, char *, char *, char *, char *, double, double)
node_count_t numNode
local number of nodes
int * numplugs
number of plugins for each region
std::vector< Target > targets
target for each region
std::vector< IonTypeList > plugtypes
plugins types for each region
IonTypeList iontypes
type for each region
void initialize_currents(double, int)
float restore_state(const char *, opencarp::mesh_t gid, bool)
int N_IIF
how many different IIF's
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...
node_count_t * N_Nodes
#nodes for each IMP
opencarp::FILE_SPEC logger
node_index_t ** NodeLists
local partitioned node lists for each IMP stored
IIF_Mask_t * IIFmask
region for each node
int adjust_MIIF_variables(const char *variable, const SF::vector< SF_int > &indices, const SF::vector< SF_real > &values)
std::string name
name for MIIF region
FILE_SPEC logger
The logger of the physic, each physic should have one.
const char * name
The name of the physic, each physic should have one.
generic_timing_stats comp_stats
std::string timer_unit(const int timer_id)
figure out units of a signal linked to a given timer
double timer_val(const int timer_id)
figure out current value of a signal linked to a given timer
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 setup(double inp_dt, double inp_start, double inp_end)
Initialize the timer_manager.
void reset_timers()
Reset time in timer_manager and then reset registered timers.
Electrical ionics functions and LIMPET wrappers.
void write_data_ascii(const MPI_Comm comm, const vector< T > &idx, const vector< S > &data, std::string file, short dpn=1)
void make_global(const vector< T > &vec, vector< T > &out, MPI_Comm comm)
make a parallel vector global
void unique_resize(vector< T > &_P)
void init_vector(SF::abstract_vector< T, S > **vec)
void binary_sort(vector< T > &_V)
SF_nbr
Enumeration encoding the different supported numberings.
@ NBR_PETSC
PETSc numbering of nodes.
@ NBR_REF
The nodal numbering of the reference mesh (the one stored on HD).
@ NBR_SUBMESH
Submesh nodal numbering: The globally ascending sorted reference indices are reindexed.
int get_plug_flag(char *plgstr, int *out_num_plugins, IonTypeList &out_plugins)
IonType * get_ion_type(const std::string &name)
GlobalData_t(* SVgetfcn)(IonIfBase &, node_index_t, int)
void update_ts(ts *ptstp)
opencarp::local_index_t node_count_t
int read_sv(MULTI_IF *, int, const char *)
opencarp::local_index_t node_index_t
std::map< int, std::string > units
timer_manager * tm_manager
a manager for the various physics timers
void compute_IIF(limpet::IonIfBase &pIF, limpet::GlobalData_t **impdata, limpet::node_index_t n)
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)
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
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.
void region_mask(mesh_t meshspec, SF::vector< RegionSpecs > ®spec, SF::vector< int > ®ionIDs, bool mask_elem, const char *reglist, bool warn_on_default_tags)
classify elements/points as belonging to a region
SF::meshdata< mesh_int_t, mesh_real_t > sf_mesh
void read_metadata(const std::string filename, std::map< std::string, std::string > &metadata, MPI_Comm comm)
Read metadata from the header.
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
void check_unassigned_tags(const SF::vector< mesh_int_t > &tags, SF::vector< RegionSpecs > ®spec, const char *gridname, const char *reglist, bool warn_on_default_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.
void register_data(sf_vec *dat, datavec_t d)
Register a data vector in the global registry.
void initialize_sv_dumps(limpet::MULTI_IF *pmiif, IMPregion *reg, int id, double t, double dump_dt)
void init_sv_gvec(gvec_data &GVs, limpet::MULTI_IF *miif, sf_vec &tmpl, igb_output_manager &output_manager)
void assemble_sv_gvec(gvec_data &gvecs, limpet::MULTI_IF *miif)
char * dupstr(const char *old_str)
bool check_tags_in_elems(const SF::vector< mesh_int_t > &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.
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
mesh_t
The enum identifying the different meshes we might want to load.
void alloc_gvec_data(const int nGVcs, const int nRegs, GVecs *prmGVecs, gvec_data &glob_vecs)
void get_time(double &tm)
SF::abstract_vector< SF_int, SF_real > sf_vec
void remove_char(char *buff, const int buffsize, const char c)
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
V timing(V &t2, const V &t1)
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
void log_stats(double tm, bool cflg)
void init_logger(const char *filename)
int calls
# calls for this interval, this is incremented externally
double tot_time
total time, this is incremented externally
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.
SF::vector< sv_data > vecs
store sv dump indices for global vectors
unsigned int nRegs
number of imp regions
bool inclPS
include PS if exists
float bogus
value indicating sv not in region
void ** getsv
functions to retrieve sv
char * name
Name of global composite sv vector.
int * svOff
sv size in bytes
char ** svNames
sv names of components forming global vector
int * svSizes
sv size in bytes
char ** imps
Name of imp to which sv belongs.
sf_vec * ordered
vector in which to place ordered data