42 double comp_time =
timing(t2, t1);
95 for (
size_t i = 0; i < rs.
size(); i++ ) {
96 rs[i].nsubregs = param_globals::imp_region[i].num_IDs;
97 rs[i].subregtags = param_globals::imp_region[i].ID;
98 for (
int j=0;j<rs[i].nsubregs;j++) {
99 if(rs[i].subregtags[j]==-1 && rank==0)
100 log_msg(NULL,3,
ECHO,
"Warning: not all %u IDs provided for imp_region[%u]!\n", rs[i].nsubregs, i);
108 tstart = setup_MIIF(loc_size, param_globals::num_imp_regions, param_globals::imp_region,
109 reg_mask.
data(), param_globals::start_statef, param_globals::num_adjustments,
110 param_globals::adjustment, param_globals::dt, purkfLen > 0);
117 log_msg(
logger, 0, 0,
"Changing simulation start time to %.2lf", tstart);
128 const char *start_fn,
int numadjust, IMPVariableAdjustment *adjust,
129 double time_step,
bool close)
141 "-----------------------------------\n\n" \
142 "Assigning IMPS to tagged regions:" );
151 if(impreg[i].num_IDs > 0) {
152 for(
int j = 0; j < impreg[i].num_IDs; j++)
161 log_msg(NULL,5,
ECHO,
"Illegal IM specified: %s\n", impreg[i].im );
162 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available models.\n" );
167 if(impreg[i].plugins[0] !=
'\0') {
170 for(
int j = 0; j < impreg[i].num_IDs; j++)
176 log_msg(NULL,5,
ECHO,
"Illegal plugin specified: %s\n", impreg[i].plugins);
177 log_msg(NULL,5,
ECHO,
"Run bench --list-imps for a list of all available plugins.\n" );
195 if(!
miif->
IIF[i]->cgeom().SVratio)
196 miif->
IIF[i]->cgeom().SVratio = param_globals::imp_region[i].cellSurfVolRatio;
200 remove_char(impreg[i].im_param, strlen(impreg[i].im_param),
' ');
201 miif->
IIF[i]->tune(impreg[i].im_param, impreg[i].plugins, impreg[i].plug_param);
211 if (impreg[i].im_sv_init && strlen(impreg[i].im_sv_init) > 0)
218 if( !start_fn || strlen(start_fn)>0 )
221 for (
int i=0; i<numadjust; i++)
227 bool restrict_to_algebraic =
true;
230 std::map<std::string,std::string> metadata;
234 if(metadata.count(
"grid") && metadata[
"grid"].compare(
"intra") == 0) {
237 read_indices_with_data(indices, values, adjust[i].file, imesh, nbr, restrict_to_algebraic, 1, PETSC_COMM_WORLD);
241 for(
size_t gi = 0; gi < indices.
size(); gi++)
242 indices[gi] = SF::local_nodal_to_local_petsc<mesh_int_t,mesh_real_t>(imesh, rank, indices[gi]);
248 adjPars->set(indices, values,
false,
true);
252 snprintf(fname,
sizeof fname,
"adj_%s_perm.dat", adjust[i].variable);
253 adjPars->write_ascii(fname,
false);
258 log_msg(0,3,0,
"%s warning: PETSC_TO_CANONICAL permutation needed registering!", __func__);
262 (*sc)(*adjPars,
true);
263 snprintf(fname,
sizeof fname,
"adj_%s_canonical.dat", adjust[i].variable);
264 adjPars->write_ascii(fname,
false);
268 log_msg(
logger, 0, 0,
"Adjusted %d values for %s", nc, adjust[i].variable);
290 char svs[1024], plgs[1024], plgsvs[1024], fname[1024];
292 strcpy(svs, reg->im_sv_dumps ? reg->im_sv_dumps :
"");
293 strcpy(plgs, reg->plugins ? reg->plugins :
"");
294 strcpy(plgsvs, reg->plug_sv_dumps ? reg->plug_sv_dumps :
"");
296 if( !(strlen(svs)+strlen(plgsvs) ) )
305 strcpy(fname, param_globals::vofile);
308 log_msg(NULL, 5,
ECHO,
"%s: a region name must be specified\n", __func__ );
313 size_t fname_len = strlen(fname);
314 char* ext_start = fname + fname_len;
315 if(fname_len >= 4 && strcmp(ext_start - 4,
".igb") == 0) ext_start -= 3;
316 strcpy(ext_start, reg->name);
332 const char* gridname,
const char* reglist)
334 bool AllTagsExist =
true;
340 for (
size_t reg=0; reg<regspec.
size(); reg++)
342 for (
int k=0; k<regspec[reg].nsubregs; k++) {
345 if(tagset.
count(regspec[reg].subregtags[k])) n++;
349 if(strcmp(reglist,
"gregion_vol"))
351 "%s[%d] references tag %d, but no element in the %s grid carries this tag — region will have no elements.\n",
352 reglist, reg, regspec[reg].subregtags[k], gridname);
353 AllTagsExist =
false;
358 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");
365 const char* gridname,
const char* reglist,
366 bool warn_on_default_tags)
368 if(!warn_on_default_tags)
return;
372 for (
size_t reg = 1; reg < regspec.
size(); reg++)
373 for (
int k = 0; k < regspec[reg].nsubregs; k++)
374 configured.
insert(regspec[reg].subregtags[k]);
377 long int n_defaulted = 0;
379 if (!configured.
count(t)) {
385 n_defaulted =
get_global(n_defaulted, MPI_SUM);
386 if (!n_defaulted)
return;
395 for (
size_t i = 0; i < unmatched.
size(); i++) {
396 if (i) taglist +=
", ";
397 taglist += std::to_string(unmatched[i]);
401 "%s: %ld element(s) in %s grid carry tags {%s} not assigned to any "
402 "%s region; these elements default to region 0.\n",
403 __func__, n_defaulted, gridname, taglist.c_str(), reglist);
408 bool warn_on_default_tags)
410 if(regspec.
size() == 1)
return;
425 regionIDs.
assign(rIDsize, 0);
430 for (
size_t reg=1; reg < regspec.
size(); reg++) {
432 for (
int k=0; k < regspec[reg].nsubregs; k++) {
433 int curtag = regspec[reg].subregtags[k];
434 if(tag_to_reg.
count(curtag)) err++;
437 log_msg(0,4,0,
"%s warning: Tag idx %d is assigned to multiple regions!\n"
438 "Its final assignment will be to the highest assigned region ID!",
441 tag_to_reg[curtag] = reg;
448 for(
size_t i=0; i<nelem; i++) {
451 if (tag_to_reg.
count(cur_tag))
453 int reg = tag_to_reg[cur_tag];
455 if (mask_elem) regionIDs[i] = reg;
459 for (
int j=0; j < eview.
num_nodes(); j++) {
461 if (cur_tag > mx_tag[n]) mx_tag[n] = cur_tag;
467 if(mask_elem)
return;
473 mesh.
pl.reduce(mx_tag,
"max");
475 for(
size_t i=0; i < regionIDs.
size(); i++)
476 if(mx_tag[i] >= 0) regionIDs[i] = tag_to_reg[mx_tag[i]];
484 for(
size_t i=0; i<alg_nod.
size(); i++) {
485 alg_reg[i] = regionIDs[alg_nod[i]];
486 gids[i] = nbr[alg_nod[i]];
491 if(param_globals::dump_imp_region) {
493 write_data_ascii(PETSC_COMM_WORLD, gids, regionIDs, std::string(reglist)+
".dat");
501 double val = std::nan(
"NaN");
515 if (impdata[limpet::Iion] != NULL)
516 impdata[limpet::Iion][n] = 0;
520 imp.
compute(n, n + 1, impdata);
536 int* offset,
int* sz,
int* plugin_idx)
540 if(strcmp(IMP, miif->
iontypes[idx].get().get_name().c_str()) == 0) {
541 return (
void*) miif->
iontypes[idx].get().get_sv_offset(SV, offset, sz);
544 for(
int k=0; k<miif->
numplugs[idx]; k++)
545 if(strcmp(IMP, miif->
plugtypes[idx][k].get().get_name().c_str()) == 0) {
547 return (
void*) miif->
plugtypes[idx][k].get().get_sv_offset(SV, offset, sz);
567 glob_vecs.
nRegs = nRegs;
570 glob_vecs.
vecs.resize(nGVcs);
573 for (
size_t i = 0; i < glob_vecs.
vecs.size(); i++) {
578 gvec.
bogus = prmGVecs[i].bogus;
580 gvec.
imps = (
char**) calloc(nRegs,
sizeof(
char *));
581 gvec.
svNames = (
char**) calloc(nRegs,
sizeof(
char *));
582 gvec.
svSizes = (
int*) calloc(nRegs,
sizeof(
int));
583 gvec.
svOff = (
int*) calloc(nRegs,
sizeof(
int));
586 for (
int j = 0; j < nRegs; j++) {
587 if (strlen(prmGVecs[i].imp)) gvec.
imps[j] =
dupstr(prmGVecs[i].imp);
589 else if (j < param_globals::num_imp_regions)
590 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
592 gvec.
imps[j] =
dupstr(param_globals::PurkIon[j - param_globals::num_imp_regions].im);
594 else if (j < param_globals::num_imp_regions)
595 gvec.
imps[j] =
dupstr(param_globals::imp_region[j].im);
620 int num_purk_regions = 0;
621 int nRegs = param_globals::num_imp_regions + num_purk_regions;
623 alloc_gvec_data(param_globals::num_gvecs, nRegs, param_globals::gvec, GVs);
626 if (GVs->
inclPS) sample_PS_ionSVs(purk);
629 for (
unsigned int i = 0; i < GVs.
vecs.size(); i++) {
633 for (
int j = 0; j < miif->
N_IIF; j++) {
636 if (gv.
getsv[j] == NULL) {
637 log_msg(NULL, 3,
ECHO,
"\tWarning: SV(%s) not found in region %d\n", gv.
svNames[j], j);
649 MULTI_IF* pmiif = &purk->ion;
650 for (
int j = miif->
N_IIF; j < nRegs; j++) {
654 if (gv.
getsv[j] == NULL) {
655 LOG_MSG(NULL, 3,
ECHO,
"\tWarning: state variable \"%s\" not found in region %d\n", gv.
svNames[j], j);
659 RVector_dup(purk->vm_pt, &gv.orderedPS_PS);
662 RVector_dup(purk->vm_pt_over, &gv.orderedPS);
663 initialize_grid_output(grid, NULL, tmo,
intra_elec_msh, GRID_WRITE, 0., 1., gv.
units, gv.orderedPS,
664 1, gv.GVcName, -purk->npt, param_globals::output_level);
669 log_msg(NULL, 5,
ECHO,
"\tError: no state variables found for global vector %d\n", i);
670 log_msg(NULL, 5,
ECHO,
"Run bench --imp=YourModel --imp-info to get a list of all parameters.\\n");
688 for(
size_t i=0; i<gvecs.
vecs.size(); i++ ) {
697 for(
int n = 0; n<miif->
N_IIF; n++ ) {
698 if( !gv.
getsv[n] )
continue;
707 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