Commit 93e7ae71 authored by Jonathan Lambrechts's avatar Jonathan Lambrechts
Browse files

use material/boundary string names

parent d6ce95e8
Pipeline #4897 passed with stage
in 27 seconds
......@@ -34,6 +34,7 @@ def _write_array(f,anc,attr) :
np.dtype('<i8'):b"Int64",
np.dtype('<f4'):b"Float32",
np.dtype('<f8'):b"Float64",
np.dtype('uint8'):b"UInt8",
np.dtype('uint64'):b"UInt64"
}[a.dtype]
f.write(b'<DataArray %s type="%s" format="binary">\n'%(attr,tname))
......@@ -44,7 +45,7 @@ def _write_array(f,anc,attr) :
def _read_array(a) :
raw = a.text.strip()
typename = a.attrib["type"]
dtype = {"Float64":np.float64,"Float32":np.float32,"Int64":np.int64,"Int32":np.int32,"UInt64":np.uint64}[typename]
dtype = {"UInt8":np.uint8,"Float64":np.float64,"Float32":np.float32,"Int64":np.int64,"Int32":np.int32,"UInt64":np.uint64}[typename]
_,n,_,s = struct.unpack("iiii",b64decode(raw[:24]))
data = zlib.decompress(b64decode(raw[24:24-(-s//3)*4]))
nc,nt = -1,-1
......@@ -196,3 +197,15 @@ def write_multipart(basename,parts,i,t,reset_index=None):
f.write(b'</vtkMultiBlockDataSet>\n');
f.write(b'</VTKFile>\n');
_write_index(basename+".pvd",os.path.basename(filename),i,t,reset_index)
def string_array_encode(a) :
joined = b"".join(a)
fmt = b"i%ii%is"%(len(a),len(joined))
r = struct.pack(fmt,len(a),*(len(i) for i in a),joined)
return np.array(list((i for i in r)),dtype="u1").reshape([-1,1])
def string_array_decode(e) :
n = struct.unpack("i",e[:4])[0]
l = struct.unpack("%ii"%n,e[4:4+4*n])
return struct.unpack("".join("%is"%i for i in l), e[4+n*4:])
......@@ -133,12 +133,19 @@ class ParticleProblem :
def disk_tag(self):
return self._get_idx("DiskTag")
def disk_material(self):
return self._get_idx("DiskMaterial")
def segments(self):
return self._get_matrix("Segment",3*self._dim+(1 if self._friction_enabled else 0))
def segment_tag(self):
return self._get_idx("SegmentTag")
def segment_material(self):
return self._get_idx("SegmentMaterial")
def triangles(self):
if self._dim == 3 :
return self._get_matrix("Triangle",12)
......@@ -151,6 +158,12 @@ class ParticleProblem :
else :
return np.array([],np.int32)
def triangle_material(self):
if self._dim == 3 :
return self._get_idx("TriangleMaterial")
else :
return np.array([],np.int32)
def set_boundary_velocity(self, tag, v) :
self._lib.particleProblemGetTagId.restype = c_size_t
tag = self._lib.particleProblemGetTagId(self._p, tag.encode())
......@@ -173,10 +186,9 @@ class ParticleProblem :
assert self._friction_enabled
self._lib.particleProblemSetFrictionRelaxation(self._p,c_double(relaxation))
def add_friction(self, static) :
def set_friction_coefficient(self, mu, mat0="default",mat1="default") :
assert self._friction_enabled
arg_type = c_double*len(static)
self._lib.particleProblemAddFriction(self._p, arg_type(*static),len(static))
self._lib.particleProblemSetFrictionCoefficient(self._p, c_double(mu), mat0.encode(),mat1.encode())
def iterate(self, dt, forces,tol=1e-8) :
"""Compute iteratively the set of velocities that respect the non-interpenetration constrain.
......@@ -198,12 +210,15 @@ class ParticleProblem :
else :
omega = np.zeros((v.shape[0],1))
x = self.position()
tag = self._get_idx("ParticleTag").reshape(-1,1)
material = self._get_idx("ParticleMaterial").reshape(-1,1)
if self._dim == 2 :
v = np.insert(v,self._dim,0,axis=1)
x = np.insert(x,self._dim,0,axis=1)
data = [("Mass",self.mass()), ("Radius",self.r()),("Velocity",v),("Omega",omega),("Tag",tag)]
VTK.write(odir+"/particles",i,t,None,x,data,vtktype="vtp")
data = [("Mass",self.mass()), ("Radius",self.r()),("Velocity",v),("Omega",omega),("Material",material)]
nmat = self._lib.particleProblemNMaterial(self._p)
self._lib.particleProblemGetMaterialTagName.restype = c_char_p
tags = list([self._lib.particleProblemGetMaterialTagName(self._p,i) for i in range(nmat)])
VTK.write(odir+"/particles",i,t,None,x,data,vtktype="vtp",field_data=[(b"MaterialNames",VTK.string_array_encode(tags))])
xdisk = self._get_matrix("Disk",2*self._dim+(2 if self._friction_enabled else 1))[:,:self._dim]
nd = xdisk.shape[0]
......@@ -217,8 +232,12 @@ class ParticleProblem :
connectivity = np.arange(0,x.shape[0],dtype=np.int32)
types = np.repeat(np.array([1,3,5],dtype=np.int32),[nd,ns,nt])
offsets = np.cumsum(np.repeat([1,2,3],[nd,ns,nt]),dtype=np.int32)
tags = np.array(np.hstack([self.disk_tag(),self.segment_tag(),self.triangle_tag()]),dtype=np.float64)
VTK.write(odir+"/boundaries",i,t,(types,connectivity,offsets),x,cell_data=[("Tag",tags.reshape([-1,1]))])
tags = np.array(np.hstack([self.disk_tag(),self.segment_tag(),self.triangle_tag()]))
materials = np.array(np.hstack([self.disk_material(),self.segment_material(),self.triangle_material()]))
ntagname = self._lib.particleProblemNTag(self._p)
self._lib.particleProblemGetTagName.restype = c_char_p
tagnames = list([self._lib.particleProblemGetTagName(self._p,i) for i in range(ntagname)])
VTK.write(odir+"/boundaries",i,t,(types,connectivity,offsets),x,cell_data=[("Tag",tags.reshape([-1,1])),("Material",materials.reshape([-1,1]))],field_data=[(b"TagNames",VTK.string_array_encode(tagnames))])
self._lib.particleProblemContactN.restype = c_size_t
fdata = []
......@@ -238,31 +257,38 @@ class ParticleProblem :
def read_vtk(self,dirname,i) :
"""Read an existing output file to set the particle data."""
x,_,d,cdata,fdata = VTK.read(dirname+"/particles_%05d.vtp"%i)
matnames = VTK.string_array_decode(fdata["MaterialNames"])
matmap = {}
for j,n in enumerate(matnames) :
matmap[j] = self._lib.particleProblemGetMaterialTagId(self._p,n)
partmat =np.vectorize(matmap.get)(d["Material"])
self._lib.particleProblemClearParticles(self._p)
self._lib.particleProblemAddParticles(self._p,c_int(x.shape[0]),
_np2c(x[:,:self._dim]), _np2c(d["Mass"]), _np2c(d["Radius"]), _np2c(d["Velocity"][:,:self._dim]),_np2c(d["Omega"]),_np2c(d["Tag"]))
_np2c(x[:,:self._dim]), _np2c(d["Mass"]), _np2c(d["Radius"]), _np2c(d["Velocity"][:,:self._dim]),_np2c(d["Omega"]),_np2c(partmat,dtype=np.int32))
x,cells,d,cdata,fdata = VTK.read(dirname+"/boundaries_%05d.vtu"%i)
tagnames = VTK.string_array_decode(fdata["TagNames"])
tagmap = {}
for j,n in enumerate(tagnames) :
tagmap[j] = self._lib.particleProblemGetTagId(self._p,n)
self._lib.particleProblemClearBoundaries(self._p)
offsets = np.hstack([[0],cells["offsets"]])
el = cells["connectivity"]
tags = cdata["Tag"]
tags = np.vectorize(tagmap.get)(cdata["Tag"])
materials = cdata["Material"]
for idx in np.where(cells["types"] == 1)[0] :
x0 = x[el[offsets[idx]],:self._dim]
t = int(tags[idx,0])
self._lib.particleProblemAddBoundaryDiskTagId(self._p, self._coord_type(*x0), c_double(0.), c_int(t))
self._lib.particleProblemAddBoundaryDiskTagId(self._p, self._coord_type(*x0), c_double(0.), c_int(tags[idx,0]), c_int(materials[idx,0]))
for idx in np.where(cells["types"] == 3)[0] :
x0 = x[el[offsets[idx]],:self._dim]
x1 = x[el[offsets[idx]+1],:self._dim]
t = int(tags[idx,0])
self._lib.particleProblemAddBoundarySegmentTagId(self._p, self._coord_type(*x0), self._coord_type(*x1), c_int(t))
self._lib.particleProblemAddBoundarySegmentTagId(self._p, self._coord_type(*x0), self._coord_type(*x1), c_int(tags[idx,0]), c_int(materials[idx,0]))
for idx in np.where(cells["types"] == 5)[0] :
x0 = x[el[offsets[idx]],:self._dim]
x1 = x[el[offsets[idx]+1],:self._dim]
x2 = x[el[offsets[idx]+2],:self._dim]
t = int(tags[idx,0])
self._lib.particleProblemAddBoundaryTriangleTagId(self._p, self._coord_type(*x0), self._coord_type(*x1), self._coord_type(*x2), c_int(t))
self._lib.particleProblemAddBoundaryTriangleTagId(self._p, self._coord_type(*x0), self._coord_type(*x1), self._coord_type(*x2), c_int(tags[idx,0]), c_int(materials[idx,0]))
_,_,_,_,fdata = VTK.read(dirname+"/contacts_%05d.vtp"%i)
ks = ("particle_particle","particle_disk","particle_segment","particle_triangle")
v = np.vstack([fdata[k] for k in ks])
......@@ -272,19 +298,19 @@ class ParticleProblem :
t = np.repeat([0,1,2,3],[fdata[k].shape[0] for k in ks])
self._lib.particleProblemSetContacts(self._p,c_int(t.shape[0]),_np2c(o,np.uint64),_np2c(v),_np2c(t,np.int32))
def add_boundary_disk(self, x0, r, tag) :
def add_boundary_disk(self, x0, r, tag, material="default") :
self._lib.particleProblemAddBoundaryDisk.restype = c_size_t
return self._lib.particleProblemAddBoundaryDisk(self._p, self._coord_type(*x0), c_double(r), tag.encode())
return self._lib.particleProblemAddBoundaryDisk(self._p, self._coord_type(*x0), c_double(r), tag.encode(),material.encode())
def add_boundary_segment(self, x0, x1, tag) :
def add_boundary_segment(self, x0, x1, tag, material="default") :
self._lib.particleProblemAddBoundarySegment.restype = c_size_t
return self._lib.particleProblemAddBoundarySegment(self._p, self._coord_type(*x0), self._coord_type(*x1), tag.encode())
return self._lib.particleProblemAddBoundarySegment(self._p, self._coord_type(*x0), self._coord_type(*x1), tag.encode(),material.encode())
def add_boundary_triangle(self, x0, x1, x2, tag) :
def add_boundary_triangle(self, x0, x1, x2, tag, material="default") :
if self._dim != 3 :
raise NameError("Triangle boundaries only available in 3D")
self._lib.particleProblemAddBoundaryTriangle.restype = c_size_t
return self._lib.particleProblemAddBoundaryTriangle(self._p, self._coord_type(*x0), self._coord_type(*x1), self._coord_type(*x2), tag.encode())
return self._lib.particleProblemAddBoundaryTriangle(self._p, self._coord_type(*x0), self._coord_type(*x1), self._coord_type(*x2), tag.encode(),material.encode())
def add_particle(self, x, r, m, tag):
"""Add a particle in the particle container.
......@@ -295,9 +321,9 @@ class ParticleProblem :
m -- particle mass
tag -- particle tag
"""
self._lib.particleProblemAddParticle(self._p, self._coord_type(*x), c_double(r), c_double(m), c_int(tag))
self._lib.particleProblemAddParticle(self._p, self._coord_type(*x), c_double(r), c_double(m), tag.encode())
def load_msh_boundaries(self, filename, tags, shift=None) :
def load_msh_boundaries(self, filename, tags, shift=None,material="default") :
"""Load the numerical domain and set the physical boundaries the particles cannot go through.
Keyword arguments:
......@@ -321,10 +347,10 @@ class ParticleProblem :
if v[3] in self._addv :
continue
self._addv.add(v[3])
self.add_boundary_disk((v[0] + shift[0], v[1] + shift[1]), 0.000, stag)
self.add_boundary_disk((v[0] + shift[0], v[1] + shift[1]), 0.000, stag,material)
v0 = el.vertices[1]
v1 = el.vertices[0]
self.add_boundary_segment((v0[0] + shift[0], v0[1] + shift[1]), (v1[0] + shift[0], v1[1] + shift[1]), stag)
self.add_boundary_segment((v0[0] + shift[0], v0[1] + shift[1]), (v1[0] + shift[0], v1[1] + shift[1]), stag,material)
else :
self._adde = set()
pnum = [m.getPhysicalNumber(2, i) for i in tags]
......@@ -338,14 +364,14 @@ class ParticleProblem :
v0 = el.vertices[j]
if not v0[3] in self._addv :
self._addv.add(v0[3])
self.add_boundary_disk((v0[0]+shift[0],v0[1]+shift[1],v0[2]+shift[2]),0.,stag)
self.add_boundary_disk((v0[0]+shift[0],v0[1]+shift[1],v0[2]+shift[2]),0.,stag,material)
v1 = el.vertices[(j+1)%3]
if (not (v0[3],v1[3]) in self._adde) and (not (v1[3],v0[3]) in self._adde) :
self._adde.add((v0[3],v1[3]))
self.add_boundary_segment(
(v0[0]+shift[0],v0[1]+shift[1],v0[2]+shift[2]),
(v1[0]+shift[0],v1[1]+shift[1],v1[2]+shift[2]),
stag)
stag,material)
v0 = el.vertices[1]
v1 = el.vertices[0]
......@@ -354,4 +380,4 @@ class ParticleProblem :
(v0[0]+shift[0],v0[1]+shift[1],v0[2]+shift[2]),
(v1[0]+shift[0],v1[1]+shift[1],v1[2]+shift[2]),
(v2[0]+shift[0],v2[1]+shift[1],v2[2]+shift[2]),
stag)
stag,material)
......@@ -42,8 +42,10 @@ struct _ParticleProblem{
Contact *contacts;
double *position, *velocity, *externalForces;
Disk *disks;
char **tagname;
int *diskTag, *segmentTag, *particleTag;
char **tagname, **materialName;
int *diskTag, *segmentTag;
int *diskMaterial, *segmentMaterial;
int *particleMaterial;
Segment *segments;
#if FRICTION_ENABLED
double *omega;
......@@ -53,6 +55,7 @@ struct _ParticleProblem{
#if DIMENSION == 3
Triangle *triangles;
int *triangleTag;
int *triangleMaterial;
#endif
int use_queue;
};
......@@ -138,9 +141,11 @@ static void diskBoundingBox(const Disk *d, double *pmin, double *pmax) {
}
}
size_t particleProblemAddBoundaryDiskTagId(ParticleProblem *p, const double x[DIMENSION], double r, size_t tag) {
size_t particleProblemAddBoundaryDiskTagId(ParticleProblem *p, const double x[DIMENSION], double r, int tag, int materialTag) {
Disk *d = vectorPush(&p->disks);
*vectorPush(&p->diskTag) = tag;
*vectorPush(&p->diskMaterial) = materialTag;
d->r = r;
#ifdef FRICTION_ENABLED
d->vt = 0;
......@@ -152,8 +157,8 @@ size_t particleProblemAddBoundaryDiskTagId(ParticleProblem *p, const double x[DI
return vectorSize(p->disks) - 1;
}
size_t particleProblemAddBoundaryDisk(ParticleProblem *p, const double x[DIMENSION], double r, const char *tag) {
return particleProblemAddBoundaryDiskTagId(p, x, r, particleProblemGetTagId(p, tag));
size_t particleProblemAddBoundaryDisk(ParticleProblem *p, const double x[DIMENSION], double r, const char *tag, const char *materialTag) {
return particleProblemAddBoundaryDiskTagId(p,x,r,particleProblemGetTagId(p,tag),particleProblemGetMaterialTagId(p,materialTag));
}
static int diskInitContact(size_t id, const Disk *d, size_t particle, const Particle *p, double *x, double alert, Contact *c) {
......@@ -255,9 +260,10 @@ struct _Triangle {
double v[DIMENSION];
};
void particleProblemAddBoundaryTriangleTagId(ParticleProblem *p, const double x0[3], const double x1[3], const double x2[3], size_t tag) {
void particleProblemAddBoundaryTriangleTagId(ParticleProblem *p, const double x0[3], const double x1[3], const double x2[3], int tag, int materialTag) {
Triangle *t = vectorPush(&p->triangles);
*vectorPush(&p->triangleTag) = tag;
*vectorPush(&p->triangleMaterial) = materialTag;
for (int i = 0; i < DIMENSION; ++i) {
t->p[0][i] = x0[i];
t->p[1][i] = x1[i];
......@@ -266,8 +272,8 @@ void particleProblemAddBoundaryTriangleTagId(ParticleProblem *p, const double x0
}
}
void particleProblemAddBoundaryTriangle(ParticleProblem *p, const double x0[3], const double x1[3], const double x2[3], const char *tag) {
return particleProblemAddBoundaryTriangleTagId(p, x0, x1, x2, particleProblemGetTagId(p, tag));
void particleProblemAddBoundaryTriangle(ParticleProblem *p, const double x0[3], const double x1[3], const double x2[3], const char *tag, const char *material) {
return particleProblemAddBoundaryTriangleTagId(p, x0, x1, x2, particleProblemGetTagId(p, tag), particleProblemGetMaterialTagId(p, material));
}
static void triangleBoundingBox(const Triangle *t, double *pmin, double *pmax) {
......@@ -340,6 +346,12 @@ static int triangleInitContact(size_t id, const Triangle *t, size_t particle, co
#endif
#ifdef FRICTION_ENABLED
static double particleProblemGetMu(const ParticleProblem *p, int mat0, int mat1) {
return p->mu[mat0*particleProblemNMaterial(p)+mat1];
}
#endif
static int contactParticleParticleSolve(Contact *c, ParticleProblem *p, double dt, double tol) {
double vn = c->dv;
for (int i = 0; i<DIMENSION; ++i)
......@@ -357,8 +369,7 @@ static int contactParticleParticleSolve(Contact *c, ParticleProblem *p, double d
(p->velocity[c->o0*2+1]-p->velocity[c->o1*2+1])*t[1]+
p->omega[c->o0]*p->particles[c->o0].r +
p->omega[c->o1]*p->particles[c->o1].r;
int index = p->particleTag[c->o0]*vectorSize(p->mu) + p->particleTag[c->o1];
double mu = p->mu[index];
const double mu = particleProblemGetMu(p,p->particleMaterial[c->o0],p->particleMaterial[c->o1]);
if(vt>(7./2.)*mu*(dp)){
ct = p->friction_relaxation*mu*(dp);
}
......@@ -410,8 +421,7 @@ static int contactParticleDiskSolve(Contact *c, ParticleProblem *p, double dt, d
p->velocity[c->o1 * DIMENSION+1]*t[1]+
p->omega[c->o1]*p->particles[c->o1].r+
p->disks[c->o0].vt;
int index = (p->particleTag[c->o1]+1)*vectorSize(p->mu) -1;
double mu = p->mu[index];
const double mu = particleProblemGetMu(p,p->particleMaterial[c->o1],p->diskMaterial[c->o0]);
double ct = 0;
if(vt>(7./2.)*mu*dp){
ct = p->friction_relaxation*mu*dp;
......@@ -457,8 +467,7 @@ static int contactParticleSegmentSolve(Contact *c, ParticleProblem *p, double dt
p->velocity[c->o1*DIMENSION +1]*t[1]+
p->omega[c->o1]*p->particles[c->o1].r+
p->segments[c->o0].vt;
int index = (p->particleTag[c->o1]+1)*vectorSize(p->mu) -1;
double mu = p->mu[index];
const double mu = particleProblemGetMu(p,p->particleMaterial[c->o1],p->segmentMaterial[c->o0]);
double ct = 0;
if(vt>(7./2.)*mu*dp){
ct = p->friction_relaxation*mu*dp;
......@@ -838,7 +847,6 @@ static void _particleProblemGenContacts(ParticleProblem *p, const double alert)
t[0] = c->n[1];
t[1] = - c->n[0];
c->ct = cold->ct;
int index = p->particleTag[c->o0]*vectorSize(p->mu) + p->particleTag[c->o1];
coordAdd(&p->velocity[c->o0 * DIMENSION], -c->ct*c->a0, t);
coordAdd(&p->velocity[c->o1 * DIMENSION], c->ct*c->a1, t);
p->omega[c->o0] -= c->In0*(c->ct);
......@@ -867,7 +875,6 @@ static void _particleProblemGenContacts(ParticleProblem *p, const double alert)
t[0] = c->n[1];
t[1] = - c->n[0];
c->ct = cold->ct;
int index = (p->particleTag[c->o1]+1)*vectorSize(p->mu) -1;
coordAdd(&p->velocity[c->o1 * DIMENSION], -c->ct*c->a1, t);
p->omega[c->o1] -= c->In1*(c->ct);
#endif
......@@ -892,7 +899,6 @@ static void _particleProblemGenContacts(ParticleProblem *p, const double alert)
t[0] = c->n[1];
t[1] = -c->n[0];
c->ct = cold->ct;
int index = (p->particleTag[c->o1]+1)*vectorSize(p->mu)-1;
coordAdd(&p->velocity[c->o1 * DIMENSION], -c->ct*c->a1, t);
p->omega[c->o1] -= c->In1*(c->ct);
#endif
......@@ -1110,9 +1116,10 @@ void particleProblemIterate(ParticleProblem *p, double alert, double dt, double
#endif
}
size_t particleProblemAddBoundarySegmentTagId(ParticleProblem *p, const double x0[DIMENSION], const double x1[DIMENSION], size_t tag) {
size_t particleProblemAddBoundarySegmentTagId(ParticleProblem *p, const double x0[DIMENSION], const double x1[DIMENSION], int tag, int materialTag) {
Segment *s = vectorPush(&p->segments);
*vectorPush(&p->segmentTag) = tag;
*vectorPush(&p->segmentMaterial) = materialTag;
for (int i = 0; i < DIMENSION; ++i) {
s->p[0][i] = x0[i];
s->p[1][i] = x1[i];
......@@ -1124,11 +1131,11 @@ size_t particleProblemAddBoundarySegmentTagId(ParticleProblem *p, const double x
return vectorSize(p->segments) - 1;
}
size_t particleProblemAddBoundarySegment(ParticleProblem *p, const double x0[DIMENSION], const double x1[DIMENSION], const char *tag) {
return particleProblemAddBoundarySegmentTagId(p, x0, x1, particleProblemGetTagId(p, tag));
size_t particleProblemAddBoundarySegment(ParticleProblem *p, const double x0[DIMENSION], const double x1[DIMENSION], const char *tag, const char *material) {
return particleProblemAddBoundarySegmentTagId(p, x0, x1, particleProblemGetTagId(p, tag),particleProblemGetMaterialTagId(p, material));
}
void particleProblemAddParticle(ParticleProblem *p, const double x[DIMENSION], double r, double m, int tag) {
void particleProblemAddParticleMaterialTagId(ParticleProblem *p, const double x[DIMENSION], double r, double m, int tag) {
size_t n = vectorSize(p->particles);
Particle *particle = vectorPush(&p->particles);
particle->r = r;
......@@ -1136,7 +1143,7 @@ void particleProblemAddParticle(ParticleProblem *p, const double x[DIMENSION], d
vectorPushN(&p->position, DIMENSION);
vectorPushN(&p->velocity, DIMENSION);
vectorPushN(&p->externalForces, DIMENSION);
vectorPushN(&p->particleTag,1);
vectorPushN(&p->particleMaterial,1);
for (int i = 0; i < DIMENSION; ++i) {
p->position[n * DIMENSION + i] = x[i];
p->velocity[n * DIMENSION + i] = 0;
......@@ -1146,14 +1153,19 @@ void particleProblemAddParticle(ParticleProblem *p, const double x[DIMENSION], d
vectorPushN(&p->omega,1);
p->omega[n] = 0.0;
#endif
p->particleTag[n] = tag;
p->particleMaterial[n] = tag;
}
void particleProblemAddParticle(ParticleProblem *p, const double x[DIMENSION], double r, double m, const char *material) {
particleProblemAddParticleMaterialTagId(p,x,r,m,particleProblemGetMaterialTagId(p,material));
}
#ifdef FRICTION_ENABLED
void particleProblemAddFriction(ParticleProblem *p, double *stat, int len) {
vectorPushN(&p->mu, len);
for (int i = 0; i < len; ++i) {
p->mu[i] = stat[i];
}
void particleProblemSetFrictionCoefficient(ParticleProblem *p, double mu, const char *mat0, const char *mat1) {
int imat0 = particleProblemGetMaterialTagId(p,mat0);
int imat1 = particleProblemGetMaterialTagId(p,mat1);
int n = particleProblemNMaterial(p);
p->mu[imat0*n+imat1] = p->mu[imat1*n+imat0] = mu;
}
void particleProblemSetBoundaryTangentVelocity(ParticleProblem *p, const char *tag, double v){
......@@ -1181,7 +1193,7 @@ void particleProblemClearParticles(ParticleProblem *p) {
vectorClear(p->velocity);
#ifdef FRICTION_ENABLED
vectorClear(p->omega);
vectorClear(p->particleTag);
vectorClear(p->particleMaterial);
#endif
}
......@@ -1194,7 +1206,7 @@ void particleProblemAddParticles(ParticleProblem *p, int n_particles, double *po
#ifdef FRICTION_ENABLED
vectorPushN(&p->omega,n_particles);
#endif
vectorPushN(&p->particleTag,n_particles);
vectorPushN(&p->particleMaterial,n_particles);
for (int i = 0; i < n_particles; ++i) {
for (int j = 0; j < DIMENSION; ++j) {
p->position[(i+N)*DIMENSION+j] = position[i*DIMENSION+j];
......@@ -1203,9 +1215,9 @@ void particleProblemAddParticles(ParticleProblem *p, int n_particles, double *po
p->particles[i+N].m = mass[i];
p->particles[i+N].r = radius[i];
#ifdef FRICTION_ENABLED
p->omega[i] = omega[i];
p->omega[i+N] = omega[i];
#endif
p->particleTag[i] = tag[i];
p->particleMaterial[i+N] = tag[i];
}
}
......@@ -1232,35 +1244,35 @@ void particleProblemSetContacts(ParticleProblem *p, size_t n, size_t *o, double
}
int *particleProblemDiskTag(ParticleProblem *p) {return p->diskTag;}
int *particleProblemDiskMaterial(ParticleProblem *p) {return p->diskMaterial;}
int *particleProblemSegmentTag(ParticleProblem *p) {return p->segmentTag;};
int *particleProblemParticleTag(ParticleProblem *p) {return p->particleTag;}
int *particleProblemSegmentMaterial(ParticleProblem *p) {return p->segmentMaterial;};
int *particleProblemParticleMaterial(ParticleProblem *p) {return p->particleMaterial;}
#if DIMENSION == 3
int *particleProblemTriangleTag(ParticleProblem *p) {return p->triangleTag;};
int *particleProblemTriangleMaterial(ParticleProblem *p) {return p->triangleMaterial;};
double *particleProblemTriangle(ParticleProblem *p) {return (double*)&p->triangles[0];}
#endif
double *particleProblemVelocity(ParticleProblem *p) {return &p->velocity[0];}
double *particleProblemDisk(ParticleProblem *p) {
#ifdef FRICTION_ENABLED
printf("f\n");
#else
printf("nof\n");
#endif
printf("%i\n", vectorSize(p->disks));
return (double*)&p->disks[0];
}
double *particleProblemSegment(ParticleProblem *p) {return (double*)&p->segments[0];}
double *particleProblemParticle(ParticleProblem *p) {return (double*)&p->particles[0];}
double *particleProblemPosition(ParticleProblem *p){return &p->position[0];}
double *particleProblemExternalForces(ParticleProblem *p){return &p->externalForces[0];}
void particleProblemDelete(ParticleProblem *p) {
vectorFree(p->particles);
vectorFree(p->disks);
vectorFree(p->diskTag);
vectorFree(p->diskMaterial);
vectorFree(p->segments);
vectorFree(p->segmentMaterial);
vectorFree(p->segmentTag);
vectorFree(p->contacts);
vectorFree(p->position);
vectorFree(p->particleTag);
vectorFree(p->particleMaterial);
vectorFree(p->velocity);
vectorFree(p->externalForces);
#ifdef FRICTION_ENABLED
......@@ -1270,10 +1282,14 @@ void particleProblemDelete(ParticleProblem *p) {
#if DIMENSION == 3
vectorFree(p->triangles);
vectorFree(p->triangleTag);
vectorFree(p->triangleMaterial);
#endif
for (size_t i = 0; i < vectorSize(p->tagname); ++i)
free(p->tagname[i]);
vectorFree(p->tagname);
for (size_t i = 0; i < vectorSize(p->materialName); ++i)
free(p->materialName[i]);
vectorFree(p->materialName);
free(p);
}
......@@ -1287,6 +1303,34 @@ size_t particleProblemGetTagId(ParticleProblem *p, const char *tag) {
return vectorSize(p->tagname) - 1;
}
size_t particleProblemGetMaterialTagId(ParticleProblem *p, const char *tag) {
for (size_t i = 0; i < vectorSize(p->materialName); ++i)
if (!strcmp(tag, p->materialName[i]))
return i;
char *dup = malloc(sizeof(char) * (strlen(tag)+1));
strcpy(dup, tag);
*vectorPush(&p->materialName) = dup;
#ifdef FRICTION_ENABLED
int n = vectorSize(p->materialName);
double *oldmu = p->mu;
p->mu = NULL;
vectorPushN(&p->mu, n*n);
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j) {
p->mu[i] = (i==n-1 || j== n-1) ? 0 : oldmu[i*(n-1)+j];
}
}
vectorFree(oldmu);
#endif
return vectorSize(p->materialName) - 1;
}
const char *particleProblemGetMaterialTagName(ParticleProblem *p, size_t id) {
if (id >= vectorSize(p->materialName))
return NULL;
return p->materialName[id];
}
const char *particleProblemGetTagName(ParticleProblem *p, size_t id) {
if (id >= vectorSize(p->tagname))
return NULL;
......@@ -1299,11 +1343,14 @@ ParticleProblem *particleProblemNew() {
p->particles = NULL;
p->contacts = NULL;
p->tagname = NULL;
p->materialName = NULL;
p->disks = NULL;
p->diskTag = NULL;
p->diskMaterial = NULL;
p->segments = NULL;
p->segmentTag = NULL;
p->particleTag = NULL;
p->segmentMaterial = NULL;
p->particleMaterial = NULL;
p->position = NULL;
p->velocity = NULL;
#ifdef FRICTION_ENABLED
......@@ -1315,6 +1362,7 @@ ParticleProblem *particleProblemNew() {
#if DIMENSION == 3
p->triangles = NULL;
p->triangleTag = NULL;
p->segmentMaterial = NULL;
#endif
return p;
}
......@@ -1359,3 +1407,10 @@ void particleProblemSetFrictionRelaxation(ParticleProblem *p, double friction_re
double *particleProblemOmega(ParticleProblem *p) {return &p->omega[0];}
#endif