public void TransferUpdatedStateToHost() { if (cz_stride != 0) { // transfer to host dcz and icz g_dcz.CopyToHost(c_dcz, 0, 0, sizeof(double) * cz_stride * FP_DATA_SIZE_CZ); // pmax, tmax g_icz.CopyToHost(c_icz, 0, 0, sizeof(int) * cz_stride * 4); // cz_failed // infer failed state, pmax[] and tmax[] Parallel.For(0, mc.nonFailedCZs.Length, i => { CZ cz = mc.nonFailedCZs[i]; if (!cz.failed) { bool tentative_fail = c_icz[i + cz_stride * (TENTATIVE_FAILED_OFFSET_CZ)] == 0 ? false : true; if (tentative_fail) { cz.failed = true; } for (int j = 0; j < 3; j++) { cz.pmax[j] = c_dcz[i + cz_stride * (TENTATIVE_PMAX_OFFSET_CZ + j)]; cz.tmax[j] = c_dcz[i + cz_stride * (TENTATIVE_TMAX_OFFSET_CZ + j)]; } cz.avgDn = c_dcz[i + cz_stride * DELTA_N_OFFSET_CZ]; cz.avgDt = c_dcz[i + cz_stride * DELTA_T_OFFSET_CZ]; cz.avgTn = c_dcz[i + cz_stride * T_N_OFFSET_CZ]; cz.avgTt = c_dcz[i + cz_stride * T_T_OFFSET_CZ]; if (cz.maxAvgDn < cz.avgDn) { cz.maxAvgDn = cz.avgDn; } if (cz.maxAvgDt < cz.avgDt) { cz.maxAvgDt = cz.avgDt; } } }); } // copy back elastic forces (should be zero on rigid objects) g_dn.CopyToHost(c_dn, sizeof(double) * nd_stride * F_OFFSET, sizeof(double) * nd_stride * F_OFFSET, sizeof(double) * nd_stride * 3); Parallel.For(0, mc.allNodes.Length, i => { Node nd = mc.allNodes[i]; nd.fx = c_dn[i + nd_stride * (F_OFFSET + 0)]; nd.fy = c_dn[i + nd_stride * (F_OFFSET + 1)]; nd.fz = c_dn[i + nd_stride * (F_OFFSET + 2)]; }); }
public static void ConvertBack(this Mesh mg) { // Nodes, Faces, Elements and CZs are converted from Extended to normal for (int i = 0; i < mg.nodes.Count; i++) { mg.nodes[i] = new Node(mg.nodes[i]); } for (int i = 0; i < mg.elems.Count; i++) { Element old_elem = mg.elems[i]; old_elem.id = i; Element new_elem = new Element(); for (int j = 0; j < 4; j++) { new_elem.vrts[j] = mg.nodes[old_elem.vrts[j].id]; } new_elem.granule = old_elem.granule; mg.elems[i] = new_elem; } for (int i = 0; i < mg.faces.Count; i++) { Face old_fc = mg.faces[i]; old_fc.id = i; Face new_fc = new Face(); if (old_fc.elem != null) { new_fc.elem = mg.elems[old_fc.elem.id]; } new_fc.id = i; new_fc.tag = old_fc.tag; new_fc.granule = old_fc.granule; new_fc.exposed = old_fc.exposed; for (int j = 0; j < 3; j++) { new_fc.vrts[j] = mg.nodes[old_fc.vrts[j].id]; } mg.faces[i] = new_fc; } for (int i = 0; i < mg.czs.Count; i++) { CZ old_cz = mg.czs[i]; CZ new_cz = new CZ(); for (int j = 0; j < 6; j++) { new_cz.vrts[j] = mg.nodes[old_cz.vrts[j].id]; } for (int j = 0; j < 2; j++) { new_cz.faces[j] = mg.faces[old_cz.faces[j].id]; } mg.czs[i] = new_cz; } // grain edges for (int i = 0; i < mg.edges.Count; i++) { GranuleEdge ge = mg.edges[i]; ge.vrts[0] = mg.nodes[ge.vrts[0].id]; ge.vrts[1] = mg.nodes[ge.vrts[1].id]; } }
// loads from proprietary binary format public void LoadFrame(Stream str, bool update = false) { BinaryReader br = new BinaryReader(str); // read properties isDeformable = br.ReadBoolean(); isIndenter = br.ReadBoolean(); isFloor = br.ReadBoolean(); bool _hide = br.ReadBoolean(); // discard name = br.ReadString(); int nNodes = br.ReadInt32(); int nElems = br.ReadInt32(); int nCZs = br.ReadInt32(); int nFaces = br.ReadInt32(); int nEdges = br.ReadInt32(); // make sure that List<> objects are filled with proper # of elements if (!update) { nodes.Clear(); nodes.Capacity = nNodes; for (int i = 0; i < nNodes; i++) { nodes.Add(new Node()); } elems.Clear(); elems.Capacity = nElems; for (int i = 0; i < nElems; i++) { elems.Add(new Element()); } czs.Clear(); czs.Capacity = nCZs; for (int i = 0; i < nCZs; i++) { czs.Add(new CZ()); } faces.Clear(); faces.Capacity = nFaces; for (int i = 0; i < nFaces; i++) { faces.Add(new Face()); } edges.Clear(); edges.Capacity = nEdges; for (int i = 0; i < nEdges; i++) { edges.Add(new GranuleEdge()); } } else { // Debug.Assert(nNodes == nodes.Count && nElems == elems.Count && nCZs == czs.Count && // nFaces == faces.Count && nEdges == edges.Count, "mesh update: incorrect count"); Debug.Assert(nNodes == nodes.Count, "mesh update: incorrect node count"); Debug.Assert(nElems == elems.Count, "mesh update: incorrect element count"); Debug.Assert(nFaces == faces.Count, "mesh update: incorrect face count"); Debug.Assert(nEdges == edges.Count, "mesh update: incorrect edge count"); Debug.Assert(nCZs == czs.Count, "mesh update: incorrect czs count"); } LoadSaveMemAlloc(); by_snapshot = br.ReadBytes(byteSize); // convert byte array to bool, int and double arrays Buffer.BlockCopy(by_snapshot, 0, isn, 0, iSize * sizeof(int)); int offset = iSize * sizeof(int); Buffer.BlockCopy(by_snapshot, offset, bsn, 0, bSize * sizeof(bool)); offset += bSize * sizeof(bool); Buffer.BlockCopy(by_snapshot, offset, dsn, 0, dSize * sizeof(double)); // restore nodes int i_off = 0, d_off = 0, b_off = 0; Parallel.For(0, nNodes, i => { Node nd = nodes[i]; nd.id = i; nd.x0 = dsn[i * ndd_str + 0]; nd.y0 = dsn[i * ndd_str + 1]; nd.z0 = dsn[i * ndd_str + 2]; nd.ux = dsn[i * ndd_str + 3]; nd.uy = dsn[i * ndd_str + 4]; nd.uz = dsn[i * ndd_str + 5]; nd.vx = dsn[i * ndd_str + 6]; nd.vy = dsn[i * ndd_str + 7]; nd.vz = dsn[i * ndd_str + 8]; nd.ax = dsn[i * ndd_str + 9]; nd.ay = dsn[i * ndd_str + 10]; nd.az = dsn[i * ndd_str + 11]; nd.fx = nd.fy = nd.fz = 0; nd.cx = nd.x0 + nd.ux; nd.cy = nd.y0 + nd.uy; nd.cz = nd.z0 + nd.uz; nd.tx = nd.ty = nd.tz = nd.unx = nd.uny = nd.unz = 0; }); d_off += ndd_str * nodes.Count; // elements Parallel.For(0, nElems, i => { Element elem = elems[i]; for (int j = 0; j < 4; j++) { elem.vrts[j] = nodes[isn[i * eli_str + j]]; } elem.granule = isn[i * eli_str + 4]; }); i_off += eli_str * elems.Count; // cohesive zones Parallel.For(0, nCZs, i => { CZ cz = czs[i]; for (int j = 0; j < 6; j++) { cz.vrts[j] = nodes[isn[i_off + i * czi_str + j]]; } cz.faces[0] = faces[isn[i_off + i * czi_str + 6]]; cz.faces[1] = faces[isn[i_off + i * czi_str + 7]]; cz.immutableID = isn[i_off + i * czi_str + 8]; cz.pmax[0] = dsn[d_off + i * czd_str + 0]; cz.pmax[1] = dsn[d_off + i * czd_str + 1]; cz.pmax[2] = dsn[d_off + i * czd_str + 2]; cz.tmax[0] = dsn[d_off + i * czd_str + 3]; cz.tmax[1] = dsn[d_off + i * czd_str + 4]; cz.tmax[2] = dsn[d_off + i * czd_str + 5]; cz.avgDn = dsn[d_off + i * czd_str + 6]; cz.avgDt = dsn[d_off + i * czd_str + 7]; cz.avgTn = dsn[d_off + i * czd_str + 8]; cz.avgTt = dsn[d_off + i * czd_str + 9]; cz.maxAvgDn = dsn[d_off + i * czd_str + 10]; cz.maxAvgDt = dsn[d_off + i * czd_str + 11]; cz.failed = bsn[b_off + i + 0]; }); b_off += czb_str * czs.Count; i_off += czi_str * czs.Count; d_off += czd_str * czs.Count; // faces Parallel.For(0, nFaces, i => { Face f = faces[i]; f.id = i; for (int j = 0; j < 3; j++) { f.vrts[j] = nodes[isn[i_off + i * fi_str + j]]; } f.granule = isn[i_off + i * fi_str + 3]; f.exposed = bsn[b_off + i * fb_str + 0]; f.created = bsn[b_off + i * fb_str + 1]; int elem_id = isn[i_off + i * fi_str + 4]; f.elem = elem_id < 0 ? null : elems[elem_id]; }); b_off += fb_str * faces.Count; i_off += fi_str * faces.Count; // edges Parallel.For(0, nEdges, i => { GranuleEdge ge = edges[i]; ge.vrts[0] = nodes[isn[i_off + i * gei_str + 0]]; ge.vrts[1] = nodes[isn[i_off + i * gei_str + 1]]; ge.exposed = bsn[b_off + i]; }); if (!update) { BoundingBox(); ComputeVolume(); } IFormatter bf = new BinaryFormatter(); surfaceFragments = (List <SurfaceFragment>)bf.Deserialize(str); object tcollObject = bf.Deserialize(str); translationCollection = (TranslationCollection)tcollObject; foreach (SurfaceFragment sf in surfaceFragments) { sf.allFaces = faces; sf.ComputeArea(); } }
public void TransferPCSR() { CSRDictionary csrd = linearSystem.csrd; // tranfer elastic elems and CZs along with offsets in sparse matrix (where to write the result) sw.Restart(); // elastic elements Parallel.For(0, mc.elasticElements.Length, i_elem => { Element elem = mc.elasticElements[i_elem]; for (int i = 0; i < 4; i++) { Node ni = elem.vrts[i]; for (int j = 0; j < 4; j++) { int pcsr_ij; Node nj = elem.vrts[j]; if (!ni.anchored && !nj.anchored && nj.altId >= ni.altId) { pcsr_ij = csrd[ni.altId, nj.altId]; } else { pcsr_ij = -1; // ni is anchored => ignore } c_ie_pcsr[i_elem + el_elastic_stride * (PCSR_OFFSET_ELEM + (i * 4 + j))] = pcsr_ij; } c_ie_pcsr[i_elem + el_elastic_stride * (PCSR_OFFSET_ELEM + 16 + i)] = ni.anchored ? -1 : ni.altId; c_ie_pcsr[i_elem + el_elastic_stride * (N0_OFFSET_ELEM + i)] = ni.globalNodeId; // c_ie_pcsr[i_elem + el_elastic_stride * (ROWSIZE_OFFSET_ELEM + i)] = ni.allNeighbors.Count; } }); g_ie_pcsr.CopyToDevice(c_ie_pcsr, 0, 0, el_elastic_stride * INT_DATA_SIZE_ELEM * sizeof(int)); // initialize indices in cohesive zones cz_stride = grid(mc.nonFailedCZs.Length) * block_size; if (cz_stride != 0) { Array.Clear(c_dcz, 0, c_dcz.Length); Parallel.For(0, mc.nonFailedCZs.Length, i_cz => { CZ cz = mc.nonFailedCZs[i_cz]; Trace.Assert(!cz.failed, "failed CZ in GPU array"); c_icz[i_cz + cz_stride * (CURRENT_FAILED_OFFSET_CZ)] = 0; c_icz[i_cz + cz_stride * (TENTATIVE_FAILED_OFFSET_CZ)] = 0; c_icz[i_cz + cz_stride * (TENTATIVE_DAMAGED_OFFSET_CZ)] = 0; for (int i = 0; i < 6; i++) { Node ni = cz.vrts[i]; for (int j = 0; j < 6; j++) { Node nj = cz.vrts[j]; int pcsr_ij; if (!ni.anchored && !nj.anchored && nj.altId >= ni.altId) { pcsr_ij = csrd[ni.altId, nj.altId]; } else { pcsr_ij = -1; // ni is anchored => ignore } c_icz[i_cz + cz_stride * (PCSR_OFFSET_CZ + (i * 6 + j))] = pcsr_ij; } c_icz[i_cz + cz_stride * (PCSR_OFFSET_CZ + 36 + i)] = ni.anchored ? -1 : ni.altId; c_icz[i_cz + cz_stride * (VRTS_OFFSET_CZ + i)] = ni.globalNodeId; // c_icz[i_cz + cz_stride * (ROWSIZE_OFFSET_CZ + i)] = ni.allNeighbors.Count; } for (int j = 0; j < 3; j++) { c_dcz[i_cz + cz_stride * (CURRENT_PMAX_OFFSET_CZ + j)] = cz.pmax[j]; c_dcz[i_cz + cz_stride * (CURRENT_TMAX_OFFSET_CZ + j)] = cz.tmax[j]; } }); g_icz.CopyToDevice(c_icz, 0, 0, cz_stride * sizeof(int) * INT_DATA_SIZE_CZ); g_dcz.CopyToDevice(c_dcz, 0, 0, cz_stride * sizeof(double) * FP_DATA_SIZE_CZ); } sw.Stop(); cf.KForcePrepare += sw.ElapsedMilliseconds; }
public void SaveFrame(BinaryWriter bw) { LoadSaveMemAlloc(); // write nodes int i_off = 0, d_off = 0, b_off = 0; Parallel.For(0, nodes.Count, i => { Node nd = nodes[i]; Debug.Assert(nd.id == i, "Node ids are not sequential"); dsn[i * ndd_str + 0] = nd.x0; dsn[i * ndd_str + 1] = nd.y0; dsn[i * ndd_str + 2] = nd.z0; dsn[i * ndd_str + 3] = nd.ux; dsn[i * ndd_str + 4] = nd.uy; dsn[i * ndd_str + 5] = nd.uz; dsn[i * ndd_str + 6] = nd.vx; dsn[i * ndd_str + 7] = nd.vy; dsn[i * ndd_str + 8] = nd.vz; dsn[i * ndd_str + 9] = nd.ax; dsn[i * ndd_str + 10] = nd.ay; dsn[i * ndd_str + 11] = nd.az; }); d_off += ndd_str * nodes.Count; // elements Parallel.For(0, elems.Count, i => { Element elem = elems[i]; elem.id = i; isn[i * eli_str + 0] = elem.vrts[0].id; isn[i * eli_str + 1] = elem.vrts[1].id; isn[i * eli_str + 2] = elem.vrts[2].id; isn[i * eli_str + 3] = elem.vrts[3].id; isn[i * eli_str + 4] = elem.granule; }); i_off += eli_str * elems.Count; // cohesive zones Parallel.For(0, czs.Count, i => { CZ cz = czs[i]; isn[i_off + i * czi_str + 0] = cz.vrts[0].id; isn[i_off + i * czi_str + 1] = cz.vrts[1].id; isn[i_off + i * czi_str + 2] = cz.vrts[2].id; isn[i_off + i * czi_str + 3] = cz.vrts[3].id; isn[i_off + i * czi_str + 4] = cz.vrts[4].id; isn[i_off + i * czi_str + 5] = cz.vrts[5].id; isn[i_off + i * czi_str + 6] = cz.faces[0].id; isn[i_off + i * czi_str + 7] = cz.faces[1].id; isn[i_off + i * czi_str + 8] = cz.immutableID; dsn[d_off + i * czd_str + 0] = cz.pmax[0]; dsn[d_off + i * czd_str + 1] = cz.pmax[1]; dsn[d_off + i * czd_str + 2] = cz.pmax[2]; dsn[d_off + i * czd_str + 3] = cz.tmax[0]; dsn[d_off + i * czd_str + 4] = cz.tmax[1]; dsn[d_off + i * czd_str + 5] = cz.tmax[2]; dsn[d_off + i * czd_str + 6] = cz.avgDn; dsn[d_off + i * czd_str + 7] = cz.avgDt; dsn[d_off + i * czd_str + 8] = cz.avgTn; dsn[d_off + i * czd_str + 9] = cz.avgTt; dsn[d_off + i * czd_str + 10] = cz.maxAvgDn; dsn[d_off + i * czd_str + 11] = cz.maxAvgDt; bsn[b_off + i + 0] = cz.failed; }); b_off += czb_str * czs.Count; i_off += czi_str * czs.Count; d_off += czd_str * czs.Count; // faces Parallel.For(0, faces.Count, i => { Face f = faces[i]; isn[i_off + i * fi_str + 0] = f.vrts[0].id; isn[i_off + i * fi_str + 1] = f.vrts[1].id; isn[i_off + i * fi_str + 2] = f.vrts[2].id; isn[i_off + i * fi_str + 3] = f.granule; isn[i_off + i * fi_str + 4] = f.elem == null ? -1 : f.elem.id; bsn[b_off + i * fb_str + 0] = f.exposed; bsn[b_off + i * fb_str + 1] = f.created; }); b_off += fb_str * faces.Count; i_off += fi_str * faces.Count; // edges Parallel.For(0, edges.Count, i => { GranuleEdge ge = edges[i]; isn[i_off + i * gei_str + 0] = ge.vrts[0].id; isn[i_off + i * gei_str + 1] = ge.vrts[1].id; bsn[b_off + i] = ge.exposed; }); // convert to byte array and write if (by_snapshot == null || by_snapshot.Length < byteSize) { by_snapshot = new byte[byteSize]; } Buffer.BlockCopy(isn, 0, by_snapshot, 0, iSize * sizeof(int)); int offset = iSize * sizeof(int); Buffer.BlockCopy(bsn, 0, by_snapshot, offset, bSize * sizeof(bool)); offset += bSize * sizeof(bool); Buffer.BlockCopy(dsn, 0, by_snapshot, offset, dSize * sizeof(double)); // save mesh properties bw.Write(isDeformable); bw.Write(isIndenter); bw.Write(isFloor); bw.Write(hide); bw.Write(name); bw.Write(nodes.Count); bw.Write(elems.Count); bw.Write(czs.Count); bw.Write(faces.Count); bw.Write(edges.Count); bw.Write(by_snapshot, 0, byteSize); bw.Flush(); IFormatter bf = new BinaryFormatter(); bf.Serialize(bw.BaseStream, surfaceFragments); bf.Serialize(bw.BaseStream, translationCollection); bw.Flush(); }