DiscreteSystemForceCalculator.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "DiscreteSystemForceCalculator.hpp"
00037
00038 DiscreteSystemForceCalculator::DiscreteSystemForceCalculator(MeshBasedCellPopulation<2>& rCellPopulation,
00039 std::vector<boost::shared_ptr<AbstractTwoBodyInteractionForce<2> > > forceCollection)
00040 : mrCellPopulation(rCellPopulation),
00041 mForceCollection(forceCollection),
00042 mEpsilon(0.01)
00043 {
00044 }
00045
00046 std::vector< std::vector<double> > DiscreteSystemForceCalculator::CalculateExtremalNormalForces()
00047 {
00048 unsigned num_nodes = mrCellPopulation.GetNumNodes();
00049
00050 std::vector< std::vector<double> > extremal_normal_forces;
00051 std::vector<double> minimum_normal_forces(num_nodes);
00052 std::vector<double> maximum_normal_forces(num_nodes);
00053
00054 for (unsigned i=0; i<num_nodes; i++)
00055 {
00056 std::vector<double> sampling_angles = GetSamplingAngles(i);
00057 std::vector<double> extremal_angles = GetExtremalAngles(i, sampling_angles);
00058
00059 double minimum_normal_force_for_node_i = DBL_MAX;
00060 double maximum_normal_force_for_node_i = -DBL_MAX;
00061
00062 for (unsigned j=0; j<extremal_angles.size(); j++)
00063 {
00064 double current_normal_force = CalculateFtAndFn(i, extremal_angles[j])[1];
00065
00066 if (current_normal_force > maximum_normal_force_for_node_i)
00067 {
00068 maximum_normal_force_for_node_i = current_normal_force;
00069 }
00070 if (current_normal_force < minimum_normal_force_for_node_i)
00071 {
00072 minimum_normal_force_for_node_i = current_normal_force;
00073 }
00074 }
00075
00076 assert( minimum_normal_force_for_node_i <= maximum_normal_force_for_node_i);
00077
00078 minimum_normal_forces[i] = minimum_normal_force_for_node_i;
00079 maximum_normal_forces[i] = maximum_normal_force_for_node_i;
00080 }
00081
00082 extremal_normal_forces.push_back(minimum_normal_forces);
00083 extremal_normal_forces.push_back(maximum_normal_forces);
00084
00085 return extremal_normal_forces;
00086 }
00087
00088 void DiscreteSystemForceCalculator::WriteResultsToFile(std::string simulationOutputDirectory)
00089 {
00090 double time = SimulationTime::Instance()->GetTime();
00091 std::ostringstream time_string;
00092 time_string << time;
00093 std::string results_directory = simulationOutputDirectory + "/results_from_time_" + time_string.str();
00094
00095 OutputFileHandler output_file_handler2(results_directory+"/", false);
00096 mpVizStressResultsFile = output_file_handler2.OpenOutputFile("results.vizstress");
00097
00098 (*mpVizStressResultsFile) << time << "\t";
00099
00100 double global_index;
00101 double x;
00102 double y;
00103 double minimum;
00104 double maximum;
00105
00106 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00107
00108 std::vector< std::vector<double> > extremal_normal_forces = CalculateExtremalNormalForces();
00109
00110 for (unsigned i=0; i<r_mesh.GetNumNodes(); i++)
00111 {
00112 global_index = (double) i;
00113
00114 x = r_mesh.GetNode(i)->rGetLocation()[0];
00115 y = r_mesh.GetNode(i)->rGetLocation()[1];
00116
00117 minimum = extremal_normal_forces[0][i];
00118 maximum = extremal_normal_forces[1][i];
00119
00120 (*mpVizStressResultsFile) << global_index << " " << x << " " << y << " " << minimum << " " << maximum << " ";
00121 }
00122
00123 (*mpVizStressResultsFile) << "\n";
00124 mpVizStressResultsFile->close();
00125 }
00126
00127 std::vector<double> DiscreteSystemForceCalculator::CalculateFtAndFn(unsigned index, double theta)
00128 {
00129 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00130
00131 std::set<unsigned> neighbouring_node_indices = mrCellPopulation.GetNeighbouringNodeIndices(index);
00132
00133 double tangential_force = 0.0;
00134 double normal_force = 0.0;
00135 double alpha;
00136
00137 c_vector<double,2> unit_vec_between_nodes(2);
00138
00139 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00140 iter != neighbouring_node_indices.end();
00141 ++iter)
00142 {
00143
00144 alpha = r_mesh.GetAngleBetweenNodes(index, *iter);
00145
00146 assert(alpha <= M_PI);
00147 assert(alpha > -M_PI);
00148
00149 if (sin(alpha-theta) > DBL_EPSILON)
00150 {
00151
00152 c_vector<double,2> force_between_nodes = zero_vector<double>(2);
00153
00154
00155 for (std::vector<boost::shared_ptr<AbstractTwoBodyInteractionForce<2> > >::iterator force_iter = mForceCollection.begin();
00156 force_iter != mForceCollection.end();
00157 ++force_iter)
00158 {
00159 force_between_nodes += (*force_iter)->CalculateForceBetweenNodes(index, *iter, mrCellPopulation);
00160 }
00161
00162 unit_vec_between_nodes[0] = cos(alpha);
00163 unit_vec_between_nodes[1] = sin(alpha);
00164
00165 double plusminus_norm_force = inner_prod(force_between_nodes,unit_vec_between_nodes);
00166 tangential_force += plusminus_norm_force * cos(alpha-theta);
00167 normal_force += plusminus_norm_force * sin(alpha-theta);
00168 }
00169 }
00170
00171 std::vector<double> ret(2);
00172 ret[0] = tangential_force;
00173 ret[1] = normal_force;
00174
00175 return ret;
00176 }
00177
00178 std::vector<double> DiscreteSystemForceCalculator::GetSamplingAngles(unsigned index)
00179 {
00180 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00181
00182 std::set<unsigned> neighbouring_node_indices = mrCellPopulation.GetNeighbouringNodeIndices(index);
00183
00184 std::vector<double> sampling_angles(4*neighbouring_node_indices.size());
00185
00186 unsigned i=0;
00187
00188 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00189 iter != neighbouring_node_indices.end();
00190 ++iter)
00191 {
00192
00193 double alpha = r_mesh.GetAngleBetweenNodes(index, *iter);
00194
00195 double alpha_minus_epsilon = alpha - mEpsilon;
00196 double alpha_plus_epsilon = alpha + mEpsilon;
00197 double alpha_plus_pi_minus_epsilon = alpha + M_PI - mEpsilon;
00198 double alpha_plus_pi_plus_epsilon = alpha + M_PI + mEpsilon;
00199
00200
00201
00202 #define COVERAGE_IGNORE
00203 if (alpha_minus_epsilon <= -M_PI)
00204 {
00205 alpha_minus_epsilon += 2*M_PI;
00206 }
00207 #undef COVERAGE_IGNORE
00208 sampling_angles[i] = alpha_minus_epsilon;
00209
00210 assert(sampling_angles[i] <= M_PI);
00211 assert(sampling_angles[i] > -M_PI);
00212 i++;
00213
00214 if (alpha_plus_epsilon > M_PI)
00215 {
00216 alpha_plus_epsilon -= 2*M_PI;
00217 }
00218 sampling_angles[i] = alpha_plus_epsilon;
00219
00220 assert(sampling_angles[i] <= M_PI);
00221 assert(sampling_angles[i] > -M_PI);
00222 i++;
00223
00224 if (alpha_plus_pi_minus_epsilon > M_PI)
00225 {
00226 alpha_plus_pi_minus_epsilon -= 2*M_PI;
00227 }
00228 sampling_angles[i] = alpha_plus_pi_minus_epsilon;
00229
00230 assert(sampling_angles[i] <= M_PI);
00231 assert(sampling_angles[i] > -M_PI);
00232 i++;
00233
00234 if (alpha_plus_pi_plus_epsilon > M_PI)
00235 {
00236 alpha_plus_pi_plus_epsilon -= 2*M_PI;
00237 }
00238 sampling_angles[i] = alpha_plus_pi_plus_epsilon;
00239
00240 assert(sampling_angles[i] <= M_PI);
00241 assert(sampling_angles[i] > -M_PI);
00242 i++;
00243 }
00244
00245 sort(sampling_angles.begin(), sampling_angles.end());
00246 return sampling_angles;
00247 }
00248
00249 double DiscreteSystemForceCalculator::GetLocalExtremum(unsigned index, double angle1, double angle2)
00250 {
00251
00252
00253 assert(angle1 < angle2);
00254
00255 double tolerance = 1e-5;
00256 unsigned counter = 0;
00257
00258 double previous_angle;
00259 double current_error;
00260 double current_angle = angle1;
00261
00262 current_error = angle2 - angle1;
00263 std::vector<double> current_ft_and_fn(2);
00264
00265 while (current_error > tolerance)
00266 {
00267 previous_angle = current_angle;
00268 current_ft_and_fn = CalculateFtAndFn(index, current_angle);
00269 current_angle -= current_ft_and_fn[0]/current_ft_and_fn[1];
00270 current_error = fabs(current_angle - previous_angle);
00271 counter++;
00272 }
00273
00274 assert(current_angle>angle1 && current_angle<angle2);
00275 assert(current_error < tolerance);
00276
00277 return current_angle;
00278 }
00279
00280 std::vector<double> DiscreteSystemForceCalculator::GetExtremalAngles(unsigned index, std::vector<double> samplingAngles)
00281 {
00282 std::vector<double> extremal_angles;
00283 std::vector<double> ft_and_fn(2);
00284 std::vector<double> tangential_force(samplingAngles.size());
00285
00286 for (unsigned i=0; i<samplingAngles.size(); i++)
00287 {
00288 ft_and_fn = CalculateFtAndFn(index, samplingAngles[i]);
00289 tangential_force[i] = ft_and_fn[0];
00290 }
00291
00292 unsigned n = samplingAngles.size()-1;
00293
00294 for (unsigned i=0; i<n; i++)
00295 {
00296 if ( ( tangential_force[i%n]>0 && tangential_force[(i+1)%n]<0 ) ||
00297 ( tangential_force[i%n]<0 && tangential_force[(i+1)%n]>0 ) )
00298 {
00299 double next_extremal_angle;
00300
00301
00302
00303 if (i==n-1)
00304 {
00305 samplingAngles[i%n] -= 2*M_PI;
00306 }
00307
00308 if (samplingAngles[(i+1)%n] - samplingAngles[i%n] < 2*mEpsilon + 1e-6 )
00309 {
00310
00311
00312 next_extremal_angle = 0.5*(samplingAngles[(i+1)%n] + samplingAngles[i%n]);
00313 }
00314 else
00315 {
00316
00317 next_extremal_angle = GetLocalExtremum(index, samplingAngles[i%n], samplingAngles[(i+1)%n]);
00318 }
00319
00320 if (next_extremal_angle <= -M_PI)
00321 {
00322 next_extremal_angle += 2*M_PI;
00323 }
00324 assert(next_extremal_angle>-M_PI && next_extremal_angle<=M_PI);
00325 extremal_angles.push_back(next_extremal_angle);
00326 }
00327 }
00328
00329 return extremal_angles;
00330 }