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