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 #include "DiscreteSystemForceCalculator.hpp"
00029
00030 DiscreteSystemForceCalculator::DiscreteSystemForceCalculator(MeshBasedCellPopulation<2>& rCellPopulation,
00031 std::vector<AbstractTwoBodyInteractionForce<2>*> forceCollection)
00032 : mrCellPopulation(rCellPopulation),
00033 mForceCollection(forceCollection),
00034 mEpsilon(0.01)
00035 {
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
00082 void DiscreteSystemForceCalculator::WriteResultsToFile(std::string simulationOutputDirectory)
00083 {
00084 double time = SimulationTime::Instance()->GetTime();
00085 std::ostringstream time_string;
00086 time_string << time;
00087 std::string results_directory = simulationOutputDirectory + "/results_from_time_" + time_string.str();
00088
00089 OutputFileHandler output_file_handler2(results_directory+"/", false);
00090 mpVizStressResultsFile = output_file_handler2.OpenOutputFile("results.vizstress");
00091
00092 (*mpVizStressResultsFile) << time << "\t";
00093
00094 double global_index;
00095 double x;
00096 double y;
00097 double minimum;
00098 double maximum;
00099
00100 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00101
00102 std::vector< std::vector<double> > extremal_normal_forces = CalculateExtremalNormalForces();
00103
00104 for (unsigned i=0; i<r_mesh.GetNumNodes(); i++)
00105 {
00106 global_index = (double) i;
00107
00108 x = r_mesh.GetNode(i)->rGetLocation()[0];
00109 y = r_mesh.GetNode(i)->rGetLocation()[1];
00110
00111 minimum = extremal_normal_forces[0][i];
00112 maximum = extremal_normal_forces[1][i];
00113
00114 (*mpVizStressResultsFile) << global_index << " " << x << " " << y << " " << minimum << " " << maximum << " ";
00115 }
00116
00117 (*mpVizStressResultsFile) << "\n";
00118 mpVizStressResultsFile->close();
00119 }
00120
00121
00122 std::set<unsigned> DiscreteSystemForceCalculator::GetNeighbouringNodeIndices(unsigned index)
00123 {
00124 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00125
00126 Node<2>* p_node = r_mesh.GetNode(index);
00127
00128 std::set<unsigned> neighbouring_node_indices;
00129
00130 for (Node<2>::ContainingElementIterator it = p_node->ContainingElementsBegin();
00131 it != p_node->ContainingElementsEnd();
00132 ++it)
00133 {
00134 Element<2,2>* p_element = r_mesh.GetElement(*it);
00135 for (unsigned i=0; i<p_element->GetNumNodes(); i++)
00136 {
00137 unsigned node_index = p_element->GetNodeGlobalIndex(i);
00138 if (node_index!=index)
00139 {
00140 neighbouring_node_indices.insert(node_index);
00141 }
00142 }
00143 }
00144 return neighbouring_node_indices;
00145 }
00146
00147
00148 std::vector<double> DiscreteSystemForceCalculator::CalculateFtAndFn(unsigned index, double theta)
00149 {
00150 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00151
00152 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(index);
00153
00154 double tangential_force = 0.0;
00155 double normal_force = 0.0;
00156 double alpha;
00157
00158 c_vector<double,2> unit_vec_between_nodes(2);
00159
00160 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00161 iter != neighbouring_node_indices.end();
00162 ++iter)
00163 {
00164
00165 alpha = r_mesh.GetAngleBetweenNodes(index, *iter);
00166
00167 assert(alpha <= M_PI);
00168 assert(alpha > -M_PI);
00169
00170 if ( sin(alpha-theta) > DBL_EPSILON )
00171 {
00172
00173 c_vector<double,2> force_between_nodes = zero_vector<double>(2);
00174
00175
00176 for (std::vector<AbstractTwoBodyInteractionForce<2>*>::iterator force_iter = mForceCollection.begin();
00177 force_iter != mForceCollection.end();
00178 ++force_iter)
00179 {
00180 force_between_nodes += (*force_iter)->CalculateForceBetweenNodes(index, *iter, mrCellPopulation);
00181 }
00182
00183 unit_vec_between_nodes[0] = cos(alpha);
00184 unit_vec_between_nodes[1] = sin(alpha);
00185
00186 double plusminus_norm_force = inner_prod(force_between_nodes,unit_vec_between_nodes);
00187 tangential_force += plusminus_norm_force * cos(alpha-theta);
00188 normal_force += plusminus_norm_force * sin(alpha-theta);
00189 }
00190 }
00191
00192 std::vector<double> ret(2);
00193 ret[0] = tangential_force;
00194 ret[1] = normal_force;
00195
00196 return ret;
00197 }
00198
00199
00200 std::vector<double> DiscreteSystemForceCalculator::GetSamplingAngles(unsigned index)
00201 {
00202 TetrahedralMesh<2,2>& r_mesh = mrCellPopulation.rGetMesh();
00203
00204 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(index);
00205
00206 std::vector<double> sampling_angles(4*neighbouring_node_indices.size());
00207
00208 unsigned i=0;
00209
00210 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00211 iter != neighbouring_node_indices.end();
00212 ++iter)
00213 {
00214
00215 double alpha = r_mesh.GetAngleBetweenNodes(index, *iter);
00216
00217 double alpha_minus_epsilon = alpha - mEpsilon;
00218 double alpha_plus_epsilon = alpha + mEpsilon;
00219 double alpha_plus_pi_minus_epsilon = alpha + M_PI - mEpsilon;
00220 double alpha_plus_pi_plus_epsilon = alpha + M_PI + mEpsilon;
00221
00222
00223
00224 #define COVERAGE_IGNORE
00225 if (alpha_minus_epsilon <= -M_PI)
00226 {
00227 alpha_minus_epsilon += 2*M_PI;
00228 }
00229 #undef COVERAGE_IGNORE
00230 sampling_angles[i] = alpha_minus_epsilon;
00231
00232 assert(sampling_angles[i] <= M_PI);
00233 assert(sampling_angles[i] > -M_PI);
00234 i++;
00235
00236 if (alpha_plus_epsilon > M_PI)
00237 {
00238 alpha_plus_epsilon -= 2*M_PI;
00239 }
00240 sampling_angles[i] = alpha_plus_epsilon;
00241
00242 assert(sampling_angles[i] <= M_PI);
00243 assert(sampling_angles[i] > -M_PI);
00244 i++;
00245
00246 if (alpha_plus_pi_minus_epsilon > M_PI)
00247 {
00248 alpha_plus_pi_minus_epsilon -= 2*M_PI;
00249 }
00250 sampling_angles[i] = alpha_plus_pi_minus_epsilon;
00251
00252 assert(sampling_angles[i] <= M_PI);
00253 assert(sampling_angles[i] > -M_PI);
00254 i++;
00255
00256 if (alpha_plus_pi_plus_epsilon > M_PI)
00257 {
00258 alpha_plus_pi_plus_epsilon -= 2*M_PI;
00259 }
00260 sampling_angles[i] = alpha_plus_pi_plus_epsilon;
00261
00262 assert(sampling_angles[i] <= M_PI);
00263 assert(sampling_angles[i] > -M_PI);
00264 i++;
00265 }
00266
00267 sort(sampling_angles.begin(), sampling_angles.end());
00268 return sampling_angles;
00269 }
00270
00271
00272 double DiscreteSystemForceCalculator::GetLocalExtremum(unsigned index, double angle1, double angle2)
00273 {
00274
00275
00276 assert(angle1 < angle2);
00277
00278 double tolerance = 1e-5;
00279 unsigned counter = 0;
00280
00281 double previous_angle;
00282 double current_error;
00283 double current_angle = angle1;
00284
00285 current_error = angle2 - angle1;
00286 std::vector<double> current_ft_and_fn(2);
00287
00288 while (current_error > tolerance)
00289 {
00290 previous_angle = current_angle;
00291 current_ft_and_fn = CalculateFtAndFn(index, current_angle);
00292 current_angle -= current_ft_and_fn[0]/current_ft_and_fn[1];
00293 current_error = fabs(current_angle - previous_angle);
00294 counter++;
00295 }
00296
00297 assert(current_angle>angle1 && current_angle<angle2);
00298 assert(current_error < tolerance);
00299
00300 return current_angle;
00301 }
00302
00303
00304 std::vector<double> DiscreteSystemForceCalculator::GetExtremalAngles(unsigned index, std::vector<double> samplingAngles)
00305 {
00306 std::vector<double> extremal_angles;
00307 std::vector<double> ft_and_fn(2);
00308 std::vector<double> tangential_force(samplingAngles.size());
00309
00310 for (unsigned i=0; i<samplingAngles.size(); i++)
00311 {
00312 ft_and_fn = CalculateFtAndFn(index, samplingAngles[i]);
00313 tangential_force[i] = ft_and_fn[0];
00314 }
00315
00316 unsigned n = samplingAngles.size()-1;
00317
00318 for (unsigned i=0; i<n; i++)
00319 {
00320 if ( ( tangential_force[i%n]>0 && tangential_force[(i+1)%n]<0 ) ||
00321 ( tangential_force[i%n]<0 && tangential_force[(i+1)%n]>0 ) )
00322 {
00323 double next_extremal_angle;
00324
00325
00326
00327 if (i==n-1)
00328 {
00329 samplingAngles[i%n] -= 2*M_PI;
00330 }
00331
00332 if (samplingAngles[(i+1)%n] - samplingAngles[i%n] < 2*mEpsilon + 1e-6 )
00333 {
00334
00335
00336 next_extremal_angle = 0.5*(samplingAngles[(i+1)%n] + samplingAngles[i%n]);
00337 }
00338 else
00339 {
00340
00341 next_extremal_angle = GetLocalExtremum(index, samplingAngles[i%n], samplingAngles[(i+1)%n]);
00342 }
00343
00344 if (next_extremal_angle <= -M_PI)
00345 {
00346 next_extremal_angle += 2*M_PI;
00347 }
00348 assert(next_extremal_angle>-M_PI && next_extremal_angle<=M_PI);
00349 extremal_angles.push_back(next_extremal_angle);
00350 }
00351 }
00352
00353 return extremal_angles;
00354 }