55 #define BOX_CENTERS_GRID false 56 #define NODE_GRID true 61 a.
x = p[0]; a.
y=p[1]; a.
z=p[2];
76 void set_axes(
float alpha_,
float beta_pr_,
float gamma_);
77 void set_bath_axes(
bool);
97 Point p(cos(alpha), sin(alpha), sin(gamma));
100 Point sp(0.0, sin(
double(beta_pr)), cos(
double(beta_pr)));
101 float lambda = -
dot(f, sp)/
dot(f, e_circ);
109 s.x = s.y = s.z = 0.0;
111 f.x = aniso_bath?1.0:0.0;
118 virtual bool inside(
Point) = 0;
120 int tag() {
return tag_; }
121 void tag(
int t) { tag_ = t; }
131 virtual bool inside(
Point p);
139 Region(ctr, bth), radius2_(r*r) {}
148 return p.
x >= p0_.x && p.
x <= p1_.x && p.
y >= p0_.y && p.
y <= p1_.y &&
149 p.
z >= p0_.z && p.
z <= p1_.z;
156 Region(origin, bth), radius2_(r*r)
157 {axis_=
normalize(dir);len_=(l==0.)?1.e36:l;}
158 virtual bool inside(
Point p );
169 float d =
dot(R, axis_);
171 return d>=0 && d<=len_ &&
mag2(R)-d*d <= radius2_;
177 Element(
int N,
const char *t):n_(N),p_(new int[N]),type_(t){}
191 Point result = ctr[p_[0]];
192 for(
int i=1; i<n_; i++ ) result = result + ctr[p_[i]];
193 return scal_X( result, 1./(
float)n_);
200 p_[0]=A; p_[1]=B; p_[2]=C; p_[3]=D; }
201 void chkNegVolume(
Point *pts);
206 Point P01 = pts[p_[1]] - pts[p_[0]];
207 Point P02 = pts[p_[2]] - pts[p_[0]];
208 Point P03 = pts[p_[3]] - pts[p_[0]];
209 double vol =
det3(P01,P02,P03);
211 std::swap(p_[0],p_[1]);
217 p_[0]=A; p_[1]=B; p_[2]=C; p_[3]=D; p_[4]=E; p_[5]=F; p_[6]=G; p_[7]=H; }
224 p_[0] = A; p_[1] = B; p_[2] = C; p_[3] = D;
232 p_[0] = A; p_[1] = B; p_[2] = C;
244 out << e.
type_ <<
" ";
245 for(
int i=0; i<e.
num()-1; i++ )
246 out << e.
p_[i] <<
" ";
247 out << e.
p_[e.
num()-1];
252 out << p.
x <<
" " << p.
y <<
" " << p.
z;
260 int read(
char *fname);
261 float lookup(
float xi);
262 int linear(
float ang_endo,
float ang_epi,
float z_endo,
float z_epi );
277 N = (z_epi-z_endo)/dz;
279 xi = (
float *)malloc(
sizeof(
float)*(N+1));
280 ang = (
float *)malloc(
sizeof(
float)*(N+1));
282 if(xi==NULL || ang==NULL) {
283 std::cerr <<
"Memory allocation failed." << std::endl;
290 float K = (ang_epi-ang_endo)/(z_epi-z_endo);
291 for(
int i=0;i<=N;i++) {
292 float z = z_endo+i*dz;
293 xi[i] = (z-z_endo)/(z_epi-z_endo)-0.5;
294 ang[i] = ang_endo + K*(z-z_endo);
303 if( !N )
return ang[0];
306 while(xi[i]<xi_ && i<N) i++;
311 return ang[i-1]+(ang[i]-ang[i-1])/(xi[i]-xi[i-1])*(xi_-xi[i-1]);
317 FILE *profile = fopen(fname,
"rt");
319 fprintf( stderr,
"Can't open transmural profile data file %s.\n", fname);
323 int err = fscanf(profile,
"%d",&N);
324 xi = (
float *)malloc(
sizeof(
float)*N);
325 ang = (
float *)malloc(
sizeof(
float)*N);
326 for(
int i=0; i<N; i++) {
327 xi[i] = (float)i/(
float)(N-1)-0.5;
328 err = fscanf(profile,
"%f",ang+i);
337 void update(
Point p );
353 if(p.
x<x_mn) x_mn = p.
x;
354 if(p.
y<y_mn) y_mn = p.
y;
355 if(p.
z<z_mn) z_mn = p.
z;
356 if(p.
x>x_mx) x_mx = p.
x;
357 if(p.
y>y_mx) y_mx = p.
y;
358 if(p.
z>z_mx) z_mx = p.
z;
365 void init(
int *_bx,
float *_res,
Point p0);
367 float z2xi(
float z,
bool nodeGrid);
368 float mn_z(
bool nodeGrid){
return nodeGrid?nodes.z_mn:bctrs.z_mn; };
369 float mx_z(
bool nodeGrid){
return nodeGrid?nodes.z_mx:bctrs.z_mx; };
382 float zd = nodeGrid?nodes.zd:bctrs.zd;
383 float z_mn = nodeGrid?nodes.z_mn:bctrs.z_mn;
388 return (z-z_mn)/zd-0.5;
396 for(
int i=0;i<3;i++) {
400 bx_inds[i][1] = bx[i]-1;
408 pc0.
x = p0.
x + res[0]/2;
409 pc0.
y = p0.
y + res[1]/2;
410 pc0.
z = p0.
z + res[2]/2;
415 p1.
x = p0.
x+bx[0]*res[0];
416 p1.
y = p0.
y+bx[1]*res[1];
417 p1.
z = p0.
z+bx[2]*res[2];
422 pc1.
x = p1.
x - res[0]/2;
423 pc1.
y = p1.
y - res[1]/2;
424 pc1.
z = p1.
z - res[2]/2;
434 nodes.xd = nodes.x_mx - nodes.x_mn;
435 nodes.yd = nodes.y_mx - nodes.y_mn;
436 nodes.zd = nodes.z_mx - nodes.z_mn;
439 bctrs.xd = bctrs.x_mx - bctrs.x_mn;
440 bctrs.yd = bctrs.y_mx - bctrs.y_mn;
441 bctrs.zd = bctrs.z_mx - bctrs.z_mn;
446 void setFiberDefs(
char *f_prof,
float fEndo,
float fEpi,
float imbr,
447 char *s_prof,
float sEndo,
float sEpi);
448 bool withSheets(
void);
468 char *s_prof,
float sEndo,
float sEpi)
470 f_Prof = strdup(f_prof);
474 s_Prof = strdup(s_prof);
482 if((f_imbr!=0.0) || (s_Endo!=0.0) || (s_Epi!=0.0) || (strcmp(s_Prof,
"")))
494 void unPrMFiberDefs(
void);
495 virtual void build_mesh(
float*,
float*,
float*,
bool *,
float*,
float,
bool,
int)=0;
496 virtual void output_boundary(
char * )=0;
498 void set_indx_bounds(
bool *sym);
499 bool chk_bath(
int i,
int j,
int k );
506 std::ofstream pt_os, elem_os, lon_os, elemc_os,
vec_os;
517 virtual void build_mesh(
float*,
float*,
float*,
bool *,
float*,
float,
bool,
int);
521 void add_tri(
int,
int,
int );
526 virtual void build_mesh(
float*,
float*,
float*,
bool *,
float*,
float,
bool,
int);
530 void add_tet(
int,
int,
int,
int );
535 virtual void build_mesh(
float*,
float*,
float*,
bool *,
float*,
float,
bool,
int);
539 void add_line(
int,
int,
int,
int );
545 return pt_os.good() && lon_os.good() && elem_os.good();
551 std::string fname(msh);
554 lon_os.open(fname.c_str());
558 pt_os.open(fname.c_str());
570 vec_os.open(fname.c_str());
583 for(
int i=0;i<3;i++) {
605 bool bth[] = {
false,
false,
false };
606 int idx[] = { i, j, k };
608 for(
int cnt=0; cnt<
dim; cnt++ )
620 param_globals::fibers.rotEndo,
621 param_globals::fibers.rotEpi,
622 param_globals::fibers.imbrication,
623 param_globals::fibers.tm_sheet_profile,
624 param_globals::fibers.sheetEndo,
625 param_globals::fibers.sheetEpi);
641 while(
region[++r] != NULL ) {
642 if(
region[r]->inside( c ) ) {
643 if(
region[r]->isbath() ) {
649 if(param_globals::first_reg)
660 elem.ax.set_bath_axes(regtype==
Anisobath);
665 elem_os <<
" " << regid << std::endl;
667 lon_os << elem.ax.fiber() <<
" " << elem.ax.sheet() << std::endl;
669 lon_os << elem.ax.fiber() << std::endl;
672 vec_os << elem.ax.fiber() << std::endl;
690 float pert,
bool aniso_bath,
int periodic_bc)
698 for(
int i=0; i<3; i++ ) {
699 bnx[i] = (int)(x[i]/res[i]);
700 tnx[i] = (int)(tissue[i]/res[i]);
705 pt0.
x = -tnx[0]*res[0]/2 + x0[0];
709 pb0.
x = sym[0]?pt0.
x-(bnx[0]-tnx[0])*res[0]/2:pt0.
x+x0[0];
725 std::cout <<
"Number of points: " <<
npt << std::endl;
729 for(
int i=0; i<=bnx[0]; i++ ) {
733 pt[
npt].
x += ((double)random()/(double)RAND_MAX)*pert*res[0];
739 int num_in_layer = (bnx[0]+1);
740 elem_os << bnx[0] << std::endl;
741 std::cout <<
"Number of linear elements: " << bnx[0] << std::endl;
743 for(
int i=0; i<bnx[0]; i++ ) {
774 float pert,
bool aniso_bath,
int periodic_bc)
782 for(
int i=0; i<3; i++ ) {
783 bnx[i] = (int)(x[i]/res[i]);
784 tnx[i] = (int)(tissue[i]/res[i]);
789 pt0.
x = -tnx[0]*res[0]/2 + x0[0];
790 pt0.
y = -tnx[1]*res[1]/2 + x0[1];
793 pb0.
x = sym[0]?pt0.
x-(bnx[0]-tnx[0])*res[0]/2:pt0.
x+ x0[0];
794 pb0.
y = sym[0]?pt0.
y-(bnx[0]-tnx[0])*res[0]/2:pt0.
y+ x0[1];
805 npt = (bnx[0]+1)*(bnx[1]+1);
806 std::cout <<
"Number of points: " <<
npt << std::endl;
810 for(
int j=0; j<=bnx[1]; j++ )
811 for(
int i=0; i<=bnx[0]; i++ ) {
812 pt[
npt].
assign<
double>(x0[0]+i*res[0], x0[1]+j*res[1], 0);
814 if( j && j!=bnx[1] && i && i!=bnx[0] ) {
815 pt[
npt].
x += ((double)random()/(double)RAND_MAX)*pert*res[0];
816 pt[
npt].
y += ((double)random()/(double)RAND_MAX)*pert*res[1];
824 if( (periodic_bc&1) == 1 )
825 nper_cnnx += bnx[1]+1;
826 if( (periodic_bc&2) == 2 )
827 nper_cnnx += bnx[0]+1;
829 int num_in_layer = (bnx[0]+1)*(bnx[1]+1);
831 if(param_globals::tri2D) {
832 elem_os << 2*bnx[0]*bnx[1]+nper_cnnx << std::endl;
833 elemc_os << 2*bnx[0]*bnx[1]+nper_cnnx << std::endl;
834 std::cout <<
"Number of triangles: " << 2*bnx[0]*bnx[1] << std::endl;
836 elem_os << bnx[0]*bnx[1]+nper_cnnx << std::endl;
837 elemc_os << bnx[0]*bnx[1]+nper_cnnx << std::endl;
838 std::cout <<
"Number of quadrilaterals: " << bnx[0]*bnx[1] << std::endl;
841 std::cout <<
"Number of periodic connections: " << nper_cnnx << std::endl;
849 std::cout <<
"Using orthotropic fiber setup." << std::endl;
851 std::cout <<
"Using transversely isotropic fiber setup." << std::endl;
853 for(
int j=0; j<bnx[1]; j++ ) {
855 for(
int i=0; i<bnx[0]; i++ ) {
856 p1 = j*(bnx[0]+1) + i;
858 p3 = (j+1)*(bnx[0]+1) + i;
865 if( param_globals::tri2D ) {
867 Triangle t1(p1, p2, p3), t2(p2, p4, p3);
871 Triangle t1(p1, p2, p4), t2(p1, p4, p3);
883 if( (periodic_bc&1) == 1 ) {
884 for(
int i=0; i<=bnx[1]; i++ ) {
885 Line l( i*(bnx[0]+1), (i+1)*(bnx[0]+1)-1 );
886 elem_os << l <<
" " << param_globals::periodic_tag<<std::endl;
887 lon_os <<
"1 0 0" << std::endl;
890 if( (periodic_bc&2) == 2 ) {
891 for(
int i=0; i<=bnx[0]; i++ ) {
892 Line l( i, (bnx[0]+1)*(bnx[1])+i );
893 elem_os << l <<
" " << param_globals::periodic_tag+1 << std::endl;
894 lon_os <<
"0 1 0" << std::endl;
916 float pert,
bool aniso_bath,
int periodic_bc)
919 int p1, p2, p3, p4, p5, p6, p7,p8;
924 for(
int i=0; i<3; i++ ) {
925 bnx[i] = (int)(x[i]/res[i]);
926 tnx[i] = (int)(tissue[i]/res[i]);
931 pt0 = {x0[0],x0[1],x0[2]};
933 pb0.
x = sym[0]?pt0.
x-(bnx[0]-tnx[0])*res[0]/2:pt0.
x + x0[0];
934 pb0.
y = sym[1]?pt0.
y-(bnx[1]-tnx[1])*res[1]/2:pt0.
y + x0[1];
935 pb0.
z = sym[2]?pt0.
z-(bnx[2]-tnx[2])*res[2]/2:pt0.
z + x0[2];
947 std::cout <<
"Reading transmural fiber rotation profile from " <<
f_def.
f_name() << std::endl;
955 std::cout <<
"Reading transmural sheet profile from " <<
f_def.
s_name() << std::endl;
963 npt = (bnx[0]+1)*(bnx[1]+1)*(bnx[2]+1);
964 std::cout <<
"Number of points: " <<
npt << std::endl;
968 for(
int k=0; k<=bnx[2]; k++ )
969 for(
int j=0; j<=bnx[1]; j++ )
970 for(
int i=0; i<=bnx[0]; i++ ) {
971 pt[
npt] = {x0[0]+i*res[0], x0[1]+j*res[1], x0[2]+k*res[2]};
972 if( k && k!=bnx[2] && j && j!=bnx[1] && i && i!=bnx[0] ) {
973 pt[
npt].
x += ((double)random()/(double)RAND_MAX)*pert*res[0];
974 pt[
npt].
y += ((double)random()/(double)RAND_MAX)*pert*res[1];
975 pt[
npt].
z += ((double)random()/(double)RAND_MAX)*pert*res[2];
981 int num_in_layer = (bnx[0]+1)*(bnx[1]+1);
982 if(!param_globals::Elem3D) {
983 elem_os << 5*bnx[0]*bnx[1]*bnx[2] << std::endl;
984 elemc_os << 5*bnx[0]*bnx[1]*bnx[2] << std::endl;
985 std::cout <<
"Number of Tetrahedra: " << 5*bnx[0]*bnx[1]*bnx[2] << std::endl;
988 elem_os << bnx[0]*bnx[1]*bnx[2] << std::endl;
989 elemc_os << bnx[0]*bnx[1]*bnx[2] << std::endl;
990 std::cout <<
"Number of Hexahedra: " << bnx[0]*bnx[1]*bnx[2] << std::endl;
996 std::cout <<
"Using orthotropic fiber setup." << std::endl;
998 std::cout <<
"Using transversely isotropic fiber setup." << std::endl;
1001 for(
int k=0; k<bnx[2]; k++ ) {
1003 for(
int j=0; j<bnx[1]; j++ ) {
1006 if(j && !(bnx[0]%2) )
1009 for(
int i=0; i<bnx[0]; i++ ) {
1010 p1 = k*num_in_layer + j*(bnx[0]+1) + i;
1012 p3 = k*num_in_layer + (j+1)*(bnx[0]+1) + i;
1014 p5 = (k+1)*num_in_layer + j*(bnx[0]+1) + i;
1016 p7 = (k+1)*num_in_layer + (j+1)*(bnx[0]+1) + i;
1023 if(!param_globals::Elem3D) {
1056 Hexahedron h1(p5, p7, p8, p6, p1, p2, p4, p3);
1073 float tsize[3], x0[3], t0[3];
1077 status = param(PARAMETERS, &argc, argv );
1078 if( status==PrMERROR||status==PrMFATAL )
1079 fprintf( stderr,
"\n*** Error reading parameters\n\n");
1080 else if( status==PrMQUIT )
1081 fprintf( stderr,
"\n*** Quitting by user's request\n\n");
1082 }
while (status==PrMERROR);
1083 if(status&&PrMERROR) exit( status );
1086 for(
int i=0; i<3; i++ ) {
1087 param_globals::size[i] *=
CM2UM;
1088 param_globals::bath[i] *=
CM2UM;
1089 param_globals::center[i] *=
CM2UM;
1092 if(param_globals::size[i]==0.) param_globals::bath[i] = 0.0;
1093 if(param_globals::bath[i]>=0) {
1094 tsize[i] = param_globals::size[i]+param_globals::bath[i];
1096 x0[i] = -0.5*param_globals::size[i]+param_globals::center[i];
1099 tsize[i] = param_globals::size[i]-2*param_globals::bath[i];
1101 x0[i] = -0.5*tsize[i]+param_globals::center[i];
1107 ctr.
x = param_globals::center[0];
1108 ctr.
y = param_globals::center[1];
1109 ctr.
z = param_globals::center[2];
1111 RegionDef* regdef = param_globals::regdef;
1113 for (
int r = 0; r < param_globals::numRegions; r++ ) {
1115 if( !param_globals::size[2]) p0.z = 0;
1117 switch(regdef[r].type) {
1119 if( !param_globals::size[2] ) p1.
z = 0;
1122 if( p0.x>p1.x ) std::swap( p0.x, p1.x );
1123 if( p0.y>p1.y ) std::swap( p0.y, p1.y );
1124 if( p0.z>p1.z ) std::swap( p0.z, p1.z );
1125 region[r] =
new BlockRegion( p0, p1, regdef[r].bath );
1128 regdef[r].rad *=
CM2UM;
1133 if( !param_globals::size[2] )
1137 regdef[r].rad *=
CM2UM;
1138 regdef[r].cyllen *=
CM2UM;
1140 regdef[r].cyllen, regdef[r].bath );
1143 region[r]->
tag(regdef[r].tag);
1145 region[param_globals::numRegions] = NULL;
1149 if( !param_globals::size[1] && !param_globals::size[2] )
1150 grid =
new Grid1D( param_globals::mesh, region );
1151 else if( !param_globals::size[2] )
1152 grid =
new Grid2D( param_globals::mesh, region );
1154 grid =
new Grid3D( param_globals::mesh, region );
1159 grid->
build_mesh(x0, tsize, param_globals::size, symbath, param_globals::resolution,
1160 param_globals::perturb, param_globals::anisoBath, param_globals::periodic);
1164 std::cerr <<
"ERROR:" << std::endl;
1165 std::cerr <<
"Could not open mesh files " << param_globals::mesh <<
".* for writing!" << std::endl;
1166 std::cerr <<
"Aborting!" << std::endl;
constexpr T min(T a, T b)
CylindricalRegion(Point origin, Point dir, float r, float l, int bth)
virtual void build_mesh(float *, float *, float *, bool *, float *, float, bool, int)
void set_indx_bounds(bool *sym)
Point p_assign_array(float *p)
virtual void output_boundary(char *fn)
Grid1D(char *m, Region **r)
constexpr T max(T a, T b)
float mx_z(bool nodeGrid)
Grid2D(char *m, Region **r)
virtual bool inside(Point p)
V det3(const vec3< V > &a, const vec3< V > &b, const vec3< V > &c)
vec3< V > normalize(vec3< V > a)
virtual void build_mesh(float *, float *, float *, bool *, float *, float, bool, int)
void add_element(Element &, region_t)
virtual void build_mesh(float *, float *, float *, bool *, float *, float, bool, int)=0
std::ostream & operator<<(std::ostream &out, Element &e)
Grid3D(char *m, Region **r)
V mag2(const vec3< V > &vect)
int main(int argc, char *argv[])
void chkNegVolume(Point *pts)
bool chk_bath(int i, int j, int k)
int linear(float ang_endo, float ang_epi, float z_endo, float z_epi)
float z2xi(float z, bool nodeGrid)
virtual bool inside(Point p)
void setFiberDefs(char *f_prof, float fEndo, float fEpi, float imbr, char *s_prof, float sEndo, float sEpi)
Quadrilateral(int A, int B, int C, int D)
Hexahedron(int A, int B, int C, int D, int E, int F, int G, int H)
virtual bool inside(Point p)
virtual void output_boundary(char *fn)
void assign(S ix, S iy, S iz)
SphericalRegion(Point ctr, float r, int bth)
void init(int *_bx, float *_res, Point p0)
V dot(const vec3< V > &p1, const vec3< V > &p2)
vec3< V > scal_X(const vec3< V > &a, S k)
void set_axes(float alpha_, float beta_pr_, float gamma_)
virtual void output_boundary(char *fn)
Triangle(int A, int B, int C)
Tetrahedron(int A, int B, int C, int D)
virtual void build_mesh(float *, float *, float *, bool *, float *, float, bool, int)
Element(int N, const char *t)
V dist_2(const vec3< V > &p1, const vec3< V > &p2)
Grid(char *, Region **, int)
BlockRegion(Point p0, Point p, int bth)
void unPrMFiberDefs(void)
float mn_z(bool nodeGrid)