File: CudaSpringForceField.h

package info (click to toggle)
sofa-framework 1.0~beta4-9
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 88,688 kB
  • ctags: 27,205
  • sloc: cpp: 151,126; ansic: 2,387; xml: 581; sh: 417; makefile: 67
file content (172 lines) | stat: -rw-r--r-- 7,054 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_GPU_CUDA_CUDASPRINGFORCEFIELD_H
#define SOFA_GPU_CUDA_CUDASPRINGFORCEFIELD_H

#include "CudaTypes.h"
#include <sofa/component/forcefield/SpringForceField.h>
#include <sofa/component/forcefield/StiffSpringForceField.h>
#include <sofa/component/forcefield/MeshSpringForceField.h>


namespace sofa
{

namespace gpu
{

namespace cuda
{

template<class DataTypes>
class CudaKernelsSpringForceField;

} // namespace cuda

} // namespace gpu

namespace component
{

namespace forcefield
{

template <class TCoord, class TDeriv, class TReal>
class SpringForceFieldInternalData< gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> >
{
public:
    typedef gpu::cuda::CudaVectorTypes<TCoord,TDeriv,TReal> DataTypes;
    typedef SpringForceField<DataTypes> Main;
    typedef typename Main::Inherit Inherit;
    typedef typename Main::Spring Spring;
    typedef SpringForceFieldInternalData<DataTypes> Data;
    typedef typename DataTypes::VecCoord VecCoord;
    typedef typename DataTypes::VecDeriv VecDeriv;
    typedef typename DataTypes::Coord Coord;
    typedef typename DataTypes::Deriv Deriv;
    typedef typename DataTypes::Real Real;

    typedef gpu::cuda::CudaKernelsSpringForceField<DataTypes> Kernels;

	//enum { BSIZE=16 };
	struct GPUSpring
	{
		int index; ///< 0 if no spring
		//float initpos;
		float ks;
		//float kd;
		GPUSpring() : index(0), /*initpos(0),*/ ks(0)/*, kd(0)*/ {}
		void set(int index, float /*initpos*/, float ks, float /*kd*/)
		{
			this->index = index+1;
			//this->initpos = initpos;
			this->ks = ks;
			//this->kd = kd;
		}
	};
	struct GPUSpring2
	{
		//int index; ///< 0 if no spring
		float initpos;
		//float ks;
		float kd;
		GPUSpring2() : /*index(0),*/ initpos(0), /*ks(0),*/ kd(0) {}
		void set(int /*index*/, float initpos, float /*ks*/, float kd)
		{
			//this->index = index+1;
			this->initpos = initpos;
			//this->ks = ks;
			this->kd = kd;
		}
	};
	struct GPUSpringSet
	{
		int vertex0; ///< index of the first vertex connected to a spring
		int nbVertex; ///< number of vertices to process to compute all springs
		int nbSpringPerVertex; ///< max number of springs connected to a vertex
		gpu::cuda::CudaVector<GPUSpring> springs; ///< springs attached to each points (layout per bloc of NBLOC vertices, with first spring of each vertex, then second spring, etc)
		gpu::cuda::CudaVector<Real> dfdx; ///< only used for StiffSpringForceField
		GPUSpringSet() : vertex0(0), nbVertex(0), nbSpringPerVertex(0) {}
		void init(int v0, int nbv, int nbsperv)
		{
			vertex0 = v0;
			nbVertex = nbv;
			nbSpringPerVertex = nbsperv;
			int nbloc = (nbVertex+BSIZE-1)/BSIZE;
			springs.resize(2*nbloc*nbSpringPerVertex*BSIZE);
		}
		void set(int vertex, int spring, int index, float initpos, float ks, float kd)
		{
			int bloc = vertex/BSIZE;
			int b_x  = vertex%BSIZE;
			springs[ 2*bloc*BSIZE*nbSpringPerVertex // start of the bloc
			       + 2*spring*BSIZE                 // offset to the spring
			       + b_x                          // offset to the vertex
			       ].set(index, initpos, ks, kd);
                        (*(GPUSpring2*)&(springs[ 2*bloc*BSIZE*nbSpringPerVertex // start of the bloc
                                + 2*spring*BSIZE                 // offset to the spring
                                + b_x+BSIZE                    // offset to the vertex
                               ])).set(index, initpos, ks, kd);
                }
	};
	GPUSpringSet springs1; ///< springs from model1 to model2
	GPUSpringSet springs2; ///< springs from model2 to model1 (only used if model1 != model2)

    static void init(Main* m, bool stiff);
    static void addForce(Main* m, bool stiff, VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2);
    static void addDForce (Main* m, bool stiff, VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double bFactor);
};

//
// SpringForceField
//

// I know using macros is bad design but this is the only way not to repeat the code for all CUDA types
#define CudaSpringForceField_DeclMethods(T) \
    template<> void SpringForceField< T >::init(); \
    template<> void SpringForceField< T >::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2); \
    template<> void StiffSpringForceField< T >::init(); \
    template<> void StiffSpringForceField< T >::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2); \
    template<> void StiffSpringForceField< T >::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double bFactor);

CudaSpringForceField_DeclMethods(gpu::cuda::CudaVec3fTypes);
CudaSpringForceField_DeclMethods(gpu::cuda::CudaVec3f1Types);

#ifdef SOFA_GPU_CUDA_DOUBLE

CudaSpringForceField_DeclMethods(gpu::cuda::CudaVec3dTypes);
CudaSpringForceField_DeclMethods(gpu::cuda::CudaVec3d1Types);

#endif // SOFA_GPU_CUDA_DOUBLE

#undef CudaSpringForceField_DeclMethods

} // namespace forcefield

} // namespace component

} // namespace sofa

#endif